From 027e104e8a90225c193ffbee7c6c4c704d9f488d Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Mon, 31 Mar 2025 10:49:11 +0000 Subject: [PATCH] Library --- .docker/docker-compose.yml | 151 +- .docs/.openapi/api-analyse.yaml | 40 +- .docs/.openapi/api-dashboard.yaml | 1 + .docs/.openapi/api-data.yaml | 419 +- .docs/.openapi/api-metadata.yaml | 875 ++-- .docs/.openapi/api-search.yaml | 21 +- .docs/.openapi/api.base.yaml | 4 +- .docs/.openapi/api.yaml | 176 +- .docs/.openapi/openapi-generate.sh | 7 +- .docs/api/broker-service.md | 3 - .docs/api/dashboard-service.md | 51 - .docs/api/data-service.md | 7 + .docs/api/ui.md | 5 - .docs/changelog.md | 9 + .docs/concepts/dashboards.md | 27 + .docs/concepts/data-versioning.md | 37 +- .docs/concepts/data-visibility.md | 20 +- .docs/concepts/ui.md | 21 - .docs/images/architecture.drawio | 28 +- .docs/images/data-versioning.png | Bin 0 -> 45988 bytes .../images/screenshots/dashboard-managed.png | Bin 0 -> 115429 bytes .docs/index.md | 12 +- .docs/kubernetes.md | 2 +- .gitignore | 2 + .gitlab-ci.yml | 150 +- .scripts/check-service.sh | 1 + Makefile | 4 +- dbrepo-analyse-service/.gitignore | 1 + dbrepo-analyse-service/Dockerfile | 11 +- dbrepo-analyse-service/Pipfile | 4 +- dbrepo-analyse-service/Pipfile.lock | 1014 ++--- dbrepo-analyse-service/app.py | 65 +- .../clients/keycloak_client.py | 37 - dbrepo-analyse-service/determine_dt.py | 28 +- dbrepo-analyse-service/determine_pk.py | 18 +- .../lib/dbrepo-1.7.3-py3-none-any.whl | Bin 32568 -> 0 bytes .../lib/dbrepo-1.7.3.tar.gz | Bin 49697 -> 0 bytes .../lib/dbrepo-1.8.0-py3-none-any.whl | Bin 0 -> 88162 bytes .../lib/dbrepo-1.8.0.tar.gz | Bin 0 -> 97755 bytes dbrepo-analyse-service/tests/conftest.py | 2 +- dbrepo-analyse-service/tests/s3_config.json | 20 - .../tests/test_determine_dt.py | 47 +- .../tests/test_determine_pk.py | 52 +- dbrepo-auth-service/init/.coveragerc | 2 - dbrepo-auth-service/init/app.py | 30 +- .../init/tests/test_unit_app.py | 18 +- .../target/create-event-listener.jar | Bin 10141 -> 10141 bytes dbrepo-dashboard-service/.coveragerc | 7 + dbrepo-dashboard-service/.gitignore | 135 + dbrepo-dashboard-service/Dockerfile | 29 +- dbrepo-dashboard-service/Pipfile | 28 + dbrepo-dashboard-service/Pipfile.lock | 2224 ++++++++++ dbrepo-dashboard-service/README.md | 14 + dbrepo-dashboard-service/access.py | 30 - dbrepo-dashboard-service/app.py | 237 + .../clients/grafana_client.py | 27 - .../clients/keycloak_client.py | 35 - dbrepo-dashboard-service/dashboard.py | 344 -- .../ds-yml/create_dashboard.yml | 55 + .../ds-yml/update_dashboard.yml | 43 + dbrepo-dashboard-service/init/.coveragerc | 7 + dbrepo-dashboard-service/init/Dockerfile | 25 + dbrepo-dashboard-service/init/Pipfile | 27 + dbrepo-dashboard-service/init/Pipfile.lock | 2094 +++++++++ dbrepo-dashboard-service/init/app.py | 66 + .../init/lib/dbrepo-1.8.0-py3-none-any.whl | Bin 0 -> 88162 bytes .../init/lib/dbrepo-1.8.0.tar.gz | Bin 0 -> 97755 bytes .../init/tests/rsa/rs256.key | 0 .../init/tests/rsa/rsa256.pkey | 0 .../init/tests/test_app.py | 100 + .../lib/dbrepo-1.8.0-py3-none-any.whl | Bin 0 -> 88162 bytes .../lib/dbrepo-1.8.0.tar.gz | Bin 0 -> 97755 bytes dbrepo-dashboard-service/panel.py | 252 -- dbrepo-dashboard-service/test.sh | 7 + dbrepo-dashboard-service/tests/conftest.py | 48 + .../tests/grafana/__init__.py | 28 + dbrepo-dashboard-service/tests/rsa/rs256.key | 3 + .../tests/rsa/rsa256.pkey | 3 + .../tests/test_integration_app.py | 208 + dbrepo-dashboard-ui/Dockerfile | 9 + .../dashboards/System/dbrepo.json | 122 +- .../dashboards/System}/rabbitmq.json | 6 +- .../grafana.ini | 1 - .../ldap.toml | 8 +- .../provisioning/dashboards/provider.yaml | 20 + .../provisioning/datasources/infinity.yaml | 17 + .../provisioning/datasources/prometheus.yaml | 7 + dbrepo-data-service/Dockerfile | 6 +- dbrepo-data-service/pom.xml | 93 +- dbrepo-data-service/querystore/pom.xml | 4 +- dbrepo-data-service/report/pom.xml | 4 +- dbrepo-data-service/rest-service/pom.xml | 6 +- .../at/tuwien/endpoints/AccessEndpoint.java | 10 +- .../at/tuwien/endpoints/DatabaseEndpoint.java | 15 +- .../at/tuwien/endpoints/RestEndpoint.java | 2 +- .../at/tuwien/endpoints/SubsetEndpoint.java | 18 +- .../at/tuwien/endpoints/TableEndpoint.java | 23 +- .../at/tuwien/endpoints/UploadEndpoint.java | 8 +- .../at/tuwien/endpoints/ViewEndpoint.java | 62 +- .../tuwien/handlers/ApiExceptionHandler.java | 18 +- .../tuwien/validation/EndpointValidator.java | 14 +- .../src/main/resources/application.yml | 11 +- .../java/at/tuwien/config/MariaDbConfig.java | 6 +- .../tuwien/config/MariaDbContainerConfig.java | 10 +- .../endpoint/AccessEndpointUnitTest.java | 18 +- .../endpoint/DatabaseEndpointUnitTest.java | 26 +- .../endpoint/SubsetEndpointUnitTest.java | 22 +- .../endpoint/TableEndpointUnitTest.java | 54 +- .../tuwien/endpoint/ViewEndpointUnitTest.java | 16 +- .../tuwien/gateway/InterceptorUnitTest.java | 13 +- .../MetadataServiceGatewayUnitTest.java | 30 +- .../handlers/ApiExceptionHandlerTest.java | 12 +- .../DefaultListenerIntegrationTest.java | 31 +- .../listener/DefaultListenerUnitTest.java | 85 +- .../tuwien/mapper/MariaDbMapperUnitTest.java | 6 +- .../tuwien/mvc/ActuatorEndpointMvcTest.java | 4 +- .../at/tuwien/mvc/OpenApiEndpointMvcTest.java | 11 +- .../tuwien/mvc/PrometheusEndpointMvcTest.java | 14 +- .../at/tuwien/mvc/SubsetEndpointMvcTest.java | 4 +- .../service/AccessServiceIntegrationTest.java | 11 +- .../ContainerServiceIntegrationTest.java | 21 +- .../service/CredentialServiceUnitTest.java | 19 +- .../DatabaseServiceIntegrationTest.java | 63 +- .../service/QueueServiceIntegrationTest.java | 15 +- .../StorageServiceIntegrationTest.java | 15 +- .../service/SubsetServiceIntegrationTest.java | 13 +- .../service/TableServiceIntegrationTest.java | 49 +- .../service/ViewServiceIntegrationTest.java | 9 +- .../java/at/tuwien/utils/MariaDbUtilTest.java | 2 +- .../validation/EndpointValidatorUnitTest.java | 6 +- dbrepo-data-service/services/pom.xml | 6 +- .../java/at/tuwien/auth/AuthTokenFilter.java | 4 +- .../auth/BasicAuthenticationProvider.java | 3 +- .../auth/InternalRequestInterceptor.java | 2 +- .../java/at/tuwien/config/CacheConfig.java | 20 +- .../at/tuwien/gateway/KeycloakGateway.java | 10 +- .../gateway/MetadataServiceGateway.java | 18 +- .../gateway/impl/KeycloakGatewayImpl.java | 2 +- .../impl/MetadataServiceGatewayImpl.java | 20 +- .../at/tuwien/listener/DefaultListener.java | 12 +- .../java/at/tuwien/mapper/DataMapper.java | 38 +- .../java/at/tuwien/mapper/MariaDbMapper.java | 36 +- .../java/at/tuwien/mapper/MetadataMapper.java | 37 +- .../java/at/tuwien/service/AccessService.java | 8 +- .../java/at/tuwien/service/CacheService.java | 31 +- .../at/tuwien/service/ContainerService.java | 10 +- .../at/tuwien/service/CredentialService.java | 2 +- .../at/tuwien/service/DatabaseService.java | 12 +- .../java/at/tuwien/service/QueueService.java | 4 +- .../at/tuwien/service/StorageService.java | 10 +- .../java/at/tuwien/service/SubsetService.java | 8 +- .../java/at/tuwien/service/TableService.java | 18 +- .../java/at/tuwien/service/ViewService.java | 8 +- .../impl/AccessServiceMariaDbImpl.java | 12 +- .../tuwien/service/impl/CacheServiceImpl.java | 42 +- .../impl/ContainerServiceMariaDbImpl.java | 12 +- .../service/impl/CredentialServiceImpl.java | 16 +- .../at/tuwien/service/impl/DataConnector.java | 4 +- .../impl/DatabaseServiceMariaDbImpl.java | 16 +- .../impl/QueueServiceRabbitMqImpl.java | 6 +- .../service/impl/StorageServiceS3Impl.java | 10 +- .../impl/SubsetServiceMariaDbImpl.java | 12 +- .../service/impl/TableServiceMariaDbImpl.java | 67 +- .../service/impl/ViewServiceMariaDbImpl.java | 8 +- .../java/at/tuwien/utils/MariaDbUtil.java | 2 +- dbrepo-gateway-service/data.json | 14 + dbrepo-gateway-service/dbrepo.conf | 93 +- dbrepo-grafana-service/.dockerignore | 1 + dbrepo-grafana-service/.gitignore | 43 + .../.mvn/wrapper/MavenWrapperDownloader.java | 118 + .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 50710 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + dbrepo-grafana-service/Dockerfile | 31 + dbrepo-grafana-service/README.md | 38 + dbrepo-grafana-service/mvnw | 310 ++ dbrepo-grafana-service/mvnw.cmd | 182 + dbrepo-grafana-service/pom.xml | 299 ++ dbrepo-grafana-service/rest-service/pom.xml | 35 + .../DbrepoGrafanaServiceApplication.java | 13 + .../java/at/tuwien/auth/AuthTokenFilter.java | 96 + .../auth/BasicAuthenticationProvider.java | 60 + .../java/at/tuwien/config/CacheConfig.java | 40 + .../java/at/tuwien/config/GatewayConfig.java | 104 + .../java/at/tuwien/config/KeycloakConfig.java | 50 + .../at/tuwien/config/WebSecurityConfig.java | 107 + .../at/tuwien/dto/DashboardConfigDto.java | 46 + .../at/tuwien/dto/HistogramConfigDto.java | 14 + .../java/at/tuwien/dto/PieChartConfigDto.java | 14 + .../java/at/tuwien/dto/TableConfigDto.java | 12 + .../src/main/java/at/tuwien/dto/TimeDto.java | 17 + .../java/at/tuwien/dto/TimeSeriesDto.java | 14 + .../tuwien/endpoints/DashboardEndpoint.java | 92 + .../at/tuwien/endpoints/DataEndpoint.java | 157 + .../exception/ContainerNotFoundException.java | 21 + .../exception/DatabaseMalformedException.java | 21 + .../exception/DatabaseNotFoundException.java | 21 + .../DatabaseUnavailableException.java | 21 + .../FormatNotAvailableException.java | 23 + .../exception/JsonProcessingException.java | 17 + .../tuwien/exception/NotAllowedException.java | 21 + .../tuwien/exception/PaginationException.java | 22 + .../exception/QueryMalformedException.java | 21 + .../exception/QueryNotFoundException.java | 21 + .../exception/QueryStoreCreateException.java | 21 + .../exception/QueryStoreGCException.java | 21 + .../exception/QueryStoreInsertException.java | 21 + .../exception/QueryStorePersistException.java | 21 + .../exception/RemoteUnavailableException.java | 21 + .../RestTemplateExchangeException.java | 17 + .../exception/ServiceConnectionException.java | 21 + .../at/tuwien/exception/ServiceException.java | 21 + .../exception/SidecarExportException.java | 21 + .../exception/SidecarImportException.java | 21 + .../exception/StorageNotFoundException.java | 21 + .../StorageUnavailableException.java | 21 + .../SyncDatabaseNotFoundException.java | 17 + .../exception/TableExistsException.java | 21 + .../exception/TableMalformedException.java | 21 + .../exception/TableNotFoundException.java | 21 + .../exception/UserNotFoundException.java | 21 + .../at/tuwien/gateway/KeycloakGateway.java | 11 + .../gateway/impl/KeycloakGatewayImpl.java | 81 + .../DashboardApiExceptionHandler.java | 52 + .../interceptor/KeycloakInterceptor.java | 55 + .../java/at/tuwien/panels/AbstractPanel.java | 47 + .../java/at/tuwien/panels/CntAllPanel.java | 69 + .../main/java/at/tuwien/panels/Dashboard.java | 29 + .../java/at/tuwien/panels/HistogramPanel.java | 110 + .../tuwien/panels/MultiTimeSeriesPanel.java | 90 + .../java/at/tuwien/panels/PieChartPanel.java | 110 + .../main/java/at/tuwien/panels/RowPanel.java | 52 + .../java/at/tuwien/panels/StatsPanel.java | 183 + .../java/at/tuwien/panels/TablePanel.java | 73 + .../at/tuwien/panels/TimeSeriesPanel.java | 93 + .../at/tuwien/service/DashboardService.java | 9 + .../java/at/tuwien/service/DataService.java | 14 + .../at/tuwien/service/DataSourceService.java | 7 + .../java/at/tuwien/service/TableService.java | 16 + .../tuwien/service/ViewGeneratorService.java | 15 + .../service/impl/DashboardServiceImpl.java | 408 ++ .../tuwien/service/impl/DataServiceImpl.java | 405 ++ .../service/impl/DataSourceServiceImpl.java | 99 + .../tuwien/service/impl/TableServiceImpl.java | 121 + .../impl/ViewGeneratorServiceImpl.java | 225 + .../src/main/resources/application-local.yml | 89 + .../src/main/resources/application.yml | 107 + .../src/test/resources/application.properties | 0 dbrepo-metadata-db/1_setup-schema.sql | 34 +- dbrepo-metadata-db/2_setup-data.sql | 4 +- dbrepo-metadata-service/Dockerfile | 33 +- dbrepo-metadata-service/api/pom.xml | 45 - .../OrcidDisambiguatedSourceTypeDto.java | 6 - dbrepo-metadata-service/entities/pom.xml | 38 - .../tuwien/entities/identifier/NameType.java | 9 - dbrepo-metadata-service/oai/pom.xml | 4 +- .../ifs/dbrepo}/oaipmh/OaiErrorType.java | 6 +- .../oaipmh/OaiListIdentifiersParameters.java | 2 +- .../oaipmh/OaiListRecordsParameters.java | 2 +- .../dbrepo}/oaipmh/OaiRecordParameters.java | 2 +- .../ifs/dbrepo}/oaipmh/RequestParameters.java | 2 +- dbrepo-metadata-service/pom.xml | 85 +- dbrepo-metadata-service/report/pom.xml | 4 +- dbrepo-metadata-service/repositories/pom.xml | 40 +- .../ifs/dbrepo}/mapper/SparqlMapper.java | 4 +- .../repository/BannerMessageRepository.java | 4 +- .../dbrepo}/repository/ConceptRepository.java | 4 +- .../repository/ContainerRepository.java | 4 +- .../repository/DatabaseRepository.java | 4 +- .../repository/IdentifierRepository.java | 4 +- .../dbrepo}/repository/ImageRepository.java | 4 +- .../dbrepo}/repository/LicenseRepository.java | 4 +- .../repository/OntologyRepository.java | 4 +- .../dbrepo}/repository/TableRepository.java | 4 +- .../dbrepo}/repository/UnitRepository.java | 4 +- .../dbrepo}/repository/UserRepository.java | 4 +- .../dbrepo}/repository/ViewRepository.java | 4 +- .../dbrepo}/utils/EnumToStringConverter.java | 2 +- dbrepo-metadata-service/rest-service/pom.xml | 18 +- .../dbrepo/MetadataServiceApplication.java} | 10 +- .../tuwien/ifs/dbrepo}/config/MvcConfig.java | 6 +- .../ifs/dbrepo}/config/SwaggerConfig.java | 2 +- .../IdentifierStatusTypeDtoConverter.java | 4 +- .../IdentifierTypeDtoConverter.java | 4 +- .../dbrepo/endpoints/AbstractEndpoint.java | 136 + .../ifs/dbrepo}/endpoints/AccessEndpoint.java | 49 +- .../dbrepo}/endpoints/ConceptEndpoint.java | 8 +- .../dbrepo}/endpoints/ContainerEndpoint.java | 22 +- .../dbrepo}/endpoints/DatabaseEndpoint.java | 141 +- .../dbrepo}/endpoints/IdentifierEndpoint.java | 30 +- .../ifs/dbrepo}/endpoints/ImageEndpoint.java | 24 +- .../dbrepo}/endpoints/LicenseEndpoint.java | 8 +- .../dbrepo}/endpoints/MessageEndpoint.java | 20 +- .../dbrepo}/endpoints/MetadataEndpoint.java | 12 +- .../dbrepo}/endpoints/OntologyEndpoint.java | 22 +- .../ifs/dbrepo}/endpoints/TableEndpoint.java | 117 +- .../ifs/dbrepo}/endpoints/UnitEndpoint.java | 8 +- .../ifs/dbrepo}/endpoints/UserEndpoint.java | 24 +- .../ifs/dbrepo}/endpoints/ViewEndpoint.java | 82 +- .../dbrepo}/handlers/ApiExceptionHandler.java | 20 +- .../dbrepo}/validation/EndpointValidator.java | 30 +- .../at/tuwien/endpoints/AbstractEndpoint.java | 53 - .../src/main/resources/application.yml | 11 +- .../dbrepo}/ApplicationIntegrationTest.java | 4 +- .../dbrepo}/config/ObjectMapperConfig.java | 2 +- .../ifs/dbrepo}/config/RabbitConfig.java | 6 +- ...ntifierStatusTypeDtoConverterUnitTest.java | 16 +- .../IdentifierTypeDtoConverterUnitTest.java | 16 +- .../endpoints/AbstractEndpointUnitTest.java | 36 +- .../endpoints/AccessEndpointUnitTest.java | 63 +- .../endpoints/ActuatorComponentTest.java | 14 +- .../endpoints/ConceptEndpointUnitTest.java | 23 +- .../endpoints/ContainerEndpointUnitTest.java | 42 +- .../endpoints/DatabaseEndpointUnitTest.java | 96 +- .../endpoints/IdentifierEndpointUnitTest.java | 213 +- .../endpoints/ImageEndpointUnitTest.java | 82 +- .../endpoints/LicenseEndpointUnitTest.java | 16 +- .../endpoints/MessageEndpointUnitTest.java | 34 +- .../endpoints/MetadataEndpointUnitTest.java | 20 +- .../endpoints/OntologyEndpointUnitTest.java | 38 +- .../endpoints/TableEndpointUnitTest.java | 314 +- .../endpoints/UnitEndpointUnitTest.java | 21 +- .../endpoints/UserEndpointUnitTest.java | 42 +- .../endpoints/ViewEndpointUnitTest.java | 167 +- .../ifs/dbrepo/entity}/EntitiesUnitTest.java | 6 +- .../gateway/BrokerServiceGatewayUnitTest.java | 15 +- .../gateway/CrossrefGatewayUnitTest.java | 12 +- .../DashboardServiceGatewayUnitTest.java | 286 ++ .../gateway/DataServiceGatewayUnitTest.java | 36 +- .../KeycloakGatewayIntegrationTest.java | 19 +- .../dbrepo}/gateway/OrcidGatewayUnitTest.java | 17 +- .../dbrepo}/gateway/RorGatewayUnitTest.java | 15 +- .../gateway/SearchServiceGatewayUnitTest.java | 12 +- .../handlers/ApiExceptionHandlerTest.java | 42 +- .../mapper/MetadataMapperUnitTest.java | 29 +- .../dbrepo}/mvc/ActuatorEndpointMvcTest.java | 6 +- ...nticationPrivilegedIntegrationMvcTest.java | 35 +- .../mvc/IdentifierEndpointMvcTest.java | 11 +- .../dbrepo}/mvc/MetadataEndpointMvcTest.java | 16 +- .../dbrepo}/mvc/OpenApiEndpointMvcTest.java | 15 +- .../mvc/PrometheusEndpointMvcTest.java | 33 +- .../service/AccessServiceUnitTest.java | 28 +- .../AuthenticationServiceIntegrationTest.java | 22 +- .../service/BrokerServiceIntegrationTest.java | 36 +- .../service/ConceptServiceUnitTest.java | 18 +- .../service/ContainerServiceUnitTest.java | 38 +- ...aCiteIdentifierServicePersistenceTest.java | 46 +- .../DatabaseServicePersistenceTest.java | 34 +- .../service/DatabaseServiceUnitTest.java | 64 +- .../service/EntityServiceUnitTest.java | 27 +- .../IdentifierServicePersistenceTest.java | 47 +- .../service/ImageServicePersistenceTest.java | 47 +- .../dbrepo}/service/ImageServiceUnitTest.java | 52 +- .../service/LicenseServiceUnitTest.java | 18 +- .../service/MessageServiceUnitTest.java | 25 +- .../service/MetadataServiceUnitTest.java | 38 +- .../StorageServiceIntegrationTest.java | 14 +- .../service/TableServicePersistenceTest.java | 49 +- .../dbrepo}/service/TableServiceUnitTest.java | 73 +- .../dbrepo}/service/UnitServiceUnitTest.java | 18 +- .../service/UserServiceIntegrationTest.java | 28 +- .../service/UserServicePersistenceTest.java | 21 +- .../dbrepo}/service/UserServiceUnitTest.java | 26 +- .../service/ViewServicePersistenceTest.java | 28 +- .../dbrepo}/service/ViewServiceUnitTest.java | 42 +- .../tuwien/ifs/dbrepo}/utils/AmqpUtils.java | 6 +- .../tuwien/ifs/dbrepo}/utils/H2Utils.java | 2 +- .../ifs/dbrepo}/utils/KeycloakUtils.java | 10 +- .../tuwien/ifs/dbrepo}/utils/XmlUtils.java | 2 +- .../validator/EndpointValidatorUnitTest.java | 46 +- .../src/test/resources/application.properties | 8 +- dbrepo-metadata-service/services/pom.xml | 13 +- .../ifs/dbrepo}/auth/AuthTokenFilter.java | 8 +- .../auth/BasicAuthenticationProvider.java | 8 +- .../auth/InternalRequestInterceptor.java | 8 +- .../ifs/dbrepo}/config/CacheConfig.java | 4 +- .../ifs/dbrepo}/config/DataCiteConfig.java | 2 +- .../ifs/dbrepo}/config/EndpointConfig.java | 2 +- .../ifs/dbrepo}/config/GatewayConfig.java | 18 +- .../ifs/dbrepo}/config/JacksonConfig.java | 6 +- .../tuwien/ifs/dbrepo}/config/JenaConfig.java | 2 +- .../ifs/dbrepo}/config/KeycloakConfig.java | 2 +- .../ifs/dbrepo}/config/MetadataConfig.java | 2 +- .../ifs/dbrepo}/config/MetricsConfig.java | 12 +- .../ifs/dbrepo}/config/RabbitConfig.java | 2 +- .../tuwien/ifs/dbrepo}/config/S3Config.java | 2 +- .../ifs/dbrepo}/config/SecurityConfig.java | 2 +- .../ifs/dbrepo}/config/TemplateConfig.java | 2 +- .../ifs/dbrepo}/config/WebSecurityConfig.java | 8 +- .../dbrepo}/gateway/BrokerServiceGateway.java | 8 +- .../ifs/dbrepo}/gateway/CrossrefGateway.java | 6 +- .../gateway/DashboardServiceGateway.java | 51 + .../dbrepo}/gateway/DataServiceGateway.java | 30 +- .../ifs/dbrepo}/gateway/KeycloakGateway.java | 10 +- .../ifs/dbrepo}/gateway/OrcidGateway.java | 6 +- .../ifs/dbrepo}/gateway/RorGateway.java | 6 +- .../dbrepo}/gateway/SearchServiceGateway.java | 8 +- .../impl/BrokerServiceGatewayImpl.java | 13 +- .../gateway/impl/CrossrefGatewayImpl.java | 12 +- .../impl/DashboardServiceGatewayImpl.java | 142 + .../gateway/impl/DataServiceGatewayImpl.java | 31 +- .../gateway/impl/KeycloakGatewayImpl.java | 16 +- .../gateway/impl/OrcidGatewayImpl.java | 10 +- .../dbrepo}/gateway/impl/RorGatewayImpl.java | 12 +- .../impl/SearchServiceGatewayImpl.java | 21 +- .../ifs/dbrepo/service/AccessService.java | 81 + .../dbrepo/service/AuthenticationService.java | 18 + .../dbrepo}/service/BannerMessageService.java | 10 +- .../ifs/dbrepo/service/BrokerService.java | 25 + .../ifs/dbrepo}/service/ConceptService.java | 6 +- .../ifs/dbrepo}/service/ContainerService.java | 15 +- .../dbrepo}/service/CredentialService.java | 4 +- .../ifs/dbrepo/service/DashboardService.java | 44 + .../ifs/dbrepo/service/DatabaseService.java | 193 + .../ifs/dbrepo}/service/EntityService.java | 34 +- .../dbrepo}/service/IdentifierService.java | 86 +- .../ifs/dbrepo}/service/ImageService.java | 15 +- .../ifs/dbrepo}/service/LicenseService.java | 6 +- .../ifs/dbrepo}/service/MetadataService.java | 20 +- .../ifs/dbrepo}/service/OntologyService.java | 17 +- .../ifs/dbrepo}/service/StorageService.java | 12 +- .../ifs/dbrepo/service/TableService.java | 140 + .../ifs/dbrepo}/service/UnitService.java | 12 +- .../ifs/dbrepo}/service/UserService.java | 23 +- .../ifs/dbrepo/service/ViewService.java | 69 + .../service/impl/AccessServiceImpl.java | 24 +- .../impl/AuthenticationServiceImpl.java | 12 +- .../impl/BannerMessageServiceImpl.java | 16 +- .../impl/BrokerServiceRabbitMqImpl.java | 18 +- .../service/impl/ConceptServiceImpl.java | 10 +- .../service/impl/ContainerServiceImpl.java | 22 +- .../service/impl/CredentialServiceImpl.java | 8 +- .../service/impl/DashboardServiceImpl.java | 51 + .../impl/DataCiteIdentifierServiceImpl.java | 50 +- .../service/impl/DatabaseServiceImpl.java | 81 +- .../service/impl/EntityServiceImpl.java | 22 +- .../service/impl/IdentifierServiceImpl.java | 53 +- .../service/impl/ImageServiceImpl.java | 20 +- .../service/impl/LicenseServiceImpl.java | 10 +- .../service/impl/MetadataServiceImpl.java | 43 +- .../service/impl/OntologyServiceImpl.java | 21 +- .../service/impl/StorageServiceS3Impl.java | 10 +- .../service/impl/TableServiceImpl.java | 54 +- .../dbrepo}/service/impl/UnitServiceImpl.java | 10 +- .../dbrepo}/service/impl/UserServiceImpl.java | 29 +- .../dbrepo}/service/impl/ViewServiceImpl.java | 71 +- .../java/at/tuwien/service/AccessService.java | 70 - .../tuwien/service/AuthenticationService.java | 22 - .../java/at/tuwien/service/BrokerService.java | 21 - .../at/tuwien/service/DatabaseService.java | 124 - .../java/at/tuwien/service/TableService.java | 64 - .../java/at/tuwien/service/ViewService.java | 72 - .../java/at/tuwien/test/AbstractUnitTest.java | 160 - dbrepo-metric-db/prometheus.yml | 2 +- dbrepo-search-service/.gitignore | 6 - dbrepo-search-service/.testpickle | Bin 100 -> 0 bytes dbrepo-search-service/Dockerfile | 6 +- dbrepo-search-service/Pipfile | 2 +- dbrepo-search-service/Pipfile.lock | 1134 ++--- dbrepo-search-service/app.py | 128 +- .../database/fields_response_payload.json | 65 - .../database/search_request_payload.json | 10 - .../unit/fields_response_payload.json | 29 - .../examples/unit/search_request_payload.json | 7 - .../friendly_names_overrides.json | 18 + dbrepo-search-service/init/Dockerfile | 13 +- dbrepo-search-service/init/Pipfile | 2 +- dbrepo-search-service/init/Pipfile.lock | 793 ++-- dbrepo-search-service/init/app.py | 98 +- .../init/clients/keycloak_client.py | 56 - .../init/lib/dbrepo-1.7.3-py3-none-any.whl | Bin 32568 -> 0 bytes .../init/lib/dbrepo-1.7.3.tar.gz | Bin 49697 -> 0 bytes .../init/lib/dbrepo-1.8.0-py3-none-any.whl | Bin 0 -> 88162 bytes .../init/lib/dbrepo-1.8.0.tar.gz | Bin 0 -> 97755 bytes dbrepo-search-service/init/tests/test_app.py | 21 - .../init/tests/test_unit_app.py | 50 + .../lib/dbrepo-1.7.3-py3-none-any.whl | Bin 32568 -> 0 bytes dbrepo-search-service/lib/dbrepo-1.7.3.tar.gz | Bin 49697 -> 0 bytes .../lib/dbrepo-1.8.0-py3-none-any.whl | Bin 0 -> 88162 bytes dbrepo-search-service/lib/dbrepo-1.8.0.tar.gz | Bin 0 -> 97755 bytes ...{update_database.yml => save_database.yml} | 19 +- dbrepo-search-service/tests/.testpickle | Bin 700 -> 0 bytes dbrepo-search-service/tests/__init__.py | 3 - dbrepo-search-service/tests/test_app.py | 57 +- dbrepo-search-service/tests/test_jwt.py | 98 - .../components/database/DatabaseToolbar.vue | 9 +- dbrepo-ui/components/identifier/Citation.vue | 1 - dbrepo-ui/composables/axios-instance.ts | 25 +- dbrepo-ui/composables/database-service.ts | 8 +- dbrepo-ui/dto/index.ts | 1 + dbrepo-ui/locales/en-US.json | 26 +- dbrepo-ui/nuxt.config.ts | 3 + .../pages/database/[database_id]/info.vue | 35 +- .../pages/database/[database_id]/settings.vue | 46 +- .../database/[database_id]/subset/index.vue | 2 +- .../[database_id]/table/[table_id]/info.vue | 11 + .../[database_id]/view/[view_id]/info.vue | 2 +- .../[database_id]/view/[view_id]/settings.vue | 1 + docker-compose.yml | 172 +- grafana/grafana.ini | 5 + helm/dbrepo/Chart.yaml | 4 +- helm/dbrepo/README.md | 4 +- helm/dbrepo/files/01-setup-schema.sql | 34 +- helm/dbrepo/files/create-event-listener.jar | Bin 10141 -> 10141 bytes helm/dbrepo/values.yaml | 16 +- install.sh | 2 +- lib/java/dbrepo-core/.gitignore | 35 + lib/java/dbrepo-core/Dockerfile | 12 + lib/java/dbrepo-core/pom.xml | 167 + .../ac/tuwien/ifs/dbrepo/core/Serialize.java | 32 + .../ifs/dbrepo/core}/api/CacheableDto.java | 2 +- .../dbrepo/core/api}/ExportResourceDto.java | 2 +- .../core}/api/amqp/ChannelDetailsDto.java | 2 +- .../dbrepo/core}/api/amqp/ConsumerDto.java | 2 +- .../core}/api/amqp/CreateExchangeDto.java | 2 +- .../dbrepo/core}/api/amqp/CreateUserDto.java | 2 +- .../core}/api/amqp/CreateVirtualHostDto.java | 2 +- .../dbrepo/core}/api/amqp/ExchangeDto.java | 2 +- .../api/amqp/GrantExchangePermissionsDto.java | 2 +- .../amqp/GrantVirtualHostPermissionsDto.java | 2 +- .../dbrepo/core}/api/amqp/QueueBriefDto.java | 2 +- .../ifs/dbrepo/core}/api/amqp/QueueDto.java | 2 +- .../core}/api/amqp/TopicPermissionDto.java | 2 +- .../dbrepo/core}/api/amqp/UserDetailsDto.java | 2 +- .../api/amqp/VirtualHostPermissionDto.java | 2 +- .../dbrepo/core}/api/auth/CreateUserDto.java | 2 +- .../dbrepo/core}/api/auth/RealmAccessDto.java | 2 +- .../api/container/ContainerActionTypeDto.java | 4 +- .../api/container/ContainerBriefDto.java | 6 +- .../core}/api/container/ContainerDto.java | 6 +- .../api/container/CreateContainerDto.java | 2 +- .../api/container/image/DataTypeDto.java | 2 +- .../api/container/image/ImageBriefDto.java | 2 +- .../api/container/image/ImageChangeDto.java | 2 +- .../api/container/image/ImageCreateDto.java | 2 +- .../core}/api/container/image/ImageDto.java | 2 +- .../api/container/image/OperatorDto.java | 2 +- .../core}/api/crossref/CrossrefDto.java | 4 +- .../crossref/form/CrossrefLiteralFormDto.java | 2 +- .../api/crossref/label/CrossrefLabelDto.java | 4 +- .../crossref/label/CrossrefPrefLabelDto.java | 2 +- .../core}/api/database/AccessTypeDto.java | 4 +- .../core}/api/database/CreateAccessDto.java | 2 +- .../core}/api/database/CreateDatabaseDto.java | 2 +- .../core}/api/database/CreateViewDto.java | 4 +- .../core}/api/database/DatabaseAccessDto.java | 4 +- .../core}/api/database/DatabaseBriefDto.java | 6 +- .../core}/api/database/DatabaseDto.java | 30 +- .../database/DatabaseModifyDashboardDto.java | 20 + .../api/database/DatabaseModifyImageDto.java | 2 +- .../database/DatabaseModifyVisibilityDto.java | 7 +- .../api/database/DatabaseTransferDto.java | 2 +- .../core}/api/database/LanguageTypeDto.java | 4 +- .../dbrepo/core}/api/database/LicenseDto.java | 2 +- .../core}/api/database/LoadFileDto.java | 2 +- .../core}/api/database/ViewBriefDto.java | 2 +- .../core}/api/database/ViewColumnDto.java | 13 +- .../dbrepo/core}/api/database/ViewDto.java | 14 +- .../core}/api/database/ViewUpdateDto.java | 2 +- .../database/internal/CreateDatabaseDto.java | 12 +- .../database/query/ExecuteStatementDto.java | 2 +- .../core}/api/database/query/ExportDto.java | 2 +- .../core}/api/database/query/FilterDto.java | 2 +- .../api/database/query/FilterTypeDto.java | 4 +- .../core}/api/database/query/ImportDto.java | 2 +- .../core}/api/database/query/OrderDto.java | 2 +- .../api/database/query/OrderTypeDto.java | 4 +- .../api/database/query/QueryBriefDto.java | 6 +- .../core}/api/database/query/QueryDto.java | 7 +- .../api/database/query/QueryPersistDto.java | 2 +- .../api/database/query/QueryTypeDto.java | 4 +- .../api/database/query/SaveStatementDto.java | 2 +- .../core}/api/database/query/SubsetDto.java | 2 +- .../api/database/table/CreateTableDto.java | 6 +- .../database/table/HistoryEventTypeDto.java | 4 +- .../core/api/database/table}/SortType.java | 4 +- .../core/api/database/table}/SortTypeDto.java | 4 +- .../api/database/table/TableBriefDto.java | 2 +- .../database/table/TableCreateRawQuery.java | 2 +- .../core}/api/database/table/TableDto.java | 24 +- .../api/database/table/TableHistoryDto.java | 2 +- .../database/table/TableInsertRawQuery.java | 2 +- .../api/database/table/TableStatisticDto.java | 17 +- .../api/database/table/TableUpdateDto.java | 2 +- .../api/database/table/TupleDeleteDto.java | 2 +- .../core}/api/database/table/TupleDto.java | 2 +- .../api/database/table/TupleUpdateDto.java | 2 +- .../table/columns/ColumnBriefDto.java | 2 +- .../api/database/table/columns/ColumnDto.java | 11 +- .../table/columns/ColumnStatisticDto.java | 6 +- .../database/table/columns/ColumnTypeDto.java | 4 +- .../table/columns/CreateTableColumnDto.java | 2 +- .../api/database/table/columns/EnumDto.java | 2 +- .../api/database/table/columns/SetDto.java | 2 +- .../api/database/table/columns/SiUnitDto.java | 4 +- .../concepts/ColumnSemanticsUpdateDto.java | 2 +- .../columns/concepts/ConceptBriefDto.java | 2 +- .../table/columns/concepts/ConceptDto.java | 4 +- .../columns/concepts/ConceptSaveDto.java | 2 +- .../table/columns/concepts/UnitBriefDto.java | 2 +- .../table/columns/concepts/UnitDto.java | 4 +- .../table/columns/concepts/UnitSaveDto.java | 2 +- .../table/constraints/ConstraintsDto.java | 8 +- .../CreateTableConstraintsDto.java | 4 +- .../foreign/CreateForeignKeyDto.java | 2 +- .../foreign/ForeignKeyBriefDto.java | 2 +- .../constraints/foreign/ForeignKeyDto.java | 6 +- .../foreign/ForeignKeyReferenceDto.java | 4 +- .../constraints/foreign/ReferenceTypeDto.java | 2 +- .../constraints/primary/PrimaryKeyDto.java | 6 +- .../table/constraints/unique/UniqueDto.java | 6 +- .../table/internal/TableCreateDto.java | 6 +- .../core}/api/datacite/DataCiteBody.java | 2 +- .../core}/api/datacite/DataCiteData.java | 2 +- .../core}/api/datacite/DataCiteError.java | 2 +- .../api/datacite/doi/DataCiteCreateDoi.java | 2 +- .../core}/api/datacite/doi/DataCiteDoi.java | 2 +- .../api/datacite/doi/DataCiteDoiCreator.java | 2 +- .../doi/DataCiteDoiCreatorAffiliation.java | 2 +- .../doi/DataCiteDoiCreatorNameIdentifier.java | 2 +- .../api/datacite/doi/DataCiteDoiEvent.java | 2 +- .../doi/DataCiteDoiFundingReference.java | 2 +- ...DataCiteDoiFundingReferenceIdentifier.java | 2 +- .../doi/DataCiteDoiRelatedIdentifier.java | 2 +- .../api/datacite/doi/DataCiteDoiRights.java | 2 +- .../api/datacite/doi/DataCiteDoiTitle.java | 2 +- .../api/datacite/doi/DataCiteDoiTypes.java | 2 +- .../api/datacite/doi/DataCiteNameType.java | 4 +- .../dbrepo/core}/api/error/ApiErrorDto.java | 2 +- .../core}/api/file/UploadResponseDto.java | 2 +- .../core/api/grafana/AccessTypeDto.java | 24 + .../core/api/grafana/CreateDashboardDto.java | 39 + .../grafana/CreateDashboardResponseDto.java | 25 + .../core/api/grafana/DatasourceDto.java | 80 + .../core/api/grafana/DatasourceTypeDto.java | 24 + .../core/api/grafana/PermissionTypeDto.java | 33 + .../api/grafana/UpdateDashboardAccessDto.java | 21 + .../AffiliationIdentifierSchemeTypeDto.java | 2 +- .../api/identifier/BibliographyTypeDto.java | 4 +- .../api/identifier/CreateIdentifierDto.java | 6 +- .../core}/api/identifier/CreatorBriefDto.java | 2 +- .../core}/api/identifier/CreatorDto.java | 3 +- .../api/identifier/DescriptionTypeDto.java | 4 +- .../api/identifier/IdentifierBriefDto.java | 2 +- .../identifier/IdentifierDescriptionDto.java | 5 +- .../core}/api/identifier/IdentifierDto.java | 8 +- .../api/identifier/IdentifierFunderDto.java | 3 +- .../identifier/IdentifierFunderTypeDto.java | 4 +- .../api/identifier/IdentifierSaveDto.java | 6 +- .../identifier/IdentifierStatusTypeDto.java | 4 +- .../api/identifier/IdentifierTitleDto.java | 5 +- .../api/identifier/IdentifierTypeDto.java | 4 +- .../dbrepo/core}/api/identifier/LinksDto.java | 6 +- .../NameIdentifierSchemeTypeDto.java | 2 +- .../core}/api/identifier/NameTypeDto.java | 4 +- .../api/identifier/RelatedIdentifierDto.java | 8 +- .../core}/api/identifier/RelatedTypeDto.java | 4 +- .../core}/api/identifier/RelationTypeDto.java | 4 +- .../identifier/SaveIdentifierCreatorDto.java | 2 +- .../SaveIdentifierDescriptionDto.java | 4 +- .../identifier/SaveIdentifierFunderDto.java | 2 +- .../identifier/SaveIdentifierTitleDto.java | 4 +- .../identifier/SaveRelatedIdentifierDto.java | 2 +- .../core}/api/identifier/TitleTypeDto.java | 4 +- .../core}/api/identifier/ld/LdCreatorDto.java | 2 +- .../core}/api/identifier/ld/LdDatasetDto.java | 2 +- .../core}/api/keycloak/CredentialDto.java | 2 +- .../core}/api/keycloak/CredentialTypeDto.java | 4 +- .../core}/api/keycloak/ModifyUserDto.java | 2 +- .../api/keycloak/RoleRepresentationDto.java | 2 +- .../dbrepo/core}/api/keycloak/TokenDto.java | 4 +- .../api/keycloak/UpdateCredentialsDto.java | 2 +- .../core}/api/keycloak/UserAttributesDto.java | 4 +- .../api/keycloak/UserCreateAttributesDto.java | 2 +- .../core}/api/keycloak/UserCreateDto.java | 2 +- .../api/keycloak/UserIdAttributesDto.java | 2 +- .../ifs/dbrepo/core}/api/ldap/UserDto.java | 2 +- .../maintenance/BannerMessageBriefDto.java | 2 +- .../maintenance/BannerMessageCreateDto.java | 2 +- .../api/maintenance/BannerMessageDto.java | 2 +- .../api/maintenance/BannerMessageTypeDto.java | 4 +- .../maintenance/BannerMessageUpdateDto.java | 2 +- .../ifs/dbrepo/core}/api/orcid/OrcidDto.java | 6 +- .../activities/OrcidActivitiesSummaryDto.java | 4 +- .../employments/OrcidEmploymentsDto.java | 4 +- .../affiliation/OrcidAffiliationGroupDto.java | 4 +- .../group/OrcidEmploymentSummaryDto.java | 4 +- .../group/summary/OrcidSummaryDto.java | 4 +- .../organization/OrcidOrganizationDto.java | 4 +- .../disambiguated/OrcidDisambiguatedDto.java | 2 +- .../OrcidDisambiguatedSourceTypeDto.java | 6 + .../api/orcid/person/OrcidPersonDto.java | 4 +- .../api/orcid/person/name/OrcidNameDto.java | 2 +- .../api/orcid/person/name/OrcidValueDto.java | 2 +- .../ifs/dbrepo/core}/api/ror/RorDto.java | 2 +- .../dbrepo/core}/api/semantics/EntityDto.java | 2 +- .../core}/api/semantics/OntologyBriefDto.java | 2 +- .../api/semantics/OntologyCreateDto.java | 2 +- .../core}/api/semantics/OntologyDto.java | 5 +- .../api/semantics/OntologyModifyDto.java | 2 +- .../api/semantics/TableColumnEntityDto.java | 2 +- .../user/ExchangeUpdatePermissionsDto.java | 2 +- .../core}/api/user/GrantedAuthorityDto.java | 2 +- .../dbrepo/core}/api/user/RoleTypeDto.java | 4 +- .../core}/api/user/UserAttributesDto.java | 2 +- .../dbrepo/core}/api/user/UserBriefDto.java | 2 +- .../dbrepo/core}/api/user/UserDetailsDto.java | 2 +- .../ifs/dbrepo/core}/api/user/UserDto.java | 4 +- .../dbrepo/core}/api/user/UserEmailDto.java | 2 +- .../dbrepo/core}/api/user/UserForgotDto.java | 2 +- .../core}/api/user/UserModifyPasswordDto.java | 2 +- .../core}/api/user/UserPasswordDto.java | 2 +- .../dbrepo/core}/api/user/UserResetDto.java | 2 +- .../dbrepo/core}/api/user/UserRolesDto.java | 2 +- .../core}/api/user/UserThemeSetDto.java | 2 +- .../dbrepo/core}/api/user/UserUpdateDto.java | 2 +- .../api/user/UserUpdatePermissionsDto.java | 2 +- .../user/external/ExternalMetadataDto.java | 4 +- .../api/user/external/ExternalResultType.java | 4 +- .../affiliation/ExternalAffiliationDto.java | 2 +- .../user/internal/UpdateUserPasswordDto.java | 2 +- .../core/entity}/container/Container.java | 12 +- .../container/image/ContainerImage.java | 4 +- .../entity}/container/image/DataType.java | 2 +- .../entity}/container/image/Operator.java | 2 +- .../core/entity}/database/AccessType.java | 4 +- .../core/entity}/database/Database.java | 33 +- .../core/entity}/database/DatabaseAccess.java | 7 +- .../entity}/database/DatabaseAccessKey.java | 2 +- .../core/entity}/database/LanguageType.java | 4 +- .../dbrepo/core/entity}/database/License.java | 2 +- .../dbrepo/core/entity}/database/View.java | 6 +- .../core/entity}/database/ViewColumn.java | 6 +- .../core/entity}/database/table/Table.java | 14 +- .../database/table/columns/ColumnEnum.java | 4 +- .../database/table/columns/ColumnSet.java | 4 +- .../database/table/columns/TableColumn.java | 6 +- .../table/columns/TableColumnConcept.java | 4 +- .../table/columns/TableColumnType.java | 4 +- .../table/columns/TableColumnUnit.java | 4 +- .../table/constraints/Constraints.java | 8 +- .../constraints/foreignKey/ForeignKey.java | 4 +- .../foreignKey/ForeignKeyReference.java | 6 +- .../constraints/foreignKey/ReferenceType.java | 2 +- .../constraints/primaryKey/PrimaryKey.java | 6 +- .../table/constraints/unique/Unique.java | 6 +- .../AffiliationIdentifierSchemeType.java | 2 +- .../core/entity}/identifier/Creator.java | 4 +- .../entity}/identifier/DescriptionType.java | 4 +- .../core/entity}/identifier/Identifier.java | 12 +- .../identifier/IdentifierDescription.java | 6 +- .../entity}/identifier/IdentifierFunder.java | 4 +- .../identifier/IdentifierFunderType.java | 2 +- .../identifier/IdentifierStatusType.java | 4 +- .../entity}/identifier/IdentifierTitle.java | 6 +- .../entity}/identifier/IdentifierType.java | 4 +- .../identifier/NameIdentifierSchemeType.java | 2 +- .../core/entity/identifier/NameType.java | 9 + .../entity}/identifier/RelatedIdentifier.java | 2 +- .../core/entity}/identifier/RelatedType.java | 4 +- .../core/entity}/identifier/RelationType.java | 4 +- .../core/entity}/identifier/TitleType.java | 4 +- .../entity}/maintenance/BannerMessage.java | 4 +- .../maintenance/BannerMessageType.java | 4 +- .../core/entity}/semantics/Ontology.java | 4 +- .../ifs/dbrepo/core/entity}/user/User.java | 4 +- .../exception/AccessNotFoundException.java | 2 +- .../exception/AccountNotSetupException.java | 2 +- .../exception/AnalyseServiceException.java | 2 +- .../AuthServiceConnectionException.java | 2 +- .../core}/exception/AuthServiceException.java | 2 +- .../BrokerServiceConnectionException.java | 2 +- .../exception/BrokerServiceException.java | 2 +- .../exception/ConceptNotFoundException.java | 2 +- .../ContainerAlreadyExistsException.java | 2 +- .../exception/ContainerNotFoundException.java | 2 +- .../exception/ContainerQuotaException.java | 2 +- .../CredentialsInvalidException.java | 2 +- .../DashboardServiceConnectionException.java | 21 + .../exception/DashboardServiceException.java | 21 + .../DataServiceConnectionException.java | 2 +- .../core}/exception/DataServiceException.java | 2 +- .../exception/DatabaseMalformedException.java | 2 +- .../exception/DatabaseNotFoundException.java | 2 +- .../DatabaseUnavailableException.java | 2 +- .../core}/exception/DoiNotFoundException.java | 2 +- .../core}/exception/EmailExistsException.java | 2 +- .../exception/ExchangeNotFoundException.java | 2 +- .../exception/ExternalServiceException.java | 2 +- .../exception/FilterBadRequestException.java | 2 +- .../FormatNotAvailableException.java | 4 +- .../IdentifierNotFoundException.java | 2 +- .../IdentifierNotSupportedException.java | 2 +- .../ImageAlreadyExistsException.java | 2 +- .../exception/ImageInvalidException.java | 2 +- .../exception/ImageNotFoundException.java | 2 +- .../exception/LicenseNotFoundException.java | 2 +- .../core}/exception/MalformedException.java | 2 +- .../exception/MessageNotFoundException.java | 2 +- .../MetadataServiceConnectionException.java | 2 +- .../exception/MetadataServiceException.java | 2 +- .../core}/exception/NotAllowedException.java | 2 +- .../exception/OntologyNotFoundException.java | 2 +- .../exception/OrcidNotFoundException.java | 2 +- .../core}/exception/PaginationException.java | 2 +- .../exception/QueryMalformedException.java | 2 +- .../exception/QueryNotFoundException.java | 2 +- .../exception/QueryNotSupportedException.java | 2 +- .../exception/QueryStoreCreateException.java | 2 +- .../exception/QueryStoreGCException.java | 2 +- .../exception/QueryStoreInsertException.java | 2 +- .../exception/QueryStorePersistException.java | 2 +- .../exception/QueueNotFoundException.java | 2 +- .../exception/RemoteUnavailableException.java | 2 +- .../core}/exception/RorNotFoundException.java | 2 +- .../SearchServiceConnectionException.java | 2 +- .../exception/SearchServiceException.java | 2 +- .../SemanticEntityNotFoundException.java | 2 +- .../dbrepo/core}/exception/SortException.java | 2 +- .../exception/StorageNotFoundException.java | 2 +- .../StorageUnavailableException.java | 2 +- .../core}/exception/TableExistsException.java | 2 +- .../exception/TableMalformedException.java | 2 +- .../exception/TableNotFoundException.java | 2 +- .../core}/exception/TableSchemaException.java | 2 +- .../exception/UnitNotFoundException.java | 2 +- .../exception/UriMalformedException.java | 2 +- .../core}/exception/UserExistsException.java | 2 +- .../exception/UserNotFoundException.java | 2 +- .../core}/exception/ViewExistsException.java | 2 +- .../exception/ViewMalformedException.java | 2 +- .../exception/ViewNotFoundException.java | 2 +- .../core}/exception/ViewSchemaException.java | 2 +- .../dbrepo/core}/mapper/MetadataMapper.java | 226 +- .../ifs/dbrepo/core}/test/BaseTest.java | 3854 +++++++++-------- .../ifs/dbrepo/core}/test/dto/LocaleDto.java | 2 +- .../ac/tuwien/ifs/dbrepo/core}/test/pom.xml | 4 +- .../dbrepo/core}/test/utils/ArrayUtils.java | 2 +- .../core}/test/utils/EndpointUtils.java | 4 +- lib/python/Makefile | 23 - lib/python/Pipfile | 5 + lib/python/Pipfile.lock | 1913 +++++--- lib/python/coverage.xml | 264 +- lib/python/dbrepo/RestClient.py | 41 +- lib/python/dbrepo/api/dto.py | 22 +- .../python/dbrepo/core}/__init__.py | 0 .../python/dbrepo/core/api}/__init__.py | 0 .../python/dbrepo/core}/api/dto.py | 8 +- lib/python/dbrepo/core/api/exceptions.py | 5 + lib/python/dbrepo/core/client/__init__.py | 0 lib/python/dbrepo/core/client/auth.py | 75 + lib/python/dbrepo/core/client/dashboard.py | 451 ++ .../python/dbrepo/core/client/search.py | 65 +- .../python/dbrepo/core/client/storage.py | 16 +- lib/python/dbrepo/core/omlib/__init__.py | 0 .../python/dbrepo/core}/omlib/constants.py | 6 +- .../python/dbrepo/core}/omlib/dimension.py | 2 +- .../dbrepo/core/omlib/exceptions/__init__.py | 0 .../omlib/exceptions/dimensionexception.py | 0 .../exceptions/unitconversionexception.py | 0 .../omlib/exceptions/unitidentityexception.py | 0 .../python/dbrepo/core}/omlib/measure.py | 10 +- .../python/dbrepo/core}/omlib/omconstants.py | 6 +- lib/python/dbrepo/core/omlib/rdf/__init__.py | 0 .../python/dbrepo/core}/omlib/rdf/om-2.0.rdf | 0 .../python/dbrepo/core}/omlib/scale.py | 12 +- .../python/dbrepo/core}/omlib/thing.py | 0 .../python/dbrepo/core}/omlib/unit.py | 10 +- lib/python/docs/index.rst | 2 +- lib/python/package.sh | 3 - lib/python/pyproject.toml | 8 +- lib/python/release.sh | 3 - lib/python/setup.py | 12 +- lib/python/test.sh | 3 - .../init => lib/python}/tests/conftest.py | 7 +- lib/python/tests/keycloak/rs256.key | 3 + lib/python/tests/keycloak/rsa256.pkey | 3 + lib/python/tests/opensearch/database.json | 1418 ++++++ .../test_integration_core_storage_client.py | 2 +- .../tests/test_unit_core_auth_client.py | 2 +- .../tests/test_unit_core_search_client.py | 3 +- lib/python/tests/test_unit_database.py | 4 + lib/python/tests/test_unit_query.py | 1 + lib/python/tests/test_unit_table.py | 5 +- lib/python/tests/test_unit_view.py | 1 + make/build.mk | 15 +- mkdocs.yml | 12 +- sonar-project.properties | 2 +- versions.json | 5 + 888 files changed, 24890 insertions(+), 11029 deletions(-) create mode 100644 .docs/.openapi/api-dashboard.yaml delete mode 100644 .docs/api/dashboard-service.md create mode 100644 .docs/concepts/dashboards.md delete mode 100644 .docs/concepts/ui.md create mode 100644 .docs/images/data-versioning.png create mode 100644 .docs/images/screenshots/dashboard-managed.png delete mode 100644 dbrepo-analyse-service/clients/keycloak_client.py delete mode 100644 dbrepo-analyse-service/lib/dbrepo-1.7.3-py3-none-any.whl delete mode 100644 dbrepo-analyse-service/lib/dbrepo-1.7.3.tar.gz create mode 100644 dbrepo-analyse-service/lib/dbrepo-1.8.0-py3-none-any.whl create mode 100644 dbrepo-analyse-service/lib/dbrepo-1.8.0.tar.gz delete mode 100644 dbrepo-analyse-service/tests/s3_config.json create mode 100644 dbrepo-dashboard-service/.coveragerc create mode 100644 dbrepo-dashboard-service/.gitignore create mode 100644 dbrepo-dashboard-service/Pipfile create mode 100644 dbrepo-dashboard-service/Pipfile.lock create mode 100644 dbrepo-dashboard-service/README.md delete mode 100644 dbrepo-dashboard-service/access.py create mode 100644 dbrepo-dashboard-service/app.py delete mode 100644 dbrepo-dashboard-service/clients/grafana_client.py delete mode 100644 dbrepo-dashboard-service/clients/keycloak_client.py delete mode 100644 dbrepo-dashboard-service/dashboard.py create mode 100644 dbrepo-dashboard-service/ds-yml/create_dashboard.yml create mode 100644 dbrepo-dashboard-service/ds-yml/update_dashboard.yml create mode 100644 dbrepo-dashboard-service/init/.coveragerc create mode 100644 dbrepo-dashboard-service/init/Dockerfile create mode 100644 dbrepo-dashboard-service/init/Pipfile create mode 100644 dbrepo-dashboard-service/init/Pipfile.lock create mode 100644 dbrepo-dashboard-service/init/app.py create mode 100644 dbrepo-dashboard-service/init/lib/dbrepo-1.8.0-py3-none-any.whl create mode 100644 dbrepo-dashboard-service/init/lib/dbrepo-1.8.0.tar.gz rename {dbrepo-search-service => dbrepo-dashboard-service}/init/tests/rsa/rs256.key (100%) rename {dbrepo-search-service => dbrepo-dashboard-service}/init/tests/rsa/rsa256.pkey (100%) create mode 100644 dbrepo-dashboard-service/init/tests/test_app.py create mode 100644 dbrepo-dashboard-service/lib/dbrepo-1.8.0-py3-none-any.whl create mode 100644 dbrepo-dashboard-service/lib/dbrepo-1.8.0.tar.gz delete mode 100644 dbrepo-dashboard-service/panel.py create mode 100644 dbrepo-dashboard-service/test.sh create mode 100644 dbrepo-dashboard-service/tests/conftest.py create mode 100644 dbrepo-dashboard-service/tests/grafana/__init__.py create mode 100644 dbrepo-dashboard-service/tests/rsa/rs256.key create mode 100644 dbrepo-dashboard-service/tests/rsa/rsa256.pkey create mode 100644 dbrepo-dashboard-service/tests/test_integration_app.py create mode 100644 dbrepo-dashboard-ui/Dockerfile rename dbrepo-dashboard-service/dashboards/system.json => dbrepo-dashboard-ui/dashboards/System/dbrepo.json (96%) rename {dbrepo-dashboard-service/dashboards => dbrepo-dashboard-ui/dashboards/System}/rabbitmq.json (99%) rename {dbrepo-dashboard-service => dbrepo-dashboard-ui}/grafana.ini (89%) rename {dbrepo-dashboard-service => dbrepo-dashboard-ui}/ldap.toml (92%) create mode 100644 dbrepo-dashboard-ui/provisioning/dashboards/provider.yaml create mode 100644 dbrepo-dashboard-ui/provisioning/datasources/infinity.yaml create mode 100644 dbrepo-dashboard-ui/provisioning/datasources/prometheus.yaml create mode 100644 dbrepo-gateway-service/data.json create mode 100644 dbrepo-grafana-service/.dockerignore create mode 100644 dbrepo-grafana-service/.gitignore create mode 100644 dbrepo-grafana-service/.mvn/wrapper/MavenWrapperDownloader.java create mode 100644 dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.jar create mode 100644 dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.properties create mode 100644 dbrepo-grafana-service/Dockerfile create mode 100644 dbrepo-grafana-service/README.md create mode 100755 dbrepo-grafana-service/mvnw create mode 100644 dbrepo-grafana-service/mvnw.cmd create mode 100644 dbrepo-grafana-service/pom.xml create mode 100644 dbrepo-grafana-service/rest-service/pom.xml create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/DbrepoGrafanaServiceApplication.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/AuthTokenFilter.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/CacheConfig.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/KeycloakConfig.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/WebSecurityConfig.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/DashboardConfigDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/HistogramConfigDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/PieChartConfigDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TableConfigDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeSeriesDto.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DashboardEndpoint.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DataEndpoint.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ContainerNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseMalformedException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/FormatNotAvailableException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/JsonProcessingException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/NotAllowedException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/PaginationException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryMalformedException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreCreateException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreGCException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreInsertException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStorePersistException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RemoteUnavailableException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RestTemplateExchangeException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceConnectionException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarExportException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarImportException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageUnavailableException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SyncDatabaseNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableExistsException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableMalformedException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/UserNotFoundException.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/KeycloakGateway.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/handlers/DashboardApiExceptionHandler.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/AbstractPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/CntAllPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/Dashboard.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/HistogramPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/MultiTimeSeriesPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/PieChartPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/RowPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/StatsPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TablePanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TimeSeriesPanel.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DashboardService.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataService.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataSourceService.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/TableService.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/ViewGeneratorService.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DashboardServiceImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataServiceImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataSourceServiceImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/TableServiceImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/ViewGeneratorServiceImpl.java create mode 100644 dbrepo-grafana-service/rest-service/src/main/resources/application-local.yml create mode 100644 dbrepo-grafana-service/rest-service/src/main/resources/application.yml rename dbrepo-search-service/init/omlib/__init__.py => dbrepo-grafana-service/rest-service/src/test/resources/application.properties (100%) delete mode 100644 dbrepo-metadata-service/api/pom.xml delete mode 100644 dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java delete mode 100644 dbrepo-metadata-service/entities/pom.xml delete mode 100644 dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameType.java rename dbrepo-metadata-service/oai/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/oaipmh/OaiErrorType.java (91%) rename dbrepo-metadata-service/oai/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/oaipmh/OaiListIdentifiersParameters.java (97%) rename dbrepo-metadata-service/oai/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/oaipmh/OaiListRecordsParameters.java (97%) rename dbrepo-metadata-service/oai/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/oaipmh/OaiRecordParameters.java (93%) rename dbrepo-metadata-service/oai/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/oaipmh/RequestParameters.java (90%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mapper/SparqlMapper.java (97%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/BannerMessageRepository.java (72%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/ConceptRepository.java (71%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/ContainerRepository.java (81%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/DatabaseRepository.java (87%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/IdentifierRepository.java (91%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/ImageRepository.java (77%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/LicenseRepository.java (73%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/OntologyRepository.java (78%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/TableRepository.java (69%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/UnitRepository.java (71%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/UserRepository.java (80%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/repository/ViewRepository.java (71%) rename dbrepo-metadata-service/repositories/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/utils/EnumToStringConverter.java (92%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien/DbrepoMetadataServiceApplication.java => ac/tuwien/ifs/dbrepo/MetadataServiceApplication.java} (64%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/MvcConfig.java (71%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/SwaggerConfig.java (98%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/converters/IdentifierStatusTypeDtoConverter.java (75%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/converters/IdentifierTypeDtoConverter.java (75%) create mode 100644 dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpoint.java rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/AccessEndpoint.java (89%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ConceptEndpoint.java (90%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ContainerEndpoint.java (92%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/DatabaseEndpoint.java (88%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/IdentifierEndpoint.java (97%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ImageEndpoint.java (91%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/LicenseEndpoint.java (91%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/MessageEndpoint.java (92%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/MetadataEndpoint.java (94%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/OntologyEndpoint.java (94%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/TableEndpoint.java (89%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/UnitEndpoint.java (90%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/UserEndpoint.java (93%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ViewEndpoint.java (85%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/handlers/ApiExceptionHandler.java (96%) rename dbrepo-metadata-service/rest-service/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/validation/EndpointValidator.java (94%) delete mode 100644 dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/ApplicationIntegrationTest.java (86%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/ObjectMapperConfig.java (95%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/RabbitConfig.java (91%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/converters/IdentifierStatusTypeDtoConverterUnitTest.java (75%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/converters/IdentifierTypeDtoConverterUnitTest.java (75%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/AbstractEndpointUnitTest.java (56%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/AccessEndpointUnitTest.java (86%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ActuatorComponentTest.java (85%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ConceptEndpointUnitTest.java (77%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ContainerEndpointUnitTest.java (85%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/DatabaseEndpointUnitTest.java (88%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/IdentifierEndpointUnitTest.java (92%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ImageEndpointUnitTest.java (76%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/LicenseEndpointUnitTest.java (82%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/MessageEndpointUnitTest.java (87%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/MetadataEndpointUnitTest.java (92%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/OntologyEndpointUnitTest.java (91%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/TableEndpointUnitTest.java (78%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/UnitEndpointUnitTest.java (77%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/UserEndpointUnitTest.java (88%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/endpoints/ViewEndpointUnitTest.java (77%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien/entities => ac/tuwien/ifs/dbrepo/entity}/EntitiesUnitTest.java (64%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/BrokerServiceGatewayUnitTest.java (94%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/CrossrefGatewayUnitTest.java (83%) create mode 100644 dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGatewayUnitTest.java rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/DataServiceGatewayUnitTest.java (97%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/KeycloakGatewayIntegrationTest.java (87%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/OrcidGatewayUnitTest.java (82%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/RorGatewayUnitTest.java (77%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/SearchServiceGatewayUnitTest.java (93%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/handlers/ApiExceptionHandlerTest.java (95%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mapper/MetadataMapperUnitTest.java (91%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/ActuatorEndpointMvcTest.java (90%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/AuthenticationPrivilegedIntegrationMvcTest.java (87%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/IdentifierEndpointMvcTest.java (86%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/MetadataEndpointMvcTest.java (93%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/OpenApiEndpointMvcTest.java (91%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/mvc/PrometheusEndpointMvcTest.java (94%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/AccessServiceUnitTest.java (94%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/AuthenticationServiceIntegrationTest.java (80%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/BrokerServiceIntegrationTest.java (88%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ConceptServiceUnitTest.java (80%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ContainerServiceUnitTest.java (84%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/DataCiteIdentifierServicePersistenceTest.java (89%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/DatabaseServicePersistenceTest.java (66%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/DatabaseServiceUnitTest.java (88%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/EntityServiceUnitTest.java (86%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/IdentifierServicePersistenceTest.java (92%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ImageServicePersistenceTest.java (65%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ImageServiceUnitTest.java (76%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/LicenseServiceUnitTest.java (79%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/MessageServiceUnitTest.java (85%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/MetadataServiceUnitTest.java (88%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/StorageServiceIntegrationTest.java (89%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/TableServicePersistenceTest.java (84%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/TableServiceUnitTest.java (89%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UnitServiceUnitTest.java (80%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UserServiceIntegrationTest.java (75%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UserServicePersistenceTest.java (84%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UserServiceUnitTest.java (82%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ViewServicePersistenceTest.java (78%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ViewServiceUnitTest.java (86%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/utils/AmqpUtils.java (98%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/utils/H2Utils.java (96%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/utils/KeycloakUtils.java (90%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/utils/XmlUtils.java (96%) rename dbrepo-metadata-service/rest-service/src/test/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/validator/EndpointValidatorUnitTest.java (94%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/auth/AuthTokenFilter.java (95%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/auth/BasicAuthenticationProvider.java (84%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/auth/InternalRequestInterceptor.java (87%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/CacheConfig.java (89%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/DataCiteConfig.java (97%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/EndpointConfig.java (86%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/GatewayConfig.java (82%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/JacksonConfig.java (84%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/JenaConfig.java (92%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/KeycloakConfig.java (96%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/MetadataConfig.java (93%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/MetricsConfig.java (90%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/RabbitConfig.java (93%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/S3Config.java (97%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/SecurityConfig.java (91%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/TemplateConfig.java (96%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/config/WebSecurityConfig.java (95%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/BrokerServiceGateway.java (85%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/CrossrefGateway.java (70%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGateway.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/DataServiceGateway.java (90%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/KeycloakGateway.java (65%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/OrcidGateway.java (69%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/RorGateway.java (69%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/SearchServiceGateway.java (60%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/BrokerServiceGatewayImpl.java (94%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/CrossrefGatewayImpl.java (83%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DashboardServiceGatewayImpl.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/DataServiceGatewayImpl.java (96%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/KeycloakGatewayImpl.java (90%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/OrcidGatewayImpl.java (82%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/RorGatewayImpl.java (83%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/gateway/impl/SearchServiceGatewayImpl.java (87%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AccessService.java create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationService.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/BannerMessageService.java (81%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BrokerService.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ConceptService.java (75%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ContainerService.java (75%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/CredentialService.java (80%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DashboardService.java create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/EntityService.java (54%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/IdentifierService.java (54%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/ImageService.java (73%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/LicenseService.java (74%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/MetadataService.java (62%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/OntologyService.java (72%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/StorageService.java (73%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/TableService.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UnitService.java (63%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/UserService.java (68%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ViewService.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/AccessServiceImpl.java (87%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/AuthenticationServiceImpl.java (62%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/BannerMessageServiceImpl.java (82%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/BrokerServiceRabbitMqImpl.java (88%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/ConceptServiceImpl.java (80%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/ContainerServiceImpl.java (84%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/CredentialServiceImpl.java (85%) create mode 100644 dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DashboardServiceImpl.java rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/DataCiteIdentifierServiceImpl.java (83%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/DatabaseServiceImpl.java (85%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/EntityServiceImpl.java (91%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/IdentifierServiceImpl.java (90%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/ImageServiceImpl.java (85%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/LicenseServiceImpl.java (76%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/MetadataServiceImpl.java (87%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/OntologyServiceImpl.java (84%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/StorageServiceS3Impl.java (88%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/TableServiceImpl.java (89%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/UnitServiceImpl.java (80%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/UserServiceImpl.java (79%) rename dbrepo-metadata-service/services/src/main/java/at/{tuwien => ac/tuwien/ifs/dbrepo}/service/impl/ViewServiceImpl.java (67%) delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java delete mode 100644 dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java delete mode 100644 dbrepo-search-service/.testpickle delete mode 100644 dbrepo-search-service/examples/database/fields_response_payload.json delete mode 100644 dbrepo-search-service/examples/database/search_request_payload.json delete mode 100644 dbrepo-search-service/examples/unit/fields_response_payload.json delete mode 100644 dbrepo-search-service/examples/unit/search_request_payload.json create mode 100644 dbrepo-search-service/friendly_names_overrides.json delete mode 100644 dbrepo-search-service/init/clients/keycloak_client.py delete mode 100644 dbrepo-search-service/init/lib/dbrepo-1.7.3-py3-none-any.whl delete mode 100644 dbrepo-search-service/init/lib/dbrepo-1.7.3.tar.gz create mode 100644 dbrepo-search-service/init/lib/dbrepo-1.8.0-py3-none-any.whl create mode 100644 dbrepo-search-service/init/lib/dbrepo-1.8.0.tar.gz delete mode 100644 dbrepo-search-service/init/tests/test_app.py create mode 100644 dbrepo-search-service/init/tests/test_unit_app.py delete mode 100644 dbrepo-search-service/lib/dbrepo-1.7.3-py3-none-any.whl delete mode 100644 dbrepo-search-service/lib/dbrepo-1.7.3.tar.gz create mode 100644 dbrepo-search-service/lib/dbrepo-1.8.0-py3-none-any.whl create mode 100644 dbrepo-search-service/lib/dbrepo-1.8.0.tar.gz rename dbrepo-search-service/os-yml/{update_database.yml => save_database.yml} (75%) delete mode 100644 dbrepo-search-service/tests/.testpickle delete mode 100644 dbrepo-search-service/tests/test_jwt.py create mode 100644 grafana/grafana.ini create mode 100644 lib/java/dbrepo-core/.gitignore create mode 100644 lib/java/dbrepo-core/Dockerfile create mode 100644 lib/java/dbrepo-core/pom.xml create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/Serialize.java rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/CacheableDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api}/ExportResourceDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/ChannelDetailsDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/ConsumerDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/CreateExchangeDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/CreateUserDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/CreateVirtualHostDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/ExchangeDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/GrantExchangePermissionsDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/GrantVirtualHostPermissionsDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/QueueBriefDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/QueueDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/TopicPermissionDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/UserDetailsDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/amqp/VirtualHostPermissionDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/auth/CreateUserDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/auth/RealmAccessDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/ContainerActionTypeDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/ContainerBriefDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/ContainerDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/CreateContainerDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/DataTypeDto.java (97%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/ImageBriefDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/ImageChangeDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/ImageCreateDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/ImageDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/container/image/OperatorDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/crossref/CrossrefDto.java (74%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/crossref/form/CrossrefLiteralFormDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/crossref/label/CrossrefLabelDto.java (75%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/crossref/label/CrossrefPrefLabelDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/AccessTypeDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/CreateAccessDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/CreateDatabaseDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/CreateViewDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseAccessDto.java (84%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseBriefDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseDto.java (70%) create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyDashboardDto.java rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseModifyImageDto.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseModifyVisibilityDto.java (76%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/DatabaseTransferDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/LanguageTypeDto.java (98%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/LicenseDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/LoadFileDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/ViewBriefDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/ViewColumnDto.java (76%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/ViewDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/ViewUpdateDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/internal/CreateDatabaseDto.java (79%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/ExecuteStatementDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/ExportDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/FilterDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/FilterTypeDto.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/ImportDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/OrderDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/OrderTypeDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/QueryBriefDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/QueryDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/QueryPersistDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/QueryTypeDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/SaveStatementDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/query/SubsetDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/CreateTableDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/HistoryEventTypeDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table}/SortType.java (76%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table}/SortTypeDto.java (73%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableBriefDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableCreateRawQuery.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableHistoryDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableInsertRawQuery.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableStatisticDto.java (67%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TableUpdateDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TupleDeleteDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TupleDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/TupleUpdateDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/ColumnBriefDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/ColumnDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/ColumnStatisticDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/ColumnTypeDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/CreateTableColumnDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/EnumDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/SetDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/SiUnitDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/ConceptBriefDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/ConceptDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/ConceptSaveDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/UnitBriefDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/UnitDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/columns/concepts/UnitSaveDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/ConstraintsDto.java (64%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/CreateTableConstraintsDto.java (79%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/foreign/CreateForeignKeyDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/foreign/ForeignKeyBriefDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/foreign/ForeignKeyDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java (81%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/foreign/ReferenceTypeDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/primary/PrimaryKeyDto.java (68%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/constraints/unique/UniqueDto.java (72%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/database/table/internal/TableCreateDto.java (80%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/DataCiteBody.java (84%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/DataCiteData.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/DataCiteError.java (84%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteCreateDoi.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoi.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiCreator.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiCreatorAffiliation.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiEvent.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiFundingReference.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiRelatedIdentifier.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiRights.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiTitle.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteDoiTypes.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/datacite/doi/DataCiteNameType.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/error/ApiErrorDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/file/UploadResponseDto.java (86%) create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/AccessTypeDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardResponseDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceTypeDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/PermissionTypeDto.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/UpdateDashboardAccessDto.java rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/AffiliationIdentifierSchemeTypeDto.java (67%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/BibliographyTypeDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/CreateIdentifierDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/CreatorBriefDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/CreatorDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/DescriptionTypeDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierBriefDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierDescriptionDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierFunderDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierFunderTypeDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierSaveDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierStatusTypeDto.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierTitleDto.java (84%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/IdentifierTypeDto.java (84%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/LinksDto.java (77%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/NameIdentifierSchemeTypeDto.java (68%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/NameTypeDto.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/RelatedIdentifierDto.java (69%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/RelatedTypeDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/RelationTypeDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/SaveIdentifierCreatorDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/SaveIdentifierDescriptionDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/SaveIdentifierFunderDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/SaveIdentifierTitleDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/SaveRelatedIdentifierDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/TitleTypeDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/ld/LdCreatorDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/identifier/ld/LdDatasetDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/CredentialDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/CredentialTypeDto.java (79%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/ModifyUserDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/RoleRepresentationDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/TokenDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/UpdateCredentialsDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/UserAttributesDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/UserCreateAttributesDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/UserCreateDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/keycloak/UserIdAttributesDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/ldap/UserDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/maintenance/BannerMessageBriefDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/maintenance/BannerMessageCreateDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/maintenance/BannerMessageDto.java (96%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/maintenance/BannerMessageTypeDto.java (83%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/maintenance/BannerMessageUpdateDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/OrcidDto.java (66%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/OrcidActivitiesSummaryDto.java (65%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/OrcidEmploymentsDto.java (66%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java (57%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java (63%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java (69%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java (60%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java (78%) create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/person/OrcidPersonDto.java (64%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/person/name/OrcidNameDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/orcid/person/name/OrcidValueDto.java (79%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/ror/RorDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/EntityDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/OntologyBriefDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/OntologyCreateDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/OntologyDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/OntologyModifyDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/semantics/TableColumnEntityDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/ExchangeUpdatePermissionsDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/GrantedAuthorityDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/RoleTypeDto.java (85%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserAttributesDto.java (94%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserBriefDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserDetailsDto.java (95%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserDto.java (92%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserEmailDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserForgotDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserModifyPasswordDto.java (90%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserPasswordDto.java (86%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserResetDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserRolesDto.java (87%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserThemeSetDto.java (88%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserUpdateDto.java (93%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/UserUpdatePermissionsDto.java (89%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/external/ExternalMetadataDto.java (78%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/external/ExternalResultType.java (82%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/external/affiliation/ExternalAffiliationDto.java (91%) rename {dbrepo-metadata-service/api/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/api/user/internal/UpdateUserPasswordDto.java (85%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/container/Container.java (88%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/container/image/ContainerImage.java (95%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/container/image/DataType.java (97%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/container/image/Operator.java (94%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/AccessType.java (63%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/Database.java (86%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/DatabaseAccess.java (89%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/DatabaseAccessKey.java (80%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/LanguageType.java (97%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/License.java (91%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/View.java (96%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/ViewColumn.java (92%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/Table.java (91%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/ColumnEnum.java (89%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/ColumnSet.java (89%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/TableColumn.java (96%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/TableColumnConcept.java (95%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/TableColumnType.java (85%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/columns/TableColumnUnit.java (95%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/Constraints.java (71%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/foreignKey/ForeignKey.java (92%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/foreignKey/ForeignKeyReference.java (89%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/foreignKey/ReferenceType.java (67%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/primaryKey/PrimaryKey.java (85%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/database/table/constraints/unique/Unique.java (87%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/AffiliationIdentifierSchemeType.java (66%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/Creator.java (96%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/DescriptionType.java (82%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/Identifier.java (95%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierDescription.java (93%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierFunder.java (93%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierFunderType.java (64%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierStatusType.java (53%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierTitle.java (93%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/IdentifierType.java (60%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/NameIdentifierSchemeType.java (66%) create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameType.java rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/RelatedIdentifier.java (97%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/RelatedType.java (85%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/RelationType.java (94%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/identifier/TitleType.java (79%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/maintenance/BannerMessage.java (93%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/maintenance/BannerMessageType.java (65%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/semantics/Ontology.java (94%) rename {dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity}/user/User.java (93%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/AccessNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/AccountNotSetupException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/AnalyseServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/AuthServiceConnectionException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/AuthServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/BrokerServiceConnectionException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/BrokerServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ConceptNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ContainerAlreadyExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ContainerNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ContainerQuotaException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/CredentialsInvalidException.java (91%) create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceConnectionException.java create mode 100644 lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceException.java rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DataServiceConnectionException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DataServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DatabaseMalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DatabaseNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DatabaseUnavailableException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/DoiNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/EmailExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ExchangeNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ExternalServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/FilterBadRequestException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/FormatNotAvailableException.java (90%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/IdentifierNotFoundException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/IdentifierNotSupportedException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ImageAlreadyExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ImageInvalidException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ImageNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/LicenseNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/MalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/MessageNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/MetadataServiceConnectionException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/MetadataServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/NotAllowedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/OntologyNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/OrcidNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/PaginationException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryMalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryNotSupportedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryStoreCreateException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryStoreGCException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryStoreInsertException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueryStorePersistException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/QueueNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/RemoteUnavailableException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/RorNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/SearchServiceConnectionException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/SearchServiceException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/SemanticEntityNotFoundException.java (92%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/SortException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/StorageNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/StorageUnavailableException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/TableExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/TableMalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/TableNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/TableSchemaException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/UnitNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/UriMalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/UserExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/UserNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ViewExistsException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ViewMalformedException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ViewNotFoundException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/exception/ViewSchemaException.java (91%) rename {dbrepo-metadata-service/repositories/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/mapper/MetadataMapper.java (79%) rename {dbrepo-metadata-service/test/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/test/BaseTest.java (69%) rename {dbrepo-metadata-service/test/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/test/dto/LocaleDto.java (86%) rename {dbrepo-metadata-service => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/test/pom.xml (94%) rename {dbrepo-metadata-service/test/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/test/utils/ArrayUtils.java (87%) rename {dbrepo-metadata-service/test/src/main/java/at/tuwien => lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core}/test/utils/EndpointUtils.java (94%) delete mode 100644 lib/python/Makefile rename {dbrepo-search-service/init/omlib/exceptions => lib/python/dbrepo/core}/__init__.py (100%) rename {dbrepo-search-service/init/omlib/rdf => lib/python/dbrepo/core/api}/__init__.py (100%) rename {dbrepo-dashboard-service => lib/python/dbrepo/core}/api/dto.py (91%) create mode 100644 lib/python/dbrepo/core/api/exceptions.py create mode 100644 lib/python/dbrepo/core/client/__init__.py create mode 100644 lib/python/dbrepo/core/client/auth.py create mode 100644 lib/python/dbrepo/core/client/dashboard.py rename dbrepo-search-service/init/clients/opensearch_client.py => lib/python/dbrepo/core/client/search.py (88%) rename dbrepo-analyse-service/clients/s3_client.py => lib/python/dbrepo/core/client/storage.py (86%) create mode 100644 lib/python/dbrepo/core/omlib/__init__.py rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/constants.py (96%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/dimension.py (96%) create mode 100644 lib/python/dbrepo/core/omlib/exceptions/__init__.py rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/exceptions/dimensionexception.py (100%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/exceptions/unitconversionexception.py (100%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/exceptions/unitidentityexception.py (100%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/measure.py (98%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/omconstants.py (99%) create mode 100644 lib/python/dbrepo/core/omlib/rdf/__init__.py rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/rdf/om-2.0.rdf (100%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/scale.py (95%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/thing.py (100%) rename {dbrepo-search-service/init => lib/python/dbrepo/core}/omlib/unit.py (99%) delete mode 100755 lib/python/package.sh delete mode 100755 lib/python/release.sh delete mode 100644 lib/python/test.sh rename {dbrepo-search-service/init => lib/python}/tests/conftest.py (90%) create mode 100644 lib/python/tests/keycloak/rs256.key create mode 100644 lib/python/tests/keycloak/rsa256.pkey create mode 100644 lib/python/tests/opensearch/database.json rename dbrepo-analyse-service/tests/test_s3_client.py => lib/python/tests/test_integration_core_storage_client.py (98%) rename dbrepo-search-service/init/tests/test_keycloak_client.py => lib/python/tests/test_unit_core_auth_client.py (97%) rename dbrepo-search-service/init/tests/test_opensearch_client.py => lib/python/tests/test_unit_core_search_client.py (99%) diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 32dafae1ec..973b1cb890 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -6,7 +6,7 @@ volumes: search-db-data: identity-service-data: metric-db-data: - dashboard-service-data: + dashboard-ui-data: services: dbrepo-metadata-db: @@ -42,8 +42,10 @@ services: ports: - "3307:3306" environment: - MARIADB_ROOT_PASSWORD: "${DATA_DB_PASSWORD:-dbrepo}" MARIADB_GALERA_MARIABACKUP_PASSWORD: "${DATA_DB_BACKUP_PASSWORD:-dbrepobackup}" + MARIADB_PASSWORD: "${READONLY_PASSWORD:-user}" + MARIADB_ROOT_PASSWORD: "${DATA_DB_PASSWORD:-dbrepo}" + MARIADB_USER: "${READONLY_USERNAME:-user}" healthcheck: test: mysqladmin ping --user=root --password="${DATA_DB_PASSWORD:-dbrepo}" --silent interval: 10s @@ -99,7 +101,7 @@ services: SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: - test: curl -fsS localhost:8080/realms/master + test: curl -fsS http://localhost:8080/realms/master interval: 10s timeout: 5s retries: 12 @@ -115,7 +117,7 @@ services: init: true restart: "no" container_name: dbrepo-auth-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.8.0 environment: AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} @@ -123,6 +125,7 @@ services: METADATA_DB: "${METADATA_DB:-dbrepo}" METADATA_DB_PASSWORD: "${METADATA_DB_PASSWORD:-dbrepo}" METADATA_USERNAME: "root" + READONLY_USERNAME: "${READONLY_USERNAME:-user}" SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" depends_on: dbrepo-auth-service: @@ -138,7 +141,7 @@ services: restart: "no" container_name: dbrepo-metadata-service hostname: metadata-service - image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.8.0 environment: ADMIN_EMAIL: "${ADMIN_EMAIL:-noreply@localhost}" ANALYSE_SERVICE_ENDPOINT: "${ANALYSE_SERVICE_ENDPOINT:-http://analyse-service:8080}" @@ -157,6 +160,7 @@ services: BROKER_USERNAME: ${SYSTEM_USERNAME:-admin} BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" CROSSREF_ENDPOINT: "${CROSSREF_ENDPOINT:-http://data.crossref.org}" + DASHBOARD_SERVICE_ENDPOINT: "${DASHBOARD_SERVICE_ENDPOINT:-http://dashboard-service:8080}" DATA_SERVICE_ENDPOINT: ${DATA_SERVICE_ENDPOINT:-http://data-service:8080} DELETED_RECORD: "${DELETED_RECORD:-persistent}" GRANULARITY: "${GRANULARITY:-YYYY-MM-DDThh:mm:ssZ}" @@ -190,6 +194,10 @@ services: condition: service_healthy dbrepo-data-service: condition: service_healthy + dbrepo-dashboard-service: + condition: service_healthy + dbrepo-search-service: + condition: service_healthy dbrepo-metadata-db: condition: service_healthy logging: @@ -199,7 +207,7 @@ services: restart: "no" container_name: dbrepo-analyse-service hostname: analyse-service - image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.8.0 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -252,7 +260,7 @@ services: restart: "no" container_name: dbrepo-search-db hostname: search-db - image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.8.0 healthcheck: test: curl -sSL localhost:9200/_plugins/_security/health | jq .status | grep UP interval: 10s @@ -276,7 +284,7 @@ services: restart: "no" container_name: dbrepo-search-service hostname: search-service - image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.8.0 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -295,12 +303,14 @@ services: interval: 10s timeout: 5s retries: 12 + logging: + driver: json-file dbrepo-ui: restart: "no" container_name: dbrepo-ui hostname: ui - image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.8.0 environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://gateway-service}" @@ -317,7 +327,7 @@ services: dbrepo-search-service: condition: service_healthy healthcheck: - test: curl -fsSL http://127.0.0.1:3000 && curl -fsSL http://127.0.0.1:3000/health + test: curl -fsSL 127.0.0.1:3000 && curl -fsSL 127.0.0.1:3000/health interval: 10s timeout: 5s retries: 12 @@ -335,6 +345,11 @@ services: - "80:8080" volumes: - ./config/dbrepo.conf:/etc/nginx/conf.d/default.conf + healthcheck: + test: service nginx status || exit 1 + interval: 10s + timeout: 5s + retries: 12 depends_on: dbrepo-analyse-service: condition: service_healthy @@ -359,8 +374,8 @@ services: environment: LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" - LDAP_USERS: "${SYSTEM_USERNAME:-admin}" - LDAP_PASSWORDS: "${SYSTEM_PASSWORD:-admin}" + LDAP_USERS: "${SYSTEM_USERNAME:-admin},${READONLY_USERNAME:-user}" + LDAP_PASSWORDS: "${SYSTEM_PASSWORD:-admin},${READONLY_PASSWORD:-user}" LDAP_GROUP: "${ADMIN_GROUP:-system}" LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" LDAP_ADMIN_DN: "${IDENTITY_SERVICE_ADMIN_DN:-cn=admin,dc=dbrepo,dc=at}" @@ -377,7 +392,7 @@ services: init: true container_name: dbrepo-search-service-init hostname: search-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.8.0 environment: LOG_LEVEL: ${LOG_LEVEL:-info} METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} @@ -395,6 +410,26 @@ services: logging: driver: json-file + dbrepo-dashboard-service-init: + restart: "no" + init: true + container_name: dbrepo-dashboard-service-init + hostname: search-dashboard-init + image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service-init:1.8.0 + environment: + LOG_LEVEL: ${LOG_LEVEL:-info} + DASHBOARD_UI_ENDPOINT: "${DASHBOARD_UI_ENDPOINT:-http://dashboard-ui:3000}" + METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" + depends_on: + dbrepo-dashboard-ui: + condition: service_healthy + dbrepo-metadata-service: + condition: service_healthy + logging: + driver: json-file + dbrepo-storage-service: restart: "no" container_name: dbrepo-storage-service @@ -420,7 +455,6 @@ services: hostname: metric-db image: docker.io/bitnami/prometheus:2.54.1-debian-12-r4 volumes: - - ./config/prometheus.yml:/etc/prometheus/prometheus.yml - ./config/prometheus.yml:/etc/prometheus/prometheus.yml - metric-db-data:/opt/bitnami/prometheus/data healthcheck: @@ -431,38 +465,12 @@ services: logging: driver: json-file - dbrepo-dashboard-service: - restart: "no" - container_name: dbrepo-dashboard-service - hostname: dashboard-service - image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.7.3 - ports: - - "3000:3000" - volumes: - - dashboard-service-data:/opt/bitnami/grafana/data - environment: - GF_SERVER_DOMAIN: "dashboard-service" - GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: "true" - LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" - LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" - LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" - healthcheck: - test: curl -fsSL --head http://127.0.0.1:3000 - interval: 10s - timeout: 5s - retries: 12 - depends_on: - dbrepo-metric-db: - condition: service_started - logging: - driver: json-file - dbrepo-storage-service-init: restart: "no" init: true container_name: dbrepo-storage-service-init hostname: storage-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.8.0 environment: S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-seaweedfsadmin} S3_BUCKET: "${S3_BUCKET:-dbrepo}" @@ -478,7 +486,7 @@ services: restart: "no" container_name: dbrepo-data-service hostname: data-service - image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.7.3 + image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.8.0 environment: AUTH_SERVICE_ADMIN: "${AUTH_SERVICE_ADMIN:-admin}" AUTH_SERVICE_ADMIN_PASSWORD: "${AUTH_SERVICE_ADMIN_PASSWORD:-admin}" @@ -522,3 +530,62 @@ services: condition: service_healthy logging: driver: json-file + + dbrepo-dashboard-ui: + restart: "no" + container_name: dbrepo-dashboard-ui + hostname: dashboard-ui + image: dbrepo-dashboard-ui:latest + build: + context: ./dbrepo-dashboard-ui + network: host + ports: + - "3000:3000" + volumes: + - dashboard-ui-data:/opt/bitnami/grafana/data + environment: + BASE_URL: "${BASE_URL:-http://localhost}" + GF_INSTALL_PLUGINS: "yesoreyeram-infinity-datasource" + GF_SERVER_DOMAIN: "dashboard-service" + GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: "true" + LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" + LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" + LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" + healthcheck: + test: curl -fsSL --head 127.0.0.1:3000 + interval: 10s + timeout: 5s + retries: 12 + depends_on: + dbrepo-metric-db: + condition: service_started + extra_hosts: + - "localhost:host-gateway" + logging: + driver: json-file + + dbrepo-dashboard-service: + restart: "no" + container_name: dbrepo-dashboard-service + hostname: dashboard-service + image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.8.0 + ports: + - "4070:8080" + environment: + AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} + AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} + AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} + BASE_URL: "${BASE_URL:-http://localhost}" + DASHBOARD_UI_ENDPOINT: "${DASHBOARD_UI_ENDPOINT:-http://dashboard-ui:3000}" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" + healthcheck: + test: curl -fsSL --head 127.0.0.1:8080/health + interval: 10s + timeout: 5s + retries: 12 + depends_on: + dbrepo-metric-db: + condition: service_started + logging: + driver: json-file diff --git a/.docs/.openapi/api-analyse.yaml b/.docs/.openapi/api-analyse.yaml index 25e15521d5..b347692d48 100644 --- a/.docs/.openapi/api-analyse.yaml +++ b/.docs/.openapi/api-analyse.yaml @@ -24,16 +24,29 @@ }, "type": "object" }, + "ApiError": { + "properties": { + "code": { + "example": "error.dashboard.create", + "type": "string" + }, + "message": { + "example": "Message", + "type": "string" + }, + "status": { + "example": "BAD_REQUEST", + "type": "string" + } + }, + "type": "object" + }, "ColumnAnalysisDto": { "properties": { "d": { "example": 4, "type": "integer" }, - "dfid": { - "example": null, - "type": "integer" - }, "enums": { "example": null, "properties": { @@ -62,19 +75,6 @@ }, "type": "object" }, - "ErrorDto": { - "properties": { - "message": { - "example": "Message", - "type": "string" - }, - "success": { - "example": false, - "type": "boolean" - } - }, - "type": "object" - }, "KeysDto": { "properties": { "keys": { @@ -111,7 +111,7 @@ }, "externalDocs": { "description": "Sourcecode Documentation", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/" }, "info": { "contact": { @@ -124,7 +124,7 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0" }, "title": "Database Repository Analyse Service API", - "version": "1.5" + "version": "1.8.0" }, "openapi": "3.0.0", "paths": { @@ -322,7 +322,7 @@ "servers": [ { "description": "Generated server url", - "url": "http://localhost:5000" + "url": "http://localhost" }, { "description": "Sandbox", diff --git a/.docs/.openapi/api-dashboard.yaml b/.docs/.openapi/api-dashboard.yaml new file mode 100644 index 0000000000..54a27444f6 --- /dev/null +++ b/.docs/.openapi/api-dashboard.yaml @@ -0,0 +1 @@ +"<!doctype html> <html lang=en> <title>500 Internal Server Error</title> <h1>Internal Server Error</h1> <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>" diff --git a/.docs/.openapi/api-data.yaml b/.docs/.openapi/api-data.yaml index 1e4dca4cd3..1f83f8ec5e 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.7.3 + version: 1.8.0 externalDocs: description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7.3/system-services-metadata/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8.0/system-services-metadata/ servers: - url: http://localhost description: Development instance @@ -63,32 +63,32 @@ paths: schema: type: string responses: - "403": - description: Not allowed to retrieve view data + "406": + description: Failed to format data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find view in metadata database + "409": + description: View schema could not be mapped 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" - "406": - description: Failed to format data + "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 + "400": + description: Request pagination is malformed content: application/json: schema: @@ -109,8 +109,8 @@ paths: schema: type: string text/csv: {} - "503": - description: Failed to establish connection with the metadata service + "403": + description: Not allowed to retrieve view data content: application/json: schema: @@ -162,32 +162,32 @@ paths: schema: type: string responses: - "403": - description: Not allowed to retrieve view data + "406": + description: Failed to format data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find view in metadata database + "409": + description: View schema could not be mapped 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" - "406": - description: Failed to format data + "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 + "400": + description: Request pagination is malformed content: application/json: schema: @@ -208,8 +208,8 @@ paths: schema: type: string text/csv: {} - "503": - description: Failed to establish connection with the metadata service + "403": + description: Not allowed to retrieve view data content: application/json: schema: @@ -264,12 +264,30 @@ paths: schema: type: string responses: + "406": + description: Failed to format data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "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: Not allowed to get table data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "400": description: Request pagination or table data select query is malformed content: @@ -292,24 +310,6 @@ paths: schema: type: string text/csv: {} - "406": - description: Failed to format data - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to get table data - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -346,28 +346,28 @@ paths: $ref: "#/components/schemas/TupleUpdateDto" required: true responses: - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "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" - "202": - description: Updated table data - "503": - description: Failed to establish connection with the metadata service + "403": + description: Update table data not allowed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Update table data not allowed + "202": + description: Updated table data + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: @@ -408,30 +408,30 @@ paths: $ref: "#/components/schemas/TupleDto" required: true responses: - "400": - description: Request pagination or table data select query is malformed + "503": + description: Failed to establish connection with the metadata service or + storage service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Create table data not allowed + "404": + description: Failed to find table in metadata database or blob in storage + service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service or - storage service + "201": + description: Created table data + "400": + description: Request pagination or table data select query is malformed content: 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 + "403": + description: Create table data not allowed content: application/json: schema: @@ -472,28 +472,28 @@ paths: $ref: "#/components/schemas/TupleDeleteDto" required: true responses: - "404": - description: Failed to find table in metadata database + "403": + description: Delete table data not allowed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Request pagination or table data select query is malformed + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Delete table data not allowed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "202": description: Deleted table data - "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: @@ -547,12 +547,30 @@ paths: schema: type: string responses: + "406": + description: Failed to format data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "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: Not allowed to get table data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "400": description: Request pagination or table data select query is malformed content: @@ -575,24 +593,6 @@ paths: schema: type: string text/csv: {} - "406": - description: Failed to format data - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to get table data - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -643,13 +643,6 @@ paths: type: integer format: int64 responses: - "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: @@ -662,8 +655,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Invalid pagination + "503": + description: Failed to communicate with database content: application/json: schema: @@ -690,8 +683,15 @@ paths: schema: type: string text/csv: {} - "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" + "400": + description: Invalid pagination content: application/json: schema: @@ -745,13 +745,6 @@ paths: type: integer format: int64 responses: - "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: @@ -764,8 +757,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Invalid pagination + "503": + description: Failed to communicate with database content: application/json: schema: @@ -792,8 +785,15 @@ paths: schema: type: string text/csv: {} - "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" + "400": + description: Invalid pagination content: application/json: schema: @@ -828,19 +828,6 @@ paths: $ref: "#/components/schemas/QueryPersistDto" required: true responses: - "403": - description: Not allowed to persist subset - 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" "202": description: Persisted subset content: @@ -865,6 +852,19 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not allowed to persist subset + 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" security: - bearerAuth: [] - basicAuth: [] @@ -939,16 +939,10 @@ paths: $ref: "#/components/schemas/ImportDto" required: true responses: - "404": - description: Failed to find table in metadata database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "202": description: Imported dataset successfully - "400": - description: Dataset and/or query are malformed + "403": + description: Import table dataset not allowed content: application/json: schema: @@ -959,8 +953,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Import table dataset not allowed + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Dataset and/or query are malformed content: application/json: schema: @@ -1000,9 +1000,8 @@ paths: 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 + "503": + description: Failed to communicate with database content: application/json: schema: @@ -1013,8 +1012,9 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "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: @@ -1063,51 +1063,51 @@ paths: $ref: "#/components/schemas/SubsetDto" required: true responses: - "403": - description: Not allowed to find subset + "417": + description: Failed to insert query into query store of data database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "501": - description: Failed to execute query as it contains non-supported keywords + "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 + "406": + description: Failed to format data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "417": - description: Failed to insert query into query store of data database + "501": + description: Failed to execute query as it contains non-supported keywords content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "406": - description: Failed to format data + "503": + description: Failed to communicate with database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Created subset + "403": + description: Not allowed to find subset content: application/json: schema: - type: string - "400": - description: Malformed select query + $ref: "#/components/schemas/ApiErrorDto" + "201": + description: Created subset content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to communicate with database + type: string + "404": + description: Failed to find database in metadata database or query in query + store of the data database content: application/json: schema: @@ -1144,18 +1144,6 @@ paths: type: integer format: int64 responses: - "403": - description: Find table history not allowed - 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 content: @@ -1176,6 +1164,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "400": + description: "Invalid pagination size request, must be > 0" + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Find table history not allowed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -1210,28 +1210,27 @@ paths: type: string format: date-time responses: - "200": - description: Found subset + "400": + description: Malformed select query content: application/json: schema: - $ref: "#/components/schemas/QueryDto" - text/csv: {} - "403": - description: Not allowed to find subset + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to communicate with database 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 + "200": + description: Found subset content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Malformed select query + $ref: "#/components/schemas/QueryDto" + text/csv: {} + "403": + description: Not allowed to find subset content: application/json: schema: @@ -1242,8 +1241,9 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "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: @@ -2040,6 +2040,20 @@ components: affiliation_identifier_scheme_uri: type: string example: https://ror.org/ + EnumDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 5343bb3d-14d3-4eb7-a86f-b8fc553cb315 + value: + type: string + example: "3" + description: "enum values, only considered when type = ENUM" IdentifierDto: required: - creators @@ -2413,6 +2427,9 @@ components: self_html: type: string example: http://example.com + dashboard_html: + type: string + example: http://example.com/d/defi2baxqawaod RelatedIdentifierDto: required: - id @@ -2488,6 +2505,20 @@ components: - Requires - IsObsoletedBy - Obsoletes + SetDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 7eb4eded-bacc-4a91-84db-a9ae6ddafda7 + value: + type: string + example: "3" + description: "enum values, only considered when type = ENUM" ViewColumnDto: required: - database_id @@ -2521,6 +2552,16 @@ components: minLength: 0 type: string example: Column comment + enums: + type: array + description: "enum values, only considered when type = ENUM" + items: + $ref: "#/components/schemas/EnumDto" + sets: + type: array + description: "enum values, only considered when type = ENUM" + items: + $ref: "#/components/schemas/SetDto" database_id: type: string format: uuid @@ -2582,6 +2623,7 @@ components: ViewDto: required: - columns + - created - database_id - id - identifiers @@ -2612,6 +2654,9 @@ components: type: array items: $ref: "#/components/schemas/ViewColumnDto" + created: + type: string + format: date-time last_retrieved: type: string format: date-time diff --git a/.docs/.openapi/api-metadata.yaml b/.docs/.openapi/api-metadata.yaml index d32cc8fe8d..2b0f9a5412 100644 --- a/.docs/.openapi/api-metadata.yaml +++ b/.docs/.openapi/api-metadata.yaml @@ -8,10 +8,10 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 - version: 1.7.3 + version: 1.8.0 externalDocs: description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/system-services-metadata/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8.0/system-services-metadata/ servers: - url: http://localhost description: Development instance @@ -42,18 +42,18 @@ paths: 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" + "200": + description: Found user + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" security: - bearerAuth: [] - basicAuth: [] @@ -77,8 +77,8 @@ paths: $ref: "#/components/schemas/UserUpdateDto" required: true responses: - "400": - description: Modify user query is malformed + "503": + description: Failed to modify user at auth service content: application/json: schema: @@ -89,24 +89,24 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to modify user at auth service + "400": + description: Modify user query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "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" + "202": + description: Modified user information + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" security: - bearerAuth: [] - basicAuth: [] @@ -133,18 +133,18 @@ paths: 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" + "200": + description: Found user + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" security: - bearerAuth: [] - basicAuth: [] @@ -194,20 +194,14 @@ paths: $ref: "#/components/schemas/CreateDatabaseDto" required: true responses: - "400": - description: Database create query is malformed or image is not supported + "404": + description: Failed to fin container/user/database in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Created a new database - content: - application/json: - schema: - $ref: "#/components/schemas/DatabaseBriefDto" - "423": - description: Database quota exceeded + "503": + description: Failed to save in search service content: application/json: schema: @@ -218,21 +212,21 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "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: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to fin container/user/database in metadata database + "423": + description: Database quota exceeded 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: @@ -243,6 +237,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "201": + description: Created a new database + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseBriefDto" security: - bearerAuth: [] - basicAuth: [] @@ -309,14 +309,14 @@ paths: application/json: schema: $ref: "#/components/schemas/DatabaseAccessDto" - "403": - description: No access to this database + "404": + description: Database not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database not found + "403": + description: No access to this database content: application/json: schema: @@ -358,29 +358,29 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Modify access not permitted when no access is granted in the - first place + "400": + description: Modify access query or database connection is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "202": description: Modified access - "503": - description: Access could not be updated 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" - "400": - description: Modify access query or database connection is malformed + "404": + description: Database or user not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database or user not found + "503": + description: Access could not be updated in the data service content: application/json: schema: @@ -415,12 +415,6 @@ paths: $ref: "#/components/schemas/CreateAccessDto" required: true responses: - "502": - description: Access could not be created due to connection error - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "202": description: Granting access succeeded content: @@ -433,6 +427,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "404": + description: Database or user not found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "503": description: Access could not be created in the data service content: @@ -445,8 +445,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database or user not found + "502": + description: Access could not be created due to connection error content: application/json: schema: @@ -475,34 +475,34 @@ paths: type: string format: uuid responses: - "502": - description: Access could not be created due to connection error + "400": + description: Modify access query or database connection is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Revoke of access not permitted as no access was found + "404": + description: "User, database with access was not found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted access - "400": - description: Modify access query or database connection is malformed + "503": + description: Access could not be revoked in the data service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "User, database with access was not found" + "202": + description: Deleted access + "403": + description: Revoke of access not permitted as no access was found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Access could not be revoked in the data service + "502": + description: Access could not be created due to connection error content: application/json: schema: @@ -540,14 +540,14 @@ paths: application/json: schema: $ref: "#/components/schemas/DatabaseAccessDto" - "403": - description: No access to this database + "404": + description: Database not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database not found + "403": + description: No access to this database content: application/json: schema: @@ -602,18 +602,18 @@ paths: $ref: "#/components/schemas/OntologyModifyDto" required: true responses: - "404": - description: Could not find ontology - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "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: [] @@ -631,16 +631,16 @@ paths: 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: [] @@ -665,18 +665,18 @@ paths: $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" + "202": + description: Updated message + content: + application/json: + schema: + $ref: "#/components/schemas/BannerMessageBriefDto" security: - bearerAuth: [] - basicAuth: [] @@ -694,16 +694,16 @@ paths: type: string format: uuid responses: + "202": + description: Deleted message + content: + application/json: {} "404": description: Could not find message content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted message - content: - application/json: {} security: - bearerAuth: [] - basicAuth: [] @@ -785,14 +785,14 @@ paths: 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: [] @@ -817,59 +817,59 @@ paths: schema: type: string responses: - "403": - description: Not allowed to view identifier + "406": + description: Failed to find acceptable representation content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to data service failed + "409": + description: Exported resource was not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found identifier successfully - content: - application/json: - schema: - $ref: "#/components/schemas/IdentifierDto" - application/ld+json: - schema: - $ref: "#/components/schemas/LdDatasetDto" - text/xml: {} - text/bibliography: {} - text/bibliography; style=apa: {} - text/bibliography; style=ieee: {} - text/bibliography; style=bibtex: {} "410": description: Failed to retrieve from S3 endpoint content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "409": - description: Exported resource was not found + "400": + description: "Identifier could not be exported, the requested style is not\ + \ known" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: "Identifier could not be exported, the requested style is not\ - \ known" + "404": + description: Identifier could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "406": - description: Failed to find acceptable representation + "502": + description: Connection to data service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Identifier could not be found + "200": + description: Found identifier successfully + content: + application/json: + schema: + $ref: "#/components/schemas/IdentifierDto" + application/ld+json: + schema: + $ref: "#/components/schemas/LdDatasetDto" + text/xml: {} + text/bibliography: {} + text/bibliography; style=apa: {} + text/bibliography; style=ieee: {} + text/bibliography; style=bibtex: {} + "403": + description: Not allowed to view identifier content: application/json: schema: @@ -903,26 +903,20 @@ paths: $ref: "#/components/schemas/IdentifierSaveDto" required: true responses: - "404": - description: "Failed to find database, table or view" - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "202": description: Saved identifier content: application/json: schema: $ref: "#/components/schemas/IdentifierDto" - "400": - description: Identifier form contains invalid request data + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "400": + description: Identifier form contains invalid request data content: application/json: schema: @@ -939,6 +933,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "404": + description: "Failed to find database, table or view" + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -956,28 +956,28 @@ paths: type: string format: uuid responses: - "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" - "404": - description: Identifier or database could not be found + "403": + description: Deleting identifier not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted identifier - "502": - description: Connection to search service failed + "503": + description: Failed to delete in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Deleting identifier not permitted + "202": + description: Deleted identifier + "502": + description: Connection to search service failed content: application/json: schema: @@ -1001,8 +1001,8 @@ paths: type: string format: uuid responses: - "404": - description: "Failed to find database, table or view" + "503": + description: Failed to save in search service content: application/json: schema: @@ -1013,30 +1013,30 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Published identifier + "403": + description: Insufficient access rights or authorities content: application/json: schema: - $ref: "#/components/schemas/IdentifierDto" - "503": - description: Failed to save in search service + $ref: "#/components/schemas/ApiErrorDto" + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Insufficient access rights or authorities + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "202": + description: Published identifier content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + $ref: "#/components/schemas/IdentifierDto" security: - bearerAuth: [] - basicAuth: [] @@ -1062,12 +1062,12 @@ paths: $ref: "#/components/schemas/DatabaseModifyVisibilityDto" required: true responses: - "400": - description: The visibility payload is malformed + "202": + description: Visibility modified successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + $ref: "#/components/schemas/DatabaseBriefDto" "503": description: Failed to save in search service content: @@ -1080,20 +1080,20 @@ paths: 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" - "502": - description: Connection to search service failed + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: The visibility payload is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database + "502": + description: Connection to search service failed content: application/json: schema: @@ -1170,8 +1170,8 @@ paths: $ref: "#/components/schemas/ViewUpdateDto" required: true responses: - "404": - description: Database or View could not be found + "400": + description: Update view query is malformed content: application/json: schema: @@ -1188,6 +1188,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "404": + description: Database or View could not be found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "202": description: Update view successfully content: @@ -1200,12 +1206,6 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Update view query is malformed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1229,22 +1229,28 @@ paths: type: string format: uuid responses: - "404": - description: "Database, view or user could not be found" + "403": + description: Deletion not allowed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "202": description: Delete view successfully - "423": - description: Delete view resulted in an invalid query statement + "404": + description: "Database, view or user could not be found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "423": + description: Delete view resulted in an invalid query statement content: application/json: schema: @@ -1261,12 +1267,6 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Deletion not allowed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1294,12 +1294,6 @@ paths: type: string format: uuid responses: - "200": - description: Find table successfully - content: - application/json: - schema: - $ref: "#/components/schemas/TableDto" "403": description: Access to the database is forbidden content: @@ -1312,6 +1306,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Find table successfully + content: + application/json: + schema: + $ref: "#/components/schemas/TableDto" security: - bearerAuth: [] - basicAuth: [] @@ -1347,32 +1347,32 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Updated the 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" + "202": + description: Updated the table + content: + application/json: + schema: + $ref: "#/components/schemas/TableBriefDto" "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" - "403": - description: Update table visibility not permitted + "502": + description: Connection to search service failed content: application/json: schema: @@ -1402,14 +1402,6 @@ paths: type: string format: uuid responses: - "400": - description: Delete table query resulted in an invalid query statement - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Delete table successfully "503": description: Failed to save in search service content: @@ -1422,14 +1414,22 @@ paths: 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" - "404": - description: "Table, database or container could not be found" + "202": + description: Delete table successfully + "400": + description: Delete table query resulted in an invalid query statement + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "502": + description: Connection to search service failed content: application/json: schema: @@ -1478,12 +1478,6 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Failed to map column statistic to known columns - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "502": description: Connection to search service failed content: @@ -1492,6 +1486,12 @@ paths: $ref: "#/components/schemas/ApiErrorDto" "202": description: Updated table statistics successfully + "400": + description: Failed to map column statistic to known columns + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1531,14 +1531,21 @@ paths: $ref: "#/components/schemas/ColumnSemanticsUpdateDto" required: true responses: + "404": + description: Failed to find user/table/database/ontology in metadata database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "202": description: Updated column semantics successfully content: application/json: schema: $ref: "#/components/schemas/ColumnDto" - "404": - description: Failed to find user/table/database/ontology in metadata database + "400": + description: Update semantic concept query is malformed or update unit of + measurement query is malformed content: application/json: schema: @@ -1561,13 +1568,6 @@ paths: application/json: schema: $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" security: - bearerAuth: [] - basicAuth: [] @@ -1593,12 +1593,18 @@ paths: $ref: "#/components/schemas/DatabaseTransferDto" required: true responses: - "400": - description: Owner payload is malformed + "403": + description: Transfer of ownership is not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Transfer of ownership was successful + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseBriefDto" "503": description: Failed to save in search service content: @@ -1611,24 +1617,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "400": + description: Owner payload is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Transfer of ownership is not permitted + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Transfer of ownership was successful - content: - application/json: - schema: - $ref: "#/components/schemas/DatabaseBriefDto" security: - bearerAuth: [] - basicAuth: [] @@ -1649,32 +1649,32 @@ paths: type: string format: uuid responses: - "200": - description: Refreshed database views metadata + "403": + description: Refresh view metadata is not permitted content: application/json: schema: - $ref: "#/components/schemas/DatabaseBriefDto" + $ref: "#/components/schemas/ApiErrorDto" "503": description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Refresh view metadata is not permitted + "200": + description: Refreshed database views metadata content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + $ref: "#/components/schemas/DatabaseBriefDto" + "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 + "502": + description: Connection to search service failed content: application/json: schema: @@ -1699,20 +1699,14 @@ paths: type: string format: uuid responses: - "400": - description: Failed to parse payload at search service + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Refreshed database tables metadata - content: - application/json: - schema: - $ref: "#/components/schemas/DatabaseBriefDto" - "503": - description: Failed to save in search service + "404": + description: Failed to find database in metadata database content: application/json: schema: @@ -1729,12 +1723,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database + "400": + description: Failed to parse payload at search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Refreshed database tables metadata + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseBriefDto" security: - bearerAuth: [] - basicAuth: [] @@ -1753,6 +1753,12 @@ paths: 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: @@ -1762,12 +1768,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: [] @@ -1789,21 +1789,76 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/DatabaseModifyImageDto" + $ref: "#/components/schemas/DatabaseModifyImageDto" + required: true + responses: + "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" + "403": + description: Modify of image is not permitted + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "410": + description: File was not found in the Storage 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 + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseBriefDto" + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/dashboard: + put: + tags: + - database-endpoint + summary: Update database dashboard uid + description: Updates the dashboard uid for a database with given id. Only the + database owner can perform this operation. Requires role `system`. + operationId: modifyDashboard + parameters: + - name: databaseId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseModifyDashboardDto" required: true responses: - "403": - description: Modify of image is not permitted - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "410": - description: File was not found in the Storage Service + "202": + description: Modify of dashboard uid was successful content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + $ref: "#/components/schemas/DatabaseBriefDto" "404": description: Database could not be found content: @@ -1816,14 +1871,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Modify of image was successful + "502": + description: Connection to search service failed content: application/json: schema: - $ref: "#/components/schemas/DatabaseBriefDto" - "502": - description: Connection to search service failed + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Malformed payload content: application/json: schema: @@ -1947,18 +2002,18 @@ paths: $ref: "#/components/schemas/ImageCreateDto" required: true responses: - "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" + "409": + description: Image already exists + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "400": description: Image specification is invalid content: @@ -2053,26 +2108,20 @@ paths: $ref: "#/components/schemas/CreateIdentifierDto" required: true responses: - "404": - description: "Failed to find database, table or view" - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "201": description: Drafted identifier content: application/json: schema: $ref: "#/components/schemas/IdentifierDto" - "400": - description: Identifier form contains invalid request data + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "400": + description: Identifier form contains invalid request data content: application/json: schema: @@ -2089,6 +2138,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "404": + description: "Failed to find database, table or view" + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2107,6 +2162,12 @@ paths: 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: @@ -2115,12 +2176,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: [] @@ -2145,38 +2200,38 @@ paths: $ref: "#/components/schemas/CreateViewDto" required: true responses: - "404": - description: Failed to find database/user in metadata database. + "403": + description: Credentials missing content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Create view successfully + "409": + description: View exists with name content: application/json: schema: - $ref: "#/components/schemas/ViewBriefDto" - "423": - description: Create view resulted in an invalid query statement + $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 + "404": + description: Failed to find database/user in metadata database. content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "201": + description: Create view successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Credentials missing + $ref: "#/components/schemas/ViewBriefDto" + "400": + description: Create view query is malformed content: application/json: schema: @@ -2187,8 +2242,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Create view query is malformed + "423": + description: Create view resulted in an invalid query statement content: application/json: schema: @@ -2213,12 +2268,6 @@ paths: type: string format: uuid responses: - "403": - description: List tables not permitted - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: List tables content: @@ -2233,6 +2282,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "403": + description: List tables not permitted + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2256,8 +2311,14 @@ paths: $ref: "#/components/schemas/CreateTableDto" required: true responses: - "400": - description: Create table query is malformed + "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: @@ -2268,30 +2329,24 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "400": + description: Create table query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Created a new table + "403": + description: Create table not permitted content: application/json: schema: - $ref: "#/components/schemas/TableBriefDto" + $ref: "#/components/schemas/ApiErrorDto" "404": description: "Database, container or user could not be found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Create table not permitted - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "502": description: Connection to search service failed content: @@ -2337,8 +2392,8 @@ paths: $ref: "#/components/schemas/CreateContainerDto" required: true responses: - "409": - description: Container name already exists + "404": + description: Container image or user could not be found content: application/json: schema: @@ -2349,20 +2404,20 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Container payload malformed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "201": description: Created a new container content: application/json: schema: $ref: "#/components/schemas/ContainerDto" - "404": - description: Container image or user could not be found + "409": + description: Container name already exists + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Container payload malformed content: application/json: schema: @@ -2450,8 +2505,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Filter params are invalid + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: @@ -2462,8 +2517,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "422": - description: Ontology does not have rdf or sparql endpoint + "400": + description: Filter params are invalid content: application/json: schema: @@ -2575,6 +2630,12 @@ paths: type: string format: uuid responses: + "404": + description: Database could not be found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "200": description: Database found successfully headers: @@ -2591,12 +2652,6 @@ paths: application/json: schema: $ref: "#/components/schemas/DatabaseBriefDto" - "404": - description: Database could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "403": description: Not allowed to view database content: @@ -2628,40 +2683,40 @@ paths: type: string format: uuid responses: - "403": - description: Not the table owner. + "404": + description: Failed to find database/table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Suggested table semantics successfully + "400": + description: Failed to parse statistic in search service content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/EntityDto" + $ref: "#/components/schemas/ApiErrorDto" "417": description: Generated query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database/table in metadata database + "200": + description: Suggested table semantics successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Failed to parse statistic in search service + type: array + items: + $ref: "#/components/schemas/EntityDto" + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "422": - description: Ontology does not have rdf or sparql endpoint + "403": + description: Not the table owner. content: application/json: schema: @@ -2696,12 +2751,6 @@ paths: type: string format: uuid responses: - "400": - description: Generated query is malformed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "404": description: Failed to find database/table in metadata database content: @@ -2716,6 +2765,12 @@ paths: type: array items: $ref: "#/components/schemas/TableColumnEntityDto" + "400": + description: Generated query is malformed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "422": description: Ontology does not have rdf or sparql endpoint content: @@ -2766,12 +2821,6 @@ paths: type: string format: uuid responses: - "404": - description: Container not found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "202": description: Deleted container "403": @@ -2780,6 +2829,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "404": + description: Container not found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -5095,6 +5150,9 @@ components: self_html: type: string example: http://example.com + dashboard_html: + type: string + example: http://example.com/d/defi2baxqawaod RelatedIdentifierDto: required: - id @@ -5172,6 +5230,7 @@ components: - Obsoletes DatabaseModifyVisibilityDto: required: + - is_dashboard_enabled - is_public - is_schema_public type: object @@ -5182,6 +5241,9 @@ components: is_schema_public: type: boolean example: true + is_dashboard_enabled: + type: boolean + example: true ViewUpdateDto: required: - is_public @@ -5353,10 +5415,12 @@ components: example: Column comment enums: type: array + description: "enum values, only considered when type = ENUM" items: $ref: "#/components/schemas/EnumDto" sets: type: array + description: "enum values, only considered when type = ENUM" items: $ref: "#/components/schemas/SetDto" database_id: @@ -5475,6 +5539,7 @@ components: value: type: string example: "3" + description: "enum values, only considered when type = ENUM" SetDto: required: - id @@ -5488,6 +5553,7 @@ components: value: type: string example: "3" + description: "enum values, only considered when type = ENUM" UnitBriefDto: required: - id @@ -5520,6 +5586,13 @@ components: properties: key: type: string + DatabaseModifyDashboardDto: + required: + - uid + type: object + properties: + uid: + type: string CreateAccessDto: required: - type @@ -6388,14 +6461,14 @@ components: type: string resumptionToken: type: string + parametersString: + type: string fromDate: type: string format: date-time untilDate: type: string format: date-time - parametersString: - type: string BannerMessageDto: required: - id @@ -6547,6 +6620,16 @@ components: minLength: 0 type: string example: Column comment + enums: + type: array + description: "enum values, only considered when type = ENUM" + items: + $ref: "#/components/schemas/EnumDto" + sets: + type: array + description: "enum values, only considered when type = ENUM" + items: + $ref: "#/components/schemas/SetDto" database_id: type: string format: uuid @@ -6608,6 +6691,7 @@ components: ViewDto: required: - columns + - created - database_id - id - identifiers @@ -6638,6 +6722,9 @@ components: type: array items: $ref: "#/components/schemas/ViewColumnDto" + created: + type: string + format: date-time last_retrieved: type: string format: date-time @@ -6768,6 +6855,7 @@ components: required: - columns - constraints + - created - database_id - id - internal_name @@ -6807,6 +6895,9 @@ components: $ref: "#/components/schemas/ColumnDto" constraints: $ref: "#/components/schemas/ConstraintsDto" + created: + type: string + format: date-time last_retrieved: type: string format: date-time diff --git a/.docs/.openapi/api-search.yaml b/.docs/.openapi/api-search.yaml index c47cbfb649..1a49f21387 100644 --- a/.docs/.openapi/api-search.yaml +++ b/.docs/.openapi/api-search.yaml @@ -1,6 +1,23 @@ { "components": { "schemas": { + "ApiError": { + "properties": { + "code": { + "example": "error.dashboard.create", + "type": "string" + }, + "message": { + "example": "Message", + "type": "string" + }, + "status": { + "example": "BAD_REQUEST", + "type": "string" + } + }, + "type": "object" + }, "IndexDto": { "properties": { "results": { @@ -98,7 +115,7 @@ }, "externalDocs": { "description": "Sourcecode Documentation", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" }, "info": { "contact": { @@ -111,7 +128,7 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0" }, "title": "Database Repository Search Service API", - "version": "1.5" + "version": "1.8.0" }, "openapi": "3.0.0", "paths": { diff --git a/.docs/.openapi/api.base.yaml b/.docs/.openapi/api.base.yaml index 479c27da3a..0000a844fa 100644 --- a/.docs/.openapi/api.base.yaml +++ b/.docs/.openapi/api.base.yaml @@ -11,7 +11,7 @@ components: type: http externalDocs: description: Project Website - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/ info: contact: email: andreas.rauber@tuwien.ac.at @@ -24,7 +24,7 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 title: DBRepo REST API - version: 1.7.3 + version: 1.8.0 openapi: 3.1.0 servers: - description: Test Instance diff --git a/.docs/.openapi/api.yaml b/.docs/.openapi/api.yaml index a61ecbcb81..ddd66dbbd7 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.3 + version: 1.8.0 servers: - description: Test Instance url: 'https://test.dbrepo.tuwien.ac.at' @@ -24,7 +24,7 @@ servers: url: 'http://localhost' externalDocs: description: Project Website - url: 'https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/' + url: 'https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/' paths: /api/analyse/datatypes: get: @@ -3244,6 +3244,62 @@ paths: security: - bearerAuth: [] - basicAuth: [] + '/api/database/{databaseId}/dashboard': + put: + tags: + - database-endpoint + summary: Update database dashboard uid + description: >- + Updates the dashboard uid for a database with given id. Only the + database owner can perform this operation. Requires role `system`. + operationId: modifyDashboard + parameters: + - name: databaseId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseModifyDashboardDto' + required: true + responses: + '202': + description: Modify of dashboard uid was successful + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseBriefDto' + '400': + description: Malformed payload + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '404': + description: Database could not be found + 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: [] /api/ontology: get: tags: @@ -4432,14 +4488,23 @@ components: example: ',' type: string type: object + ApiError: + properties: + code: + example: error.dashboard.create + type: string + message: + example: Message + type: string + status: + example: BAD_REQUEST + type: string + type: object ColumnAnalysisDto: properties: d: example: 4 type: integer - dfid: - example: null - type: integer enums: example: null properties: @@ -4459,15 +4524,6 @@ components: example: decimal type: string type: object - ErrorDto: - properties: - message: - example: Message - type: string - success: - example: false - type: boolean - type: object KeysDto: properties: keys: @@ -5267,6 +5323,20 @@ components: affiliation_identifier_scheme_uri: type: string example: 'https://ror.org/' + EnumDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 5343bb3d-14d3-4eb7-a86f-b8fc553cb315 + value: + type: string + example: '3' + description: 'enum values, only considered when type = ENUM' IdentifierDto: required: - creators @@ -5643,6 +5713,9 @@ components: self_html: type: string example: 'http://example.com' + dashboard_html: + type: string + example: 'http://example.com/d/defi2baxqawaod' RelatedIdentifierDto: required: - id @@ -5718,6 +5791,20 @@ components: - Requires - IsObsoletedBy - Obsoletes + SetDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 7eb4eded-bacc-4a91-84db-a9ae6ddafda7 + value: + type: string + example: '3' + description: 'enum values, only considered when type = ENUM' ViewColumnDto: required: - database_id @@ -5751,6 +5838,16 @@ components: minLength: 0 type: string example: Column comment + enums: + type: array + description: 'enum values, only considered when type = ENUM' + items: + $ref: '#/components/schemas/EnumDto' + sets: + type: array + description: 'enum values, only considered when type = ENUM' + items: + $ref: '#/components/schemas/SetDto' database_id: type: string format: uuid @@ -5812,6 +5909,7 @@ components: ViewDto: required: - columns + - created - database_id - id - identifiers @@ -5842,6 +5940,9 @@ components: type: array items: $ref: '#/components/schemas/ViewColumnDto' + created: + type: string + format: date-time last_retrieved: type: string format: date-time @@ -7225,6 +7326,7 @@ components: - Obsoletes DatabaseModifyVisibilityDto: required: + - is_dashboard_enabled - is_public - is_schema_public type: object @@ -7235,6 +7337,9 @@ components: is_schema_public: type: boolean example: true + is_dashboard_enabled: + type: boolean + example: true ViewUpdateDto: required: - is_public @@ -7406,10 +7511,12 @@ components: example: Column comment enums: type: array + description: 'enum values, only considered when type = ENUM' items: $ref: '#/components/schemas/EnumDto' sets: type: array + description: 'enum values, only considered when type = ENUM' items: $ref: '#/components/schemas/SetDto' database_id: @@ -7516,32 +7623,6 @@ components: 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 @@ -7574,6 +7655,13 @@ components: properties: key: type: string + DatabaseModifyDashboardDto: + required: + - uid + type: object + properties: + uid: + type: string CreateAccessDto: required: - type @@ -8376,14 +8464,14 @@ components: type: string resumptionToken: type: string + parametersString: + type: string fromDate: type: string format: date-time untilDate: type: string format: date-time - parametersString: - type: string BannerMessageDto: required: - id @@ -8609,6 +8697,7 @@ components: required: - columns - constraints + - created - database_id - id - internal_name @@ -8648,6 +8737,9 @@ components: $ref: '#/components/schemas/ColumnDto' constraints: $ref: '#/components/schemas/ConstraintsDto' + created: + type: string + format: date-time last_retrieved: type: string format: date-time diff --git a/.docs/.openapi/openapi-generate.sh b/.docs/.openapi/openapi-generate.sh index edd927d202..aeab907799 100644 --- a/.docs/.openapi/openapi-generate.sh +++ b/.docs/.openapi/openapi-generate.sh @@ -1,14 +1,15 @@ #!/bin/bash declare -A services -services[4000]=search -services[5000]=analyse +services[4050]=analyse +services[4060]=search +services[4070]=dashboard services[9093]=data services[9099]=metadata # requires https://github.com/mikefarah/yq/ -> v4.44.3 function retrieve () { - if [[ "$2" == analyse ]] || [[ "$2" == search ]]; then + if [[ "$2" == analyse ]] || [[ "$2" == search ]] || [[ "$2" == dashboard ]]; then echo "... retrieve json api from localhost:$1" curl -sSL "http://localhost:$1/api-$2.json" | yq -o=json - > "./.docs/.openapi/api-$2.yaml" else diff --git a/.docs/api/broker-service.md b/.docs/api/broker-service.md index 373eb35b95..18bf4fe8b4 100644 --- a/.docs/api/broker-service.md +++ b/.docs/api/broker-service.md @@ -61,9 +61,6 @@ The consumer takes care of writing it to the correct table in the [Data Service] ## Limitations -* No support for MQTT in the [Metadata Service](../system-services-metadata) - and [Data Service](../system-services-data) because of MQTT's missing permission system. - !!! question "Do you miss functionality? Do these limitations affect you?" We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get diff --git a/.docs/api/dashboard-service.md b/.docs/api/dashboard-service.md deleted file mode 100644 index ea3f565046..0000000000 --- a/.docs/api/dashboard-service.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -author: Martin Weise ---- - -## tl;dr - -!!! debug "Debug Information" - - Image: [`docker.io/bitnami/grafana:10.4.9-debian-12-r0`](https://hub.docker.com/r/bitnami/grafana) - - * Ports: 3000/tcp - * UI: `http://<hostname>/dashboard` - * Management UI: `http://<hostname>:3000` (see [Management](#management)) - * Prometheus: `http://<hostname>/dashboard/metrics` - - To directly access in Kubernetes (for e.g. debugging), forward the svc port to your local machine: - - ```shell - kubectl [-n namespace] port-forward svc/dashboard-service 3000:3000 - ``` - -## Overview - -The Dashboard Service is visualizing the status of DBRepo with charts. The default dashboard provisioner located in -`/etc/grafana/provisioning/dashboards/provider.yaml` checks for new `JSON` dashboard files in `/app/dashboards` every 10 -seconds and makes the available in the Dashboard Service. - -## Management - -The Dashboard Service can be accessed with admin users (see [Identity Service](../../api/identity-service)). In this -case, access the UI via the port `3000` directly to avoid UI Redirects. - -!!! bug "UI Redirects" - - It is a known bug [#460](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/460) - that when being logged-in, the UI randomly redirects when being accessed from the Gateway Service, we therefore - recommend to access port `3000` directly: `http://<hostname>:3000`. Anonmyous users are not affected. - -## Limitations - -* Unintended redirects when being logged-in (see above). - -!!! question "Do you miss functionality? Do these limitations affect you?" - - We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get - in [contact](../../contact) with us, we happily answer requests for collaboration with attached CV and your programming - experience! - -## Security - -(none) diff --git a/.docs/api/data-service.md b/.docs/api/data-service.md index bc43a5d363..ff27c03586 100644 --- a/.docs/api/data-service.md +++ b/.docs/api/data-service.md @@ -45,6 +45,13 @@ cache the connection details from the [Metadata Service](../metadata-service) su everytime e.g. a sensor measurement is inserted. By default, this information is stored for 60 minutes. System administrators can disable this behavior by setting `CREDENTIAL_CACHE_TIMEOUT=0` (cache is deleted after 0 seconds). + +## Upload + +The Data Service also is capable to upload files to the S3 backend. The default limit +of [`Tomcat`](https://spring.io/guides/gs/uploading-files#_tuning_file_upload_limits) in Spring Boot is configured to be +`2GB`. You can provide your own limit with setting `MAX_UPLOAD_SIZE`. + ## Limitations * Views in DBRepo can only have 63-character length (it is assumed only internal views have the maximum length of 64 diff --git a/.docs/api/ui.md b/.docs/api/ui.md index b82058c19b..5393c9ff79 100644 --- a/.docs/api/ui.md +++ b/.docs/api/ui.md @@ -95,13 +95,8 @@ User Interface on development. * Frontend: [Vuetify 3+](https://vuetifyjs.com/en/) * State: [Pinia](https://pinia.vuejs.org/) -### Example - -See the [API Overview](..) page for detailed examples. - ## Limitations -* Changing the OIDC provider URL requires to build the UI from scratch. * When developing locally, the `axios` module does not parse custom headers (such as `X-Count`, `X-Headers`) and/or blocks CORS requests wrongfully. diff --git a/.docs/changelog.md b/.docs/changelog.md index f2cb6b83a1..47439d975f 100644 --- a/.docs/changelog.md +++ b/.docs/changelog.md @@ -2,6 +2,15 @@ author: Martin Weise --- +## v1.8.0 (2025-??-??) + +#### Features + +* Refactored internal Java-based testing data that improves test consistency + in [#510](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/510). +* Added automated dashboard generation for all public databases where each view has an overview of its data and + schema in [#460](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/460). + ## v1.7.3 (2025-03-17) [:simple-gitlab: GitLab Release](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tags/v1.7.3) diff --git a/.docs/concepts/dashboards.md b/.docs/concepts/dashboards.md new file mode 100644 index 0000000000..e6dd2bf22f --- /dev/null +++ b/.docs/concepts/dashboards.md @@ -0,0 +1,27 @@ +--- +author: Martin Weise +--- + +We use [Grafana](https://grafana.com) to display and automatically generate dashboards that describe a dataset. + +## Provisioned Dashboards + +Every provisioned dashboard consists of two areas: + +1. **Unmanaged**: this area can be modified by the database owner and is not affected by provisioning. It is the area + above the "Generated Statistics" row. +2. **Managed**: this area is affected by provisioning, any changes to this area will be overridden and deleted without + notice. Note that the dashboard links are also affected by provisioning. + +Everytime the views of the database change (e.g. a new view is added, a view is deleted) then the dashboard for this +database is provisioned. + +<figure id="fig1" markdown> + +<figcaption>Figure 1: Generated dashboard containing unmanaged (yellow) and managed (green) content.</figcaption> +</figure> + +!!! question "How do I disable managed dashboards?" + + If you prefer not to have automatically-generated dashboards, you can disable managed dashboards for a database + in the UI. Go to **your database** > **Settings** > **Visibility** > **Managed Dashboard** > **Disabled**. \ No newline at end of file diff --git a/.docs/concepts/data-versioning.md b/.docs/concepts/data-versioning.md index 8a9abc667b..45a7cb6e73 100644 --- a/.docs/concepts/data-versioning.md +++ b/.docs/concepts/data-versioning.md @@ -6,34 +6,23 @@ Data is getting bigger and so are expectations of data provisioning in regards t after quality check and not in snapshot intervals), cost-effectiveness (i.e. no duplication of data), transparent, precise citation and many more. -[System-versioned](https://mariadb.com/kb/en/system-versioned-tables/) tables in MariaDB are improved data structures -that keep track of historical data. For each entry in a system-versioned table, a time period is maintained that denotes -the validity time span of this tuple from its start to end. Tuples in system-versioned tables are not *actually* -modified, they are marked as (in-)valid in time periods. - -<figure markdown> - -| ID | Sensor | Temp | Start | End | -|----|--------|------|-------|-----| -| 1 | A | 23.1 | t1 | | -| 2 | B | 25.8 | t2 | | - +System-versioned tables in MariaDB are improved data structures that keep track of historical data. For each entry in a +system-versioned table, a time period is maintained that denotes the validity time span of this tuple from its start to +end. Tuples in system-versioned tables are not *actually* modified, they are marked as (in-)valid in time periods +(c.f. [Fig. 1](#fig1)). + +<figure id="fig1" markdown> + +<figcaption>Fig. 1: Data versioning in MariaDB system-versioned tables.</figcaption> </figure> Assuming that Sensor A was calibrated wrong and an updated measurement is passed to the system-versioned table, the table contents show that the old row with Temp 23.1 is not deleted, but marked as valid in time span (t1, t3). The updated row with Temp 22.1 is marked as valid from time span t3 onwards. -<figure markdown> - -| ID | Sensor | Temp | Start | End | -|----|--------|------|-------|-----| -| 1 | A | 23.1 | t1 | t3 | -| 2 | B | 25.8 | t2 | | -| 1 | A | 22.1 | t3 | | - -</figure> +## Further Reading -System-versioned tables are part of the SQL:2011 standard and have been adopted by many database management system -vendors: MariaDB (10.5 and higher), Google BigQuery, IBM DB2 (12 and higher), SQL Server (2016 and higher), Azure SQL, -PostgreSQL with [temporal tables extension](https://github.com/nearform/temporal_tables), etc. \ No newline at end of file +System-versioned tables are part of the current ISO/IEC 9075-2:2023 ("SQL") standard and have been adopted by many +database management system vendors, e.g. MariaDB (10.5 and higher), Google BigQuery, IBM DB2 (12 and higher), +Cockroach DB, SAP HANA, SQL Server (2016 and higher), Azure SQL, PostgreSQL +with [temporal tables extension](https://github.com/nearform/temporal_tables), etc. \ No newline at end of file diff --git a/.docs/concepts/data-visibility.md b/.docs/concepts/data-visibility.md index 31c6ca3682..e08e717fa1 100644 --- a/.docs/concepts/data-visibility.md +++ b/.docs/concepts/data-visibility.md @@ -2,10 +2,23 @@ author: Martin Weise --- +## Overview + There are several ways to set the visibility of (meta-)data in DBRepo. It is possible to set the data visibility to visible/hidden and the schema to be visible/hidden for each database and separately for each table, each view and each subset of a database. +<figure markdown> + +| Name | `is_public` | `is_schema_public` | UI? | Search? | Dashboard? | +|-----------------------------|-------------|--------------------|--------------------|--------------------|--------------------| +| [Visible](#visibility) | `True` | `True` | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Data-only](#data-only) | `True` | `False` | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Schema-only](#schema-only) | `False` | `True` | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Hidden](#hidden) | `False` | `False` | :x: | :x: | :x: | + +</figure> + ## Visibility In total there are four possible visibility settings that can be applied on database level and then at the subsequent @@ -22,6 +35,8 @@ levels (table, view, subset). We give two examples for better understanding: owner wants the data to be visible to the public (anonymously), so he changes the settings to data=visible, schema=hidden. Now everybody can see the data but not the table(s) that contain the data. +In any case, a Grafana dashboard will be created. + #### Visible !!! info "Possible use-case: data publication supplement to an open-access publication" @@ -40,8 +55,9 @@ Where the resource's schema visibility is hidden but the data is visible. Where the resource's data visibility is hidden but the schema is visible. -#### Draft +#### Hidden !!! info "Possible use-case: project data storage before publication" -Where the resource's data and schema visibility is hidden. It will not be findable even in the search. \ No newline at end of file +Where the resource's data and schema visibility is hidden. It will not be findable even in the search. The automatically +generated Dashboard cannot be viewed anonymously (only users with read-access can view). \ No newline at end of file diff --git a/.docs/concepts/ui.md b/.docs/concepts/ui.md deleted file mode 100644 index ab6848b7ba..0000000000 --- a/.docs/concepts/ui.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -author: Martin Weise ---- - -It provides a graphical interface for a researcher to interact with the API (c.f. Figure 1). - -<figure markdown> -{ .img-border } -<figcaption>Figure 1: User Interface</figcaption> -</figure> - -For examples on how to use the User Interface, visit the [API](../api/) page to find out how to create -users, databases and how to import your data. - -## Server / Client - -TBD - -## Cache - -TBD \ No newline at end of file diff --git a/.docs/images/architecture.drawio b/.docs/images/architecture.drawio index b1aed4cb40..d2009bf10b 100644 --- a/.docs/images/architecture.drawio +++ b/.docs/images/architecture.drawio @@ -1,4 +1,4 @@ -<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.0.9 Chrome/128.0.6613.186 Electron/32.2.5 Safari/537.36" version="26.0.9" pages="9"> +<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.1.1 Chrome/132.0.6834.210 Electron/34.3.3 Safari/537.36" version="26.1.1" pages="9"> <diagram id="mvBsv1rP8O80Qe3yGnn_" name="docker-compose"> <mxGraphModel dx="683" dy="391" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"> <root> @@ -1108,11 +1108,33 @@ </root> </mxGraphModel> </diagram> - <diagram id="7HywRA3nQAgvNxZjCRq2" name="private-embargo"> - <mxGraphModel dx="1434" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"> + <diagram id="7HywRA3nQAgvNxZjCRq2" name="data-versioning"> + <mxGraphModel dx="988" dy="563" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"> <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> + <mxCell id="795Xv0Ka93fOG331V9Xn-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="795Xv0Ka93fOG331V9Xn-4" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="622" y="141" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="795Xv0Ka93fOG331V9Xn-8" value="t3:<b> UPDATE</b>&nbsp;tbl<br><b>SET</b> `Temp` = <font style="color: light-dark(rgb(251, 35, 108), rgb(251, 35, 108));">22.1</font><br><b>WHERE</b> `ID` = 1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;fontSize=17;" parent="795Xv0Ka93fOG331V9Xn-7" vertex="1" connectable="0"> + <mxGeometry x="-0.1405" y="3" relative="1" as="geometry"> + <mxPoint x="22" y="3" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="795Xv0Ka93fOG331V9Xn-4" value="" style="rounded=1;whiteSpace=wrap;html=1;arcSize=4;" parent="1" vertex="1"> + <mxGeometry x="120" y="80" width="284" height="122" as="geometry" /> + </mxCell> + <mxCell id="795Xv0Ka93fOG331V9Xn-18" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,iVBORw0KGgoAAAANSUhEUgAABJEAAAHoCAYAAAD5W34cAACAAElEQVR4XuydB5iV1bWGTTP2buyxRGNFNHYMEcUGoiiKgg0RFOzYqWIHLIiKPYiKEkWxoCioFCsR0RhbTJPYk1yvN7m5aQbcl3fBd7LPP2eQGc4MM+b7nmc95y9773//ex+G2e+stfZSybIsy7Isy7Isy7Isy7K+REsVL1iWZTVV/eMf/7DZbHU0y7Isy7Isy6qWDJEsy2o2YkH8y1/+0mazLaL99a9/Lf4zsizLsizLsqx6yxDJsqxmI0Mkm61uZohkWZZlWZZlVVOGSJZlNRsZItlsdTNDJMuyLMuyLKuaMkSyLKvZyBDJZqubGSJZlmVZlmVZ1ZQhkmVZzUaGSDZb3cwQybIsy7Isy6qmDJEsy2o2MkSy2epmhkiWZVmWZVlWNWWIZFlWs5Ehks1WNzNEsizLsizLsqopQyTLspqNDJFstrqZIZJlWZZlWZZVTRkiWZbVbGSIZLPVzQyRLMuyLMuyrGrKEMmyrGYjQySbrW5miGRZlmVZlmVVU4ZIlmU1Gxki2Wx1M0Mky7Isy7Isq5oyRLIsq9nIEMlmq5sZIlmWZVmWZVnVlCGSZVnNRg0FkV5//fX09ttv17huszWWvfnmm2HF64trhkiWZVmWZVlWNWWIZFlWs1FDQKRRo0alXXbZJb322mtxvvvuu6fvf//7DQaVZsyYkdZaa63UtWvXGvdqs2KdcePGpY4dO6allloqXXnllTXKyyZNmpROOOGEtOKKK6bWrVvXuF8ta+gx+0+wmTNnpl133TWNHTu2xr3FMUMky7Isy7Isq5oyRLIsq9mo2hBpwIABaeutt04vv/xy6RpA6Xvf+16DAZEXX3wxrbHGGqlz58417tVmleqMHz/+SyGSbOONN25QiNTQY/afYsBCYNzQoUNr3KuvGSJZlmVZlmVZ1ZQhkmVZzUbVhEgjR45M3/72t9O0adNq3GsOJoh01VVX1bhXtGpBJMKtttxyyxrXm5o1l35WsokTJ6ZvfetbacyYMTXu1ccMkSzLsizLsqxqyhDJsqxmo2pBpDfeeCM8e4444oga95qLCSJdffXVNe4VrVoQ6bLLLkurrLJKjetNzZpLP2uz9u3bpw033DD94he/qHGvrmaIZFmWZVmWZVVThkiWZTUbVQsi4b0DgCEfUn6d8DaAyze+8Y3StWuuuSatu+66Uf7kk09OW221VVpmmWXS6quvnvr16xdlpk+fnvbaa68os9lmm6W+ffuW6g8aNCi8Ylq2bBn5bo4//vjIUbTbbruVPfvyyy+P0LqddtopQppatWoV13/+859XrCOIdMghh0Sfll122bTaaqulww47rCw8D6sEkV566aXUqVOntNFGG8VzseJ45Na/f/+05pprxtjwLoSwcb3SmPXo0SOtsMIKAUJ69uwZz2DM+Bw+fHi6+eab0z777BOgZ+WVV069evUqexbw5Iwzzoh2W7RoEZ8aa4ywue7du0efd9hhh7TJJpuk3r17L7SfGDmlGFvGgs999903xoF7hAWut956MaZnnnlmPJd3oC36x3h36dIlvguMNfP9s5/9LOoOGzYsoORyyy2XjjzyyCiz9NJLp8033zzeNX+32uY5txEjRlT8ftbHDJEsy7Isy7KsasoQybKsZqNqQSRAC4t0ctAU7x111FFlQATr06dPlL/22mvTk08+mZ544omAE1//+tfT1KlTowyJuQEiQKRim9tss0168MEHS+eUyYHQfffdl772ta9F25wDSYrQp1hHEOmss85Kr776asAm4AOAA0CR1y1CpHfeeSdtt912AV8EnE4//fQAH0899VRZ3dwOPPDAih4+lcaM5wFWbrzxxvTII48EEFl77bWj3JAhQ9L9998fY9KmTZt4jwkTJpTqkgycvlCP87vvvrss/9M555yTvvvd78auepyTM4q+fVk/mTPGiuMXXnghffOb3wwYpftnn312POeiiy5KDzzwQPSROlwDhtEP+nnSSSfFtYEDB5bqduvWLa5Nnjw55o8wScaA933ssceizKLMM0YbembxXl3NEMmyLMuyLMuqpgyRLMtqNqoWRNp2221rQA9ZJSAiiPTTn/60dO2mm26Ka7feemvpGot+rt15552la4CS7bffvqy9IhC6+OKLA0gBQ3Qtf1alOrUl1j722GPjeg6tihAJjyjK4LWja88991xcwwMoby+32uBMpTHjeTw3v4YnF8/IPaUEiABgnBNqCAhr27ZtWV28mNi9jOMOHTqEFw8wTPfz8aqtn+xql59vsMEGaY899iidCyIBmHTtjjvuiGvk0NI14A/vm++wJ4iUt//MM89EObzFOF+UecbwcKKtSoCprmaIZFmWZVmWZVVThkiWZTUbVQsiEWa10kor1biOVQIilSDS6NGj49oNN9xQukZYG3X33nvv0rXDDz+8Rt6iIhDCUwWvGLxrBg8eXNFDqlinNojEs7hO2JSuFSESIWiUue2228rqAjgOOuigGs+W1QZnKo1ZJYhUCdIU3wPvI86LXjh4BOHJxDEwhjI777xzuu6660oeSbLa+lm04rhU6h/eQ1wjDC+vC+jCo03nlSASRogc4YYcL8o8y2gL2Fm8XlczRLIsy7Isy7KqKUMky7KajaoFkdZaa60IPStexyoBkUWFSFi7du2iPuFMhE4BrN56662yMkUghN1+++3hsUSbgAagRJ5YuVinCF9keEZxHUiha0VYovcBbgBiZACP3LumaLXBmUpjVl+IJC+p9ddfv6xvhN4JxmCEkuFJRFnm8oorrijdq9RPPJzOPffc8DwiFxLJq5dffvkGh0j0mbxKOv+yeZYB9PC2Kl6vqxkiWZZlWZZlWdWUIZJlWc1G1YJIAAkSPRevY5WASF0gkqADnjQXXnhhOvXUU2s8owiEcgM+kfCaNnIwUqxThC+yoUOHxnXyN+laESLJEwlgU3z+wqwSnMEqjVl9IRI5hzhnzIvPqWTkLSKBNs+fMmVKXKvUz+OOOy4SZTO+ulYcl0r9W1yIRJLtSnmyaptnDODF9WIYZH3MEMmyLMuyLMuqpgyRLMtqNqoWRNpxxx0jwTG5bYr3KgGRukAkDKiBdwxeKM8//3yN+0UgdM8995R2+sLwTKH+iSeeWGudInyRHXHEEdH//LlFWKI8RBdccEFZ3S8zQt2KcAarNGb1hUiEpgH49t9//xrPkeV5qLCHHnoo2tBuZpX6yZxg+bXiuFTq3+JAJNphXJgTzhdlnjF2jKOtYl6o+pghkmVZlmVZllVNGSJZltVsVC2IpAV/pZ3IKgGRukIk5SUiAXTxHlYEQiS4zj1v2PGNPpC8u7Y6RfiCkTiabeZJrp0/rwhLgBcArtVWWy3ACzCNa0CPWbNmldXNjXYJs5o0aVLsBofHDNcrjVl9IVL+nEGDBpWgC8m4VY+cU7kXFXWBOrpfqZ9AKcLXHn744YA0JD9fffXVGxQikQ+LctqNbVHmGdOYLCzJ+aKaIZJlWZZlWZZVTRkiWZbVbFQtiAQ4YZGeh3wBG/AIAXzgpURuIDx2yGGzzTbbRHk8Slj4s8jfa6+94tqPfvSjsu3pMaAMSaDvvffesutPPPFEAI4VV1wxrbHGGrG9PGFN9Aeos/XWWwco4lPbx9dWB6BFiBY7lpEzaNNNN42+k/dHOXaAKITVEcZFHii2ppeHEqCEcCraXHrppSN3E2FgebhX0SZOnBjlAFUkfX700Ucrjhl9/853vhPP5fkkkCbRd4sWLWLMgC/sHjdmzJiAO1zjvQWGGD/CAElA/a1vfSvGEthD29znHQlJJNyL9//BD34QUK+2fgJxHn/88Rhj2uNe3759U5s2bcITiF3jSDJO2WL/yJ+k/pHEm/ln3IE/7BhH+CDPBCIBrmiTvtI/6vBdUb8WNs+5KXF4Xre+ZohkWZZlWZZlVVOGSJZlNRtVCyKxNTxJi/fbb78a92y2+hgQqeiNVV8DMO2www41rtfHDJEsy7Isy7KsasoQybKsZqNqQSQMT5Nvf/vbEQJWvGez1dUqhbPVx/B8w4Nq8uTJNe7VxwyRLMuyLMuyrGrKEMmyrGajakIkjAU7oViPPfZYjXs2W12sGhAJsEmIHHmYivfqa4ZIlmVZlmVZVjVliGRZVrNRtSESRnJt8t688sorNe7ZbItiJPYmB5LyKQEni2W+zMhRdcABB6Rnn322xr3FMUMky7Isy7Isq5oyRLIsq9moISCSzfZVNkMky7Isy7Isq5oyRLIsq9nIEMlmq5sZIlmWZVmWZVnVlCGSZVnNRoZINlvdzBDJsizLsizLqqYMkSzLajYyRLLZ6maGSJZlWZZlWVY1ZYhkWVazkSGSzVY3M0SyLMuyLMuyqilDJMuymo0MkWy2upkhkmVZlmVZllVNGSJZltVsZIhks9XNDJEsy7Isy7KsasoQybKsZiNDJJutbmaIZFmWZVmWZVVTS82dOzdhH330UWrbtm1aaqmlwr72ta+Fcfz1r389ffOb34xPXbPZbDabzdb07Bvf+EYY/1/z/7ZlWZZlWZZlVUtLffHFFwn7+OOPDZFsNpvNZmvmBkDi/2xDJMuyLMuyLKvainC2OXPmpM8++yyNGzcuDR8+POyaa64J0/GIESNK5zabzbYk7JJLLkn9+vWz2WwVrH///mEDBgxIAwcOjM/zzz+/+P++ZVmWZVmWZdVbAZH+9a9/pb///e8Bk/BKQvJQ0jEhb7pms9lsS8L+67/+q0bOF5vN9m/79a9/nX71q1+Fcfzzn//83//jW5ZlWZZlWdZiqpQTCQMi8Yk4xtDnn38eCW1ZxFmWZS0pAZHeeecdm81WwYBIwCOOf/GLX4TNmjWr+M/IsizLsizLsuqtUk4kTN5GSGCJc2AS3kqGSJZlLUkZItlsC7eiZ5IhkmVZlmVZllVNRTibAFKuSmDJsixrSara4Wz5ohsPjuL9olVapC+sbm0L+2J7tdVvTFtYP5uyKXTry8ZatqjlFmZ5G182d4vyrC9ro1LZSu1yDe8jyvz2t79Nv/nNb9Krr75a/GdkWZZlWZZlWfVWQCTLsqzmoPpAJEGG3MgVw2L7rbfeSm+//XYstt99992yOvkx5Tl+8803o7wW8IIJLNgpwz0+VZ7z/Fpu3H/jjTfi/uzZs0u5bHSPdnVMX2t7l2JfMfWRY/VRbfOumNpVmfy9mpLpndQ3+q7+cp2xxzSXGt+8jtrI5zwfH8roO6Ex4Vo+Lho/rtMGxnV9byinupRTXcqpD/k78ann0YbeS/eoq7L5HPKuXOe7qGt528W+GiJZlmVZlmVZ1ZQhkmU1J33wafpixq/SFw/MSHNHTJxv59yV5nQZkea0HpT+tfEpYRyHzbvOfYw6YdSfZ81R1YBIAila5LOI55zFOcdczyFEDld0X8Y1tafy+bNVXs/Vwl7nAAZBBIGAHBrQroCE2iw+O7/Gud5D/caK/civCYAV+95UTO9Q7F/xXO+TX8vnXXXyOVQZzY3GLX+GzgWrKA/AETAS1KFcDpwq9VP3ZIJMgki0Wel99H3M+0S9/LuXP0vtc/7KK68U/xlZlmVZlmVZVr1liGRZTVlAowXASICoWgZkElxqLqoPRMpNi2stynWshbjggOANx6+99lp4DHGsECHa0iIeL6IcPuXeJ4JT+bN1T+CAa9TPTXCLMphgEdfpozyiBH9Unmf97ne/K/VP74Plx+zYxX2eTf+xHEY0JePdXn/99dI570E/Bct4l5/97GclyKMxyudLY8x45eNOexpjjgWXiuCQeu+9916MLXW5T9vUUzk+5aGkueG+5kNzlH//1Ff1h3PKqgzlOX///fdL7wYU4jvJ82ibueOYsoZIlmVZlmVZVkPLEMmympo++DSgEV5ERfDTUFbyWpr33KbspVQfiKQFuwCBTCCChbhATb4Yz+vRDteBGbon2CBooPbyZ+WASnAo74Mgh+BB/kzKFz2RBAd0rLa5Lzgl4CTTszhWe3lIl+41dcvHVOCLMdK7CA4VAZDmU2On8cvb1dzkY8onls+v6qover7mWRBJ9/OxVb/zucqfL9N3QpBPc6b30XeFclznXJCNsnyqr7RtiGRZlmVZlmVVU4ZIltUUtAAcFeHOItvO/cLmtB+S5nS7Yf7nPIvrxbKLYOGlNK8/TU11hUg5FJBXhxbtAhICSJTJQZLOc7CTgxquyZNEkEKLeLVRCSKpLYEPeZio3byNvKzeJzf1g3s5MKmtrfxdKllx/JqCaVwZA0weQFzL5zEfZ40P5StBJM2PTG1rjPI2dT//VH3V0/cEmMN16mnecs+pHCLVNt5qS33Qe+RzSPvyxJLHmepqzPSehkiWZVmWZVlWNWWIZFlLUnWBRzv3S3PPGZPmDns4zR01NX0xYVYpv9GXGmXnGfWoL9BU4xkFa2owqa4QSQtqPllQs/gWWNHiGyNcjU95dxQX+AJCn3zySXguaYFOWwIaKkdbWA4i8r7kIEehVAIOOZBQvwUrVIa25R2j6/lzBFF0Tc8S0JCHi+4rlK04bk3J6C/vLY8b3kVjoHcQ2OG+5k/zqWuCLxxr/jWHGm/aVAijxlbfCXka6ftQDJcjrI42PvjggxLkUZ/VRj5XglIKlaMdgagPP/wwzvX95FhzRTsK2eOc+hwLJhkiWZZlWZZlWQ0lQyTLWhJaFHiEZ1G3GwIc1YBC1TLA0gKoVOP5TRAm1RciCQDoXGABywEO9+TpokW/FueqzzVBiqJRX14mLOwFLJTDJvd6yvsCCBAY0TmfPFf9Up8FifQsrgmkcCyQIKBFHzBBh7yv6gfXF+YdsySNPgq6qH/qO/3GuJ6/S/4emkMBN64JDOVzwT1BJq4zHoI3Kpc/S0Apn6+8f/rUdUE8ruXwUJ5s6o++aznYo47a4FPGPfpLziSO8++46hgiWZZlWZZlWdWUIZJlNaYWAR6FtxGeRkXg09AmT6V5zy/2qanApMWFSAIwWvQXYQL3OQbIqJ7qAhRI4iwYIzigdrWoF4zAG0VwSBBJ7cpUj3I//elP0+TJk9PDDz+cHnroofTII4+kRx99NM2YMaPUX8EJecDknkg5RFK/eC6wgnvqx/PPP58efPDBNH78+LD77rsvPf30000eImkMuCZwI7CCFUFPcW6KZTUuXFcZXQcA8hxBPEDMtGnTYm4eeOCBmB+McVO9HOTJW4z+4GFEGdoS4FNoG/cpx3Xmhu8Acz5u3Lgw5uepp54q9VuAifb0XeC58mISJDREsizLsizLshpKhkiW1UgC1BShTMkWhKrVADtLygBKXwKTAGKNrfpAJBmLagEjFt7yvuEzBy1c41PhTPIoog7lVI9zLdwFAxTOxDMEnrhPG9TlngCAvJQAA9S75ZZb0vHHH5+23HLL9L3vfS+1bNkyHXbYYenWW28tgw0CEQIqXMc4pk9qlzrqL+dcnzBhQurbt2/aZptt0uabb5622mqreBbXuC8w0RRNIIU+ap64ns8L7ym4xHkOBQVt1I7gj9qnHiDn1VdfjXvyFgIcjhkzJp188slp5513TptssknabLPNUvv27dPFF18ccydopLA45ohr6i/taz54Jv3iPtfpFxBo6tSp6Yorrkj7779/2mKLLeIZ2KGHHhqwirKASdXP30PeU3oXQyTLsizLsiyroWSIZFmNoFq9j5oaPCraQmDSkvBKqi9E0qI6ByosujlmMf/ss8+mn/zkJwFTTjvttHT66aenM844I5199tlpwIAB4XUCLFAdyl977bVxj3J9+vQJoDBq1Kj00ksvlaCPIJLy25Dvhk95zah/tInXyZlnnpk23njjtMIKK6SVV1457bLLLgEWBIUoC9S4/vrro2+Uv/POO8ODRW0JLOi9OVb95557Ll133XXphz/8YVpnnXXSt771rfS1r30t9erVq8lCpJkzZ4ZX1qWXXlqaEz4x5uv2229PL7zwQmnnPMb7xz/+cerfv3+UOeuss9LgwYPjGl49gjeUlVeSQhjl7cM4yPuJ9iZNmpSGDRuWdtttt7TKKqukr3/962nrrbeO78msWbOinmDi3XffHdf5TowcOTL6xpwJcPFsgUhd49l8b+65557UtWvXtOmmm8YzMOYKLyjalqcTpu8zxrkAqe4ZIlmWZVmWZVkNIUMky2pIffBpmtNlRA0A0+ThUdEWApPmnnNX8a0bTPWBSFpQC+IACRROxAKea4QonXPOOWnDDTdMSy+9dIAVPoE5a6+9drrkkksCHAnQ4NFz0EEHpfXXX79Udqeddkrnn39+eI0Ixqg8niZAA7xccjhBOQACOW3wgsHrqHXr1vFMINL222+fLrvssihLG5SljXbt2gUAWmqppdJJJ50UcITnyBtKMIV3FVzQe0+fPj0Ax7bbbhv1sRNOOKFJAiQMgAKwA+Asu+yyMdbAlW9/+9tp3XXXTT179owwM8aF8ozjiSeeGB5D3/jGN2KcNtpoo9S9e/cAbsy3YAtjojA0eR4xRhj3GUMdM//HHHNMQD6e//3vfz/GHojE2NEm833KKaeU+nfggQcGgAQQCTQJZApI5uFp9A1Y1bZt25gXvls/+tGPor76I+8mebapTfWBa4ZIlmVZlmVZVkPJEMmyGkjAlyJwCQ+e9kNqQprmYhNmBQCr8U6tB8X9hlZdIRKLaIV/KTcNi3DdZ9ENQAC83HvvvemII44o8wIBFBx33HGRQ0hhY7Tx4osvhkfPXnvtFWCD8CPCnR5//PHwOhEgyGGSnifAI5iQ95U+0CZeQiuuuGLabrvtAioADOTFArTYZ599on9ABiAKnjpcpw1Bj7xteb7wOWXKlPDMAXoJVNBGsT9NxYBCgCS8ioBqyyyzTLz7GmusESDvpptuKuUKYpwBMXiEHXnkkWm55ZZL3/3ud9PBBx8cOYZefvnlaLP4nVBdgZgiUOMckCOIBJhizk899dTS3MqrCS8kxpQ+7rfffpFziufmbep7xzWFKXKd42uuuSYgoeYXqIg3VhE4YfJCUgijzg2RLMuyLMuyrIaSIZJlNYBqC19rVt5HtVktXkmNEd62uBBJC2sZ5wIJeOgQOrbnnnuWIAB5ic4999z05JNPlrw8KAuwIfzskEMOSauuump8ErqksKXcI4RPFv8cs9iXN4kW/HxqFzW8VoBIeCIBkXbYYYd05ZVXloEhIAkQ6PDDDw/ohZcO+XTkiQOcEAwSeNK5INKFF14YoXK8J9ajR4+yMLimZBofYFHnzp3T8ssvH3PDGHXr1i3CEJUTSUAGzyTCEvHmAsIMGjQoYIoAkWCM5kOAkOdpzgRiBImYc7yZyCH1zW9+M3JKCSIJ6PB58803x9xgzBNeYnwv1Baf8nqiDwp55DrHzOcBBxwQ8wLko/+EK1I2B6AaGz4NkSzLsizLsqzGkiGSZVVZhHcVAUuEr42aWhPINGObO+zhmu8JKGtAkFRXiJQvtAEqgjv5YptrgBm8i5544ol09NFHxwIeUEACajyM2DGL8gI0eKUQAgc8IqQKWEBdAEbetqCGPnkOQEFhdVroaxc1PIratGmTvvOd76SVVlopQriASMADGW0BG7DcAycHQDrn3fRswRLy+xB2B6ACxgAq8EQqttFUjD7Rb8b3vPPOi3Gh34wREG306NFRLh8f5oZ5W2211cKTDA8v2tGc6BPwxlwwlvrUmNIm4yfIA0QiTA7vNJ5P0mvC2eR5Rpu0kbcnWEVbtKGyym3EvCunEmWBRVdddVV4IinUkJxIfDcpL8ClY7Wt6/m5IZJlWZZlWZbVEDJEsqwqqhJAatbha19mE2bF+xXfuaFA0uJAJC30c48Orim3DIt+FvF4l5ALiZCl9dZbL+27776R8Jh68mbC8wdvHryGyC101113lXb1AlYBEZ555pnYcY3kz8cee2zq1KlTeJiw+xY5iAhbAuhQjz7SF+AHoWo8F1jygx/8IA0dOrQEBtglDHDVoUOHAA3YiBEj0vPPPx/PpIwSZOMBg1cLuZ4Iw2I3McrvvffeAafIE0S4F0AEOFIpjKspmOYIcIenGHmoyDfE+Oy6665xDQBDOcaeub3hhhvCE4iwwIEDB0Zya8aY+WGeyW/EnJLrChBEWeaFMSIMDs8lwtAEeOgH3w08toBHjFmLFi0isTkgiDKTJ0+Otgidoy3GmsTrJDNnjgWU6CPhbbfddlvq169ffDeow7P5ru2xxx4BquSJZIhkWZZlWZZlNSUZIllWlfTFAzNqwJQ53W6oCV6+alYhvC1yJM0bj2qrPhCp0kJbQEGAQmFfeKEAhwhZArAAKsh9c+ONNwZ8UAgSibUBD4QaAQDIhaRnADsAEIAIAAHJlSkDvCE8jnAsAA75fMirRL4fnk+71AM+bLDBBhGKBaC6/PLLo5/AIcAD4GT11VcvQQY8boBRwAyBA9oEPgEm8Djiua1atQogQS4k8vqQU4h3JPl0U4ZIjA3wjjnD6wiwRgghIAmgRLihQtUYI8YBcAbgI2SP8DKBROANXmUkK+edAXIYYw5Yw7sJ7yXqAZ8YV3kuzZgxI+AfYWyMWREi0W6XLl0ioTfzAmhi/JVYW6AQoMVOcZTlObTHnDA3GOfMjSGSZVmWZVmW1RRliGRZVRAw5T8SIMlqA0kzqptsuz4QSaaFtRbb+YJbXix8knuHhMgs5PFGAioAZAAB1AE0sY07EAEwBHTC60f5bthyHkAALCJJN8eEqQGeSJINQCJUDhDUq1evSPhMeBOQgfw+gAd2iQMiEU4H8ACOAFLwOMK7iATTggyADQAGMIP+0c+LLroodvUCtPAeHTt2jD7gLUPuJsASIEa5n2hDYK04bkvaND8APN7z0EMPjfFRyCHhanh9AXt4ByANY0hScpJx894KIWMOAEyAHsIQAWuM58SJEyOPEqGEahfPMeaScaU+4wqw23rrrWPMAI29e/cODzDuA2vwbgIOqg12WaMNEmMrr9X1118f88H8k/eK9oYPHx59oH/0PYeEhkiWZVmWZVlWU5IhkmUtpgAlNQDSVzmErTarENoGSEoffFocsnprcSBSvrguwqQcntx///2xTTveQMACvHXYcQvIQE4bwpNY9HMfbyQgEOFKgARABqFUeB4BoPCGufTSSyMsih3g8DTC+wR4QLuEt+GNRF15IhEKhYcNXlCAkCFDhpS8hPCGAWDRBn3jGXjUAFcULkUScMLdSDzNfbyQzj777OgD/ccz5qijjkpbbbVV7CwnT6TiWDUVAwwB7hgDkp/j4YU3knaWY6zJecT7AXqYP+AQY0Q4IaFragtIx7sSLggEZJ4fe+yxmBvC1RiXNddcM8YWzyS8kZhv+sDYA/223HLLAER4qFFfHmB8MrZ8J7jPuBKayHzRN30/qMOOcUsvvXSExvFMQBf1gU14NzFnzolkWZZlWZZlNUUZIlnWYgpQ8h8PkGSVQFKXEcUhq7cWByIVPY+08AYQ4EUkTxx2LyOZtfLSAGLwfiGkjYX+gw8+GCFUgACAAPBBoVSEvJEfiZ3B8PY595xzojzPwtMJTyAAD7l6ADiADpJyK9wKAEJeHO4DmnbcccfwXuIeAAIvG0ATIW2ADjyNABtAJN6B/gFKAETc5xl4xuD9onfn/cjTBGgh95MgUg4ompLxXowrx0AWoAweYPLUweOKMcJLC4DG8c477xwhapwDiKjLGDMX5CnCQ4id1u68884S4AFUAQsBO0AgYBEeWk8//XSMPSCHBOSEm/GdwIOI8vSNseM5gEaSfXOf/gGRlFtJbRDeKEBEOCSQkesCUVdffXV4whkiWZZlWZZlWU1RhkiWtRgigbQBUsEmzIrd6PJxqVZ+pPpAJBbSAARBIgGdfLc2eSNxjwX/2LFjwwsIwIIBJfCAoSyeRoSoAXJIzIx3j+oDCjgHaAAU8JwBLmgLdnYYI3EzgAqAQ84jgBQAg7ZJrC2IhCcSkInE0Wobr5o77rgjcujIE4eQKkKh8IYCmgDAACAAJp6hkDm9KxCJd+GdAE20ARxpquFsMvoGZGEMgHr0HcMjiITX5IHiPfHsATKRIJ2xZ04Zf+abMQREAfMIgQMACeBRjlA3ABwQCFh0/PHHR7uUAeRwrsTajHGfPn1KUJJ8SzyfMDgBLiASUA8PKWAjx3vuuWcpZxJAkTxX1OU7wDP4fpGnyRDJsizLsizLaooyRLKs+uqDT8tAScCSCbNqQpX/QJs7amo5XCOsrQqqD0TS4roIkmR5OYUcARkIKyM3DV4pJKIGtACYAA2AAIACnix4yggi0QbAgmss/AlvIoky27YTGoX3C3CKkCnC2ch5BERSKBoQieeSrwdPJGARnjVqG08kcuxwXeFs8kQCiOA1Q3kgFf2mDULZCNnSOLCzHPALQCUQhcdNUwVIyodE/8g/BKRjF7S11lorQsJIhk0uo/Hjx8eOd4wvkAn4RnlBIiVPZ6yBNiTNZrc7ckThDcQ44RlEe4BD5hzgBwjke0I4G4nSyafEc4FIeCLRPn3ku4EnWefOneO+PJEAR9wDXpEzSXmXmDvKAiwBPbwf0AuvsdxbyRDJsizLsizLakoyRLKseoowrRyUkFi6CFP+k43E4uXjc1dxCOus+kAkha4J9BQtLyuvErxGACt4uQBjSHIN3AEKASjIyUPYEUCmuLAHIOGJBDwgdAqvJXIjEd5GMmY8jAAIeArhiURomcLpgBDkSSInEgCIOiT1pm3gFCBDEAnQscwyy0QoGjl1qI93Df3iOYAK2jjvvPPCA0rPwLOGHd/I+UMZ2gFEFYFaU7F8dzZ5bF188cUR6oenFeMI2CFBNp5BJEIHMhFGRnlMO6zJkwlYxxgcffTRkVMJUEMb1KU9xoScV4cddlhAJH0n8HICLgEA8VginFHhbMAa2mW+teudIBL38BTjPqF0AEDmDkjFNe5rhz5AGOFsTqxtWZZlWZZlNUUZIllWPUR4VpmnjcPYalqlsLYZi7dbW30hkkCSFtsACaCKwIo8lLQIZ+ENvGHBDwwA+gCUyHWEB8/uu+8ei388RxQaR11AAXl3AEN4xFAHWEM9cirdeuutAQjwNAJWsMsaoIm6OUQCYACbACX0Q/0jyTOeTfQBuAWMACLhaQQsYZc4EnHjiYQ3DPALbxngl8aDcDaeSdvaRQzowjs0VZAkOKcd8EaPHh1AB08x5gf4wzkePIwdQAmPpffff780Nxjhfso5RE4jvIm6desWO+AB54A6hKsxdsCirl27BpgD4OFNhPcZgE6JtZlXJf3mOwO4IpyNPlGG0ES8j4B/hLThLcV3inFn7gCS3Oce78b3h6TtfAeATLRjiGRZlmVZlmU1JRkiWVY9lIOR8LIZNbUmRLGlucMeLodtixnWVh+IpIV1DpMEbYoASWXxLsGDBDChvEGrrrpqeAYBhwhDAi5QnvYUKgVoANAAjhQSBVQAegASqAOo4DoQCY8myqsPQCQSQrN7WJ4TSdALiEROJK7TPv0SRCJ0C88oIEkezkYIHcmoBRcIeQNyAZEog+GJVBy3pmKMi0IGOWcOyQHFO7ADHeOA5w9QiDxPQBfmjjlRLiTN+U033RSJxglZoy7JxYF0hC8y54QW4h3G3ACL8FSSJxIhcOReAjLxTAAUEAlYRfsAIOZPOZEoA0Ri7Jl7wtmAeUoKzveqffv20ScgEnNMGyNGjAgYBsiijCGSZVmWZVmW1ZRkiGQtUX3xxRfFS01ehGWVgZFuN9SAJ7Z/W3G3tsVJsl1XiMQimlAmFuiCPUWPGy24lXiaY8oDbNhuXRBJ+YMAFf379y8lbQZwUI92uYaXCwCA8uS/wcuFMCr6AqwAQG244YbhaYInEm3RR9rAu4kQKCXWBnKQKFteOOREwnMFiCQQQa6mCRMmBEQCVuDtpJ3leAbhWiRr1vvirUReJ0LigCW0AWjKk0w3JdPubIy1oBDvCWzB6wgvMQEXvIMAYkAm6jHu8l5i/Al3wzuL8i1atAgIhGcWOZd4FnmRlFh70003jRxIgDnq8kwl1tbubNQHHHKfZxFWyPwqcTZeR+zWB0ACEHEfsARgog/sLEdoHqFyvBdACi8q4FKlnEi5Fb/DfBoiWZZlWZZlWQ2tRoNIwIK5c+fWgAZc++c//5nmzJlTOlcZjrFcxfqc5+X/9a9/1WiDtis9u7FUfI+8H3n/c+XX+eS9Pv/889I4cp7Xq+09i+2rPmWx4rM5Vzs6L5ZBaqN4T+2rnsoU20W8w9/+9rfS3OfP0nHeXrGMzvN+VCpbHJO6irr6XqF/tR5UDpFefCd9/vzb8SlwMnfGL8PKYMq8+1h+vbbjYrm8zUrtzHnhnfTPZ98q6wN9wlQu6r4wv+6XPaPYn2Lf8ufkZYrXo+wjM8s9t7pcU/Y9qIvqCpG0sC4urotlclMZoAwJlwmZUqJkwAA5bwADQAGBKe2+Ri4kPF3wWsLDB0+js846K0ADAIiQtpYtW6bll1++LCeSvG0ARIAFkkbjRQTooA/cB3LRxqhRo8KLSIm1gRZcA2DRZ4ASOZjUB3YZI6QNQIHHC2FbgCq8nQTIjjvuuBJwKY7HkrY8FxJjwDnvwlgxDkAhvQdjd/PNN8c4UV4JywVUmAvNJ8AJKMR4AXEAPHgAqT15IgGRaEs5kQCAjCv3yZvF94D7jD878jEfChMk7BEIiAca7wCIAtgRzgjgI/cVoWv0QfmauK+cVkAkQCL1eWdgGs/Sd5jvHmOi73jxe26IZFmWZVmWZVVbjQKRWDD++c9/TrNnz46/+pIzBLd+ffKLN78c/8///E8Yx1wjfwTGscqrDr908xd1FgssnFhcAiRY7GMCC4IlOdhYXKhQV+XARX36+9//nj7++ONYWLDwZKcgvR+LGRLhsuBgIfCXv/wl/eMf/wjYpvcTRNL75O+pY6QyOuZ+XqYIYNS2xigfK9XNy+pa0fJ31bHmRW0IIuXPy/tarKc6OlY/ihCS40rvoLbrItUvvev9hVxI3UYGKPnnc2+lt0c/kp65clTYs1feHqbzkl3x47Di/Zeuuyf9duzk9NmkmSXQw+e/nv9FDXhUtIA1CyBSwCzqc/7c/PNS3QXtCR7lECk/rwSR9Ky8H8XrxTb0zHhu+8vLx23etfqoPhCprsa/OXklAX3wFhKQYeFPyBNeSvycEtx5d4EnC6ABUIG3Ep5EwADAxHXXXRdw48ILL4xQtzXWWCPa++53v1vaRp4d1tg1jTCpVVZZJS277LIBG9iqHogAEOFnA94veBop786uu+4aybNpg58n/EzEg4rnAEzIFwRcIWGz+sA54VyACgyohAcTP3OK49EULIckAih4GzG2gmGMF4mwgT4AF8oIimk+CfXbY4894t032mij8BRjPBgXhZHJu4kyeJUBq/j5zE58eBYpDxMhcR07doxQQkAN3wm8zgBHCmcDVAGFxo0bF5CIOSQ8kZBFYBTfKxJ6AxJvueWWCG075JBDItyR+rwXHk+AKPI5FSGfvOrycD/MEMmyLMuyLMtqKDU4RGIRziKfX2bJDcFfVfkrPLvq8Mkv0fwyzS/y+ksr4R0sfPhLPEYZPlWPY/5Sz+KOxKQXXHBB/AL/xz/+MZ6Hx46Ai4CF+iLowL3GVA5UAEKffPJJevzxx+O9WYiwcNT7sThh8XH44YfH4nP27Nnpr3/9a9Tnk/p5m5zn78n7AamK0CTvg5QDKerRfhG+SNznWbqm9qifj3klUVbl5FGVX8/BUC71K+8jJnEdyJZf45hrRdiUj9GiSu/Hs+N9i6Fsj8ycD0xeeCcNPaRH2m/V74W1X+P7qcOaW6T9V900zvk8YI3N4zrn7VbbLLVbfbNS+WO+v1u6ref56bVbHyh5FAGA/jbt9RL44Rk52OE6oCiHPv945s30t+mvx6fKY7SlsjkoytvC8msy1c8BlO6p3SI8UnuCTJ/f9lT5uF3zaHGoF0mNAZEADkrGTG4dbetO3p0111wzQIQW70ABIDbHgCSuAxUIF+PnGv+WqQMsAg7069cvQqoADQp5AjgBFs4444yAOUqorMTZ5NDh5wA/40iaTXv8nAB0ACv4eUh7QA4gED9D6QM/Rwl7045jgCnaAmrgeYSXE+3zLO7x85TE0MXxWNImSMdYA0tIlj173s9EoFnv3r1L4WcANwCb8kvJg0n1mSNgHKF9hIgB8hgXwtPwBjr//PNj3gBR2kGPOeQaxvwBljRmfPLswYMHB9ACFDGmwCyFovGdAQgBl/Ayoi/0G2AFSAJY4RVFu+Tb4hnMD/PE85XXSrvPffjhhyU4xNjwyZjIU0uAzRDJsizLsizLaig1CkRiIf7pp5/GL7P8Ms5iRa76LK5YCPBX+D/84Q9hHHONewoLYKFF6MD1118fCy7aIdcHiyfukayWXW0I12ChKY+X2jxT6gMU6qocsghEoPfeey8WhYRKtG7dOhYtLCz5a/OwYcMiLwchMSx0CJ8gES5eS/QZACPoonfhmt6t0vNyUKNrlAcI6Xpt9XJTmRwcaSxzU/vFPuVl9AyktvIynKu/xf7J8rJ6rsoDkvByElzSO9RV6lupD3lYVvvLS5AEYHJxh2PTvqtskrpsvGO67KDuacxpg9Mtx5+bTtu5XWqz7Pqp7QobpqM22yVdfMCxaVSvfunOkwelKzv3Ssdu3iodsdEO6dae56U3fvxgCf4IJAWM0bUFnj0lL6AMFKkfQB1AksoVywoM5aCo5DWUeQ/VsAWgSMfFdsvaWGC6/s+Hflo+dj8cVPZdW1Q1BkTKw4LIRQNI4mcLXkJsC4835ezZs8vKyRNEu3ThKQls4t8zdYAIo0ePjp9teFLedttt0R4AHDgA9CEfEmFplCWEjU/KsBsbPwOAQ3ij8POP++TSwQBLeNJMmzYtvF2UoBlvRryLeD7t0B+ei2cNsIifQRdddFHUJ7k0YAOvyOJ4LGmTZ5ggEkCI6yS6xnMTbzHekfdjbAVPNB8K92JsGEPyEzHOvPegQYPi5y7jIi9Qxkdzw/zRJkZCc7y5GHvqUWbkyJGlcDjGjrnU3PAHAo757jC/zAmQke8Hnk30gfb0/aDumDFjIjk3IYfUHzx4cLTFnPNHh/w7h2lMONa7aswMkSzLsizLsqyGUINDJCSIQagavyQDTZTDgp2OyC/CL7yCAyzQ+EWafCKAJv7qC0xhkYWnDECKBQSLBpKU8ld5vJUIU+AXcnJT4IkjyJCDgMaUgIa8bzgGbLDY6NChQ/zlHK+CU045JRYZn332WbwbCxIWL4SpYPfee28snPQ+RSgj2KJx5rwIVQRpJPVF/VJ7qrMwozwASmOc31P9HBZp/IvtqJzu57BGgEttqlwOjvI+axzy/vBdoY+LI41d9Gvci+XeNMMeLoETQaRO622b+rc9PE0dckv6w4QX0i/ueDRd1bl3QKS9lv9uOnWn/dP484ZF6NrvJzyfXrnpvjRg7yPSkd/bOTyR3hj1UA1vIUGcHCLVgDbZdfqCJ5JC4QSNcnCk+vn9/F1yU7sqV/Rayuvm0CuHSJGf6Zjry8bv8+feLs3voqoxIBKLchbnynXENS3I8fjgWNe1cOe6kmNzLo8QTB4xfBYX+dThXg4ClPxb+W7UVn5NbeRlaEOJsblGHzG1/cEHH5TKqV/Y7Hk/b5XTqTgWTcXUbyw/pu+YPMMwQSOOuScApRxWePPofTX2jIPmjzKaM0xtqT2ehfeZvh/qSzF5u4BP3l/1hfp8ap6Uu0n95Vh90nzRFyU/V3/kdaVzTO+AGSJZlmVZlmVZ1VaDQyQWiVrws6jnL+BHHHFEKSSAHYKAJPzSLWiApw7ASBCJsoRfkBvpT3/6U8nLhAUlf6UFxBACQq4K6vBXXNrI4UoOFxpTeibvRp+BQfxFm3A1+oy3FX/NZrGgsC1gEosDPK0IR+Ev3Sx8eIc8tEvAJX8njTfldKzk1cVygjEqm9fPgY0ATV6f+6rHPY7zsoI7KiuIlMMgrgF58nmSVFbzVula3i7QSaF4Ul63vlK/4tm1hLIJrOB9dPzWP0r3nX1Z+vXdT6S/TPlZ+uWYiQGR9lhmvQBJvbZvm+4989L0u/uejrC1/33q1XTtkaem7lu1TiOP7ZNevWlcGbwpgho9DwPMAIv+/swb80PKFoAkeQHlsEeAJ29DOZTyZ8RzC8/JAZLazfsWnkbz2tLzeG+F4eV1546aWj5+88azrmoMiKRFPmFTgBcW9fy7xTjmHsbPGBbqHFNPMEcgqAiTZNzj37eAgECCynKeQw0BDQEnnkf53/3ud2XAgXYpnwMN+pxDC/VP7QtucT3vQ1My9Zn31Ltxzvt/9NFH0W+Ni0CNTHCJdjjnnZWcOr+vMVR92mXsOM/HSFAn7xNh2IJAmkvqCjSqX5pHPVuQCeMadfi+5XOsPvJd07ypPOdcpxzlcxhpiGRZlmVZlmU1lBoFIgkqAAyAQ4SeAYaUDwRIwi/P8ojhF2PCB7hHKBs5I4455pio+7//+79RTiL8AM8mciRRjjwXgCX+6izgknu0CEQsLlxYFAmY6Jn0h4UCoRPsykN/Se5KyAOeVeoXYIScPgA3wlFYDODFJbjz3//937FQICSCZKyDL7ggjLAM8k4RrkF+KMoyVoQIki+F5yhEggSu5E8hPIZwHby6uE9YC+csSnKAgvFcrpPsnNAL2sEI++Dzqquuirkk3xPgSmNMXwgl4R7AjFAQwmh4Fu1wnYUdcysPJ0Aa1ymr9gk/oc+0xfeDMBHu0RbeXYJa+s7lc6zvQV2ltuK7lIdjHXt9CZDI04aE2RMGXJ1+eddj6U+TZwVI+dWYx9PVh5+U2iw3P5zt5B32DYg0+76nSl4/M6+/Jz3c76pIrv3RQ8+UIBBt/OaeJ9KUy29J9511aRrde0C6vVf/9JM+l6RpQ28Lb6a/Tv15ABzAzYfjp6cJA4dHqBz24xP6pkf6X53eGzclzRhxV7r/nCHprlMuSHecNCDdc/pFaerQW9M7dz6WPnvipfCIemzQiLjPc+jj88PviDbpC+9JO5Muuj7q0j59eajvFdEX4NfTl91c6iftPHj+Fennt45P/zVxxnzgNGFWmpMl2J7TelBxuL9UjQGRMHl3cCxoIA8TzoEGggSCM1q0a/HPdRb9ao9Plcuv0SZARMCCujnMEdwQ6BCw0L28HfUhf0YOO/Qs1RWQKbbV1Kw4H3oveRQJkum6xqIIXfjMx1NtYJpbLIeGAkeUL1olMKRnqo7gnq7re6Tvh95LYErAUO+A6bum75PGpNgX3c+/j4ZIlmVZlmVZVjXV4BAJaTEPHABAEJoGQMLLCFA0efLk9Pvf/z7KsVhnkYPXEaFcJD7FY6dr167hsfR///d/ZRCIX9RJlEpiatqkPPmUACw8j/aKnjbyhGloAR+U9Jrn8ol3A7kw1llnnYBIwCQS95KHgzEAHgl25J5G8ijCCNcDRJ144omxyxLJXzGSvLJ7ELCFXC7siEd9xpMxz7f01tbhALeTTz45PJ4AcYQFkmQWby71RQAMOEUeFTykCEPkmew+xSdt80neKoAQEIg6tMFuUcAickAx33hfsbsU/WWLc66T64p6ACdgEiCRvFfaFYs+kyCYcEXAWo8ePSIhLt5sJKAlt4jGmXdmvPLvCX3Jk4Ivqmgjxn766+WhWJePL3nplLx8shAuDMCDR9LwLienPZffIO2z0sYRzgZoEUTKPYfy9v7y9M/Sm6MeDq+mfnt1Tt222D0dteku6bANtktHb7ZrhMABiN6/f0p4IgGcXr/twXTujw6JpN14PeH9dGLLvQJCAZTObHVgOnyjH0RC7w7f2SLaABYBkMjfdMF+R0bbJP8+ZN0W6aL2x6Tpw34cMIw+vTzyJ+mSDt0ifxPvAxij/OD9j4p3ApadvOO+cb/T+ttGsvCbu5+TXrnx3pKH05yzy7256qrGgEgs3lm0A134tyZPEu6xyC9CHpnghOCDduPSIp8yqsd9lRPY4Tk8U2BD8EGm59KWvFVoP7+n/uVwhbZ5Fv3hOj+DcnAxe/bsOJZnVPG9lrQJnGmsdC7PG441DoInAkbyIhJk4f15X9UR1BE0ooy8emiDsgJC3BPYEVgqgiGBQIy55J7CCDkWsBIsUl36Sps8OwdB6jef6rPekWcxp7nXksbMEMmyLMuyLMtqKDUKRJIAIMCSzp07l3YW2nHHHUvhWohFPgAB2MQ9oAcQAdDANYU/ycOHX9DxUGrZsmW0R7t77bVXeLwI4AgY8SmvqLrChPpI4Ch/Fv0F0JAPSdBLW0kDdYA/ePyovtrAADIsPPAmApoBcAgNZFzIITVw4MCAOWwJzbbheGMBZDCgGiGB2tKbcsAikvayaxAeTJwzfoQHduvWLT311FPhxUR9FlhsIw48AjYBkvA8Inkvc8q9zTffPHbLAzaR2wkgNG3atMj5xPwQwke/8IoiiS27R9FXdh4iiTi7I1GXuQUW8l7MOztc8R0AIvHc008/PZKPU1dQDHCmXdo0x/LEQvn3oC7SHBTzIX0+5MEIJVMYl0K95LXDNULV8CQCIgF1gC69t9+7FM6Wh4tFSNhzb4UBhIA3w484KR235Q/De4ljvIkeOG9oGtqpZ+RQAtjccOyZ6aMHpwdI+uSR56JtYFFAnnnPBDyR3PuZK0cFBLqp+9mp13Ztwyuq49pbpxO23TPAEKBp1g33pof6XZlO36V97Bh38LrbRPu8A55Of3zsxWij756HxU5ztA+wOm2XdmnyxTeENxLeS5d17J6O3aJVtNF1k50iTO/TiT+dn+y7AJF497qoMSCSTIt8hY0JXrDoBy6wSBc8EDiQZ4lAlBbztJFDIYEl2qGc2uaTf2sAAuAAx9RTeYEq9YF2BRTk+SJApPL5+whI5GX1DgIkxXFY0qb3UF8FS/Jx1f0ieFEdygvqCN6pfcY5hzeUYayoq/FXu9zXXBXHmk/BKEFArtO2+qv509xTVte5JgjItfyTstTTO6i9HJbxmY+N+myIZFmWZVmWZVVTDQ6R5BnCAh6INHbs2Ni6Hi8cvEjwTCEkDXCUgyHCldjyGEiAJxLhbEWIhBHmBXghtxLtsb0y9fCwUS6gHCIVoU5jKAcY9Hfq1KnhWQUEos9AEEAJnld4BQF28IAAJuUgijwdePTsueeeMX54ExHmhQcTsIfxAawQ0kduKMAQixnGgYUMnj14f/E8PIFOPfXUgDw8h8UYz9bW1Ww1DuzhOjBo1qxZETZIEnPlqAIy8T70i62zGXN2SmJhJOAF2AIG4lFEnwBPzDUwAG8z2gRoAYgoR5J1ABQAcPr06encc88NDyfgFmWAUHie8Z3p0qVL1KXPJCJXonCNdT73gkF1FfWjnftnlMGPOQ/PLOUUUn4gASGOuf6nJ2eVwtnwCsKASOPOvjw8iASPShBpXnvAIELIRnQ9NUAMu73h6TPp4pEBct6998kISwPwdFhzi3TGrgeEJxHPwnsJGIQHEcAKyNN969YRcka9zybNjJC7gft2mZ+jabn592867qxIAA68Am6RIBzIBIgatG/X9OyVt0fIG/0jNI0cTsAh2j9ora3SwH26xK5y/zPp5fTfj7+Unrjw+gBN2pHu/DaHBmACJM0dVZ4XqSlDJEECwSDBFxbqAhGCCECAHNjk8AIreooIdAiK5BABYMA5/37y+7lxTV4tOdTguqCKvGUEFNRPQQyBJ91XmaZomgvejbHnGu+iedB9zZNAC6b3EqQTfBE4k1dTPn85ZFNbxXnK51/PzNsVRFIOJrWlNjS3tfVZ3zvO9V2iX/mYqA1dy+urXUMky7Isy7Isq5pqFIgEEFA4Fh4z5EQCggAGACdse83Cifss2oESXAMqUGallVYKiERdIJLAlHbwYiGx++67R9lVVlklvGWAF/JMUfLlJSXlMpKAMuzGRogZ/ZVXFoAHw2sHryR++c8TVrMYwctq5ZVXTiuuuGJpTBg32mdXNwAdeZYAL3gH4WXEOJBz6Ywzzig9gzC4iRMnBrATpGLMmBf6sscee8S24SxSPv7444BEBx10UEA67nfv3j2x1TmLeuZB+afUFsfkWwISAn/wtmLe8TpTiB4LN6CYvMiAU3379o2/tpMkG8CFxxGeSoJI9IlwHEQ+qHbt2oXnFJ5nlSR4lIO8ukiJx0kCXQaRHplZIwG1Ek3LE+nPT71Stjsb4OakH+wT3kRApFKS6gUeTHgh/d/U19Lbd0wIDyHK77/qpunu0y6M8DeeAcjBI4lwsbYrbpiO3bxVenTgNemDB6ZF2BkeTEAgQas+rTpEXdoFMinRt3aLAyjxPACS+sN9ABL38Wqiv3989MV4L0L0xpx6QSQIB0IRZgeEAiCpfx8/9Gx4POkZvDPgLLyvChDpiwdmFId8oWoMiCRYkXuSaPHONS3s+RSsycOUqEN5QQsBIQEM1VddPgUD+MyBk+CCwEP+XJ4hDyjBLX6OAn5pl58X3FMIF59qk+dQR4BDxzlIaUomQKN3kVcOnxpjyml8NX4aG+rL60fgLB+XIhDiU/PDczimvuaQn5sCO5TXc/P50D31LZ9fyjLeCk/T90ahdOov9QS5qJsnU9d3h3OFKBbHwRDJsizLsizLqrYaHCIhFu9ABcKigB7AE6CAEmsDjJRYmwU/oW14mgCYKAfYwHNn3LhxpW3llS+IY37ZJhwKjxTCw7bffvtItpyXzfMg1dcrpa7KAYaexyf9Aszw3goRAyYpNAuvHXIFAX2ALgAVdqXD8wdvHkAO3kZnnXVWeDUpBxC5hwSRuE/oF6F+1Ce07cwzzyztitemTZsAWYy7+tavX79Sriogk7yKmDcWPswb8IoyPIPwN3IUAaO4D6zSu+LdNGbMmAjbw5OM8oShAYY0Jizg6B/zrDC7Xr16BZwinA1whScSOZQIZwNE4aEGNEP07bnnnosxYsGk74/GWd5q+VzUVYJPRYhUCkNbkBxbO5/lu5jhOSSIpPAy4Av5gwAqRQhFW+8/MDU9Pvi68EKKcLHVN0vjzxsWoWoBmxbkJjp0g5bRZucNt0+jTuwbnkBAIpJlA5G4h5EjiTA0+ghIwjMq3y2OvEhv3f5IQCT1QYnAsbN/2DFyL9EGzydEj/xK7EJH+4JIqs9zgFmAJoXw4e10W8/zI+E4Hlxl4zhiYnHIF6rGgEi5CQgJHghE5FBHoIdjFvSCGgIZAj45BOIeJm+hHEgISqit/DmCHwIeeT/VxyKAUhlBBY4Fw1RPbedtNiUTFMnhSN5vLAdy1NG4c0/vq3cUbBG8K94T3OG+npPPbd4PhZKpLdXXHOfzqXfRc3Q9f0b+bnp/Qal8bvVZnOd8vLhuiGRZlmVZlmVVU40CkRAL8RwiAQVyiAQ40iIfsEGoE8meKQf0IPcPu5XlYIhPzvmL7m677VaCSBwT3oQHCaJdIEueH6c+QKGuqgQudA0jDA0IAvAC/uB5hVcN4Ix32WabbcITh/AvFq+8P7mQuI83EqFgQBzGlHuXXXZZeGQRGgeUat26dYSHAV1YSACRaJcxJSTu8ccfD68vCYgkTyXq4t3Dcxk7IBa7v1GPZODLLbdcAKVWrVpFMm0SWwN/6Cvvxl/GSZat8De8iQBm7KKGmAOeTVJ1niVPLJKM830AIuFFRQieEoIDpChfSfpOFCGS5nxxxU5iJfixc7+y7e1ziCQQwydeOzUg0nZtY3c1eRbl3kucs1saAIacRwAYwtmAOngbAYjYCY3dzwgj436n9bZN1x11euQzAvCwQ9qF7Y4ueRIRSiYvIfpD+1d27lWCRP3bHh4JvEsQ6cUMIi07HyKx4xthbIJIt/Y4N3I18YzuW7WO5Nl5fd6F3EwBkRbkZbri0BMj8TfjVAaRzrmrONQLVX0gUr4gFzAQRNBiO4cIueULdOry74HjfFFfhDZqm7Kcq2xu1JE3kLyI1Ne87RwSqN3ccyZ/fjFcS++jZ3CcwwUd614lONVULO9XDkz0HryvYF8OYvKxyOcyP87nX+OvOZH3lsqp3XxONS+aU8255obz/Dh/rq7nc6A28zkr9l3XVZa5z6/pfShriGRZlmVZlmVVU40GkZDC2fAqkkeMwtkUVoUAEOT3IbeRkmUDkdh6Xl4olAUSAWLw0KEsHkvAlX333TcASA6R8lCrPFfOkhR90pb2hEzQZwDY8ssvH0CF8cEjCNBEqBo7spHLSHmUeF+8kgA6hPwBbLSTGRCJungD4YlEfTyB5AGGJ9LTTz+dPvnkk1J/gEiCOTlE0pixQCLPEmFteAepD4A7PJ+Ut4ryLIyATnoXyuM5BRiSeDYhb3iRCV7RBl5oQCRyIvXp0yfgEfeAYyQIXxLKIdKcbjeUwZ8iCBJQErRR+Jgg0tg+F4cnUqW6eBThtUPOIYGnvVfaKGBS2MqbxC5vhLJxn13Urj/6jMg5xPNIcE2ImkLJgEjkKZJnFO0DdKhPviI8kd4Y9VDkSxIEI4m3nn3W7gdFsm08kegj3kx4IgGPuN9jmz3iXBBJ7wIoU94ldpQ7r02nNHPk2PkQaed+/x7LLiOKQ71Q1RUisYjGU0SLbL7PfI/zRMQs3OVFogV4fs4iXWFInAsyqBxtzp49P9E24UiCBlynnMLdcm8jPVv9zIGCgEEODfRMjgUK8nocKwwq7zvn8naiLP2kL4B3QQpBEHnrqO3mbowB78v7KXG2xlEgTuOSjyHGeRHeqByf+ZjxDK6r/XzeZJTT/DeGGSJZlmVZlmVZDaUGh0gAhTwn0r333hteN4AMjITYgAd5sCBCvQi1wjMHUJHvzqZk2fIy4Rfl0aNHl3bqAlqQfJkQJ4EjQaPcS6XoIdQQ4hl6rkBMfpz3iwTVLHSuvvrq2KlNUAWoRMgaibaBaGxrz3sCjYBxl1xySYSd3XTTTZEjCOOY5NzAGBYRhJkBqfDqoS7juffee0e7gByNEfmIAFSAIXIv0Y4gEoYnGQshQA6eRz169IhQPAASIWubbrppeE5pxygSYAtscY/d1/BE0vvjiQQAzCGSPM7wfAI4UQfPpxwiUZ+5bYw5lHLvmS+DSIIxkd9o9CMBbfLE2oSzvfuTJ0tJuRUSh+G5RA6kSFy93PqRE+maLqdESBkeQRMGXD3/eMB8I+E2Hj5/mPBCPA9vJRJrK1wNeCNARLgb/cETCYBE+0Ckip5IC6DXOa0PThMvGDE/Kfa8+7Qxqle/gEdAqjycLR8H3jFA1LxnHL3ZrgGmCJuLd92p77/HsvWg4lAvVHWFSJgAQe7ZUVz0c15c5HNf0EbQQdfUTu4FUskEkXKvmOIz1CaW94nyORBSH2Xcp6yu5+8hWKLncC8/V7iWPKtyWPJVMN5VYy5jbDTGs2fPjnHKcyZxX1Zsj/ESIMzb1zypXe5Rv5hnSfNcbLehzBDJsizLsizLaig1OERSyBkgCY8YIBKgQOFsgCLy4lSCSAAmeSLhocK28EoirfA0dmYbMGBA7HQmjxh2CXvttdfi2SrbmMBBymGRwBdJtfnlnt3OFEomkITnFO+Dx47yIxHSBzhhAcInsAzQQ9gb29oDl3g/Je+mHfIR0TZgijEH/rDoAcgAYxh7vLWmTZsWEEl9AyJxj3Fs27ZtKScSXkF4imnhST85JxzupJNOCpAEeKLPHTt2jHdjEUUoHeAHbynmB08owJXmhTlnngmJU2JtEnaTY+nPf/5zDYi01lprxRhQP9+FrTFU5onUfkgNeFSESJgg0pWH/Tt8TEmmfzt2ciShznMqYcAlPH+O+f5uAWE6fGeLCFHDy6jU/oI6eBh99NAzcY+6eBqx+9olHbqVoNV5e3QqJc3mPom1gUQCPDlEUvslz6l596nPbmtAJIWzkYMJiASIInfTDceeWQqZkwfWmNMGzwdV89rpuW2bdM/pF8UOcRH+l0Gkhg5nE4gR8BEsACJwLC+d4sJbHipFE0QQHKBcnkhZMCeHBmovBw7qn8oVYRL3BDT0bNoWnMjfic+8HCaIRFsqq37qObTFOKhPeb+au/GOGgPej3flZ5neVeNFOY0L55TBNEa0xXW+J0rkrbGqNHc5iMrnRH0p9rOhTM+lT4ZIlmVZlmVZVjXV4BAJCabgEYM3EdvDy0MFUEQ4W56bB08WvFEIUaMMXi55OBvtARAAU2PHjk3t27cP0EDiZaAUCbgBKfJYWVIQCfFcIJp2lQOCAL06deoU76g+Mj70EyjEfUE2xgd4xmIPOINnEuFrJN8mCTUghzY0JrQ1c+bMSEA9Y8aMgD2MO39FJ0k1MAZgg6cRQAdgJw+p/v37B6DiuXgH4W2kPCnsita7d+90wQUXBJyirwAogA+AD1BEXULd2AmO+QQQKWk40It7zI08xGgXLzLmmWcCosjxBFyifXIsnXrqqRHORp9zT6Tcs6wxRNhVyRspy4lUNADP3595IyAPMIVk0sO7nBxhaISlnbzjvpEviJxI8ljKjQTaeBP1bNEmIEy71TYLrx52XysBqgXeSy8MvzNC4z56cHoAKZ5HzqSLD/j37mw5RAJqAXLwbALu0P7AfbqEJxMQSO+gnEjcJzE3Hk/szibvqluOPzfgESCKBNucf/bE/JA53p1QvZHH9inlVTplx/3SpIuuD+BFG7lXV0NDJBbRCmUCDggm8O9JHid8CgZxLEDAd5jvYr5jlv49CBzQlnbGytsSMOA5tAHIEbCQ55LC4wQrBHUwwSjKKsRKAAjjOvf5Wcm5wtNUVm1QTvCJ8oILmCCHAEo+Js3d5MHF+2usFFLIMX9k4L15Z8rncA3jXB5keSii2tL4at41pmpL3xnq52Ne7GdDmZ5niGRZlmVZlmVVW40CkRALfjxa7rnnnghnw9sF6MBuY8AUfikXbOKXduAQu6wBF/BE6tKlS3gxAZGAIizeAAonn3xy7PxFeBeABQjBX4zxlhFsECRRPxRG1tCSxwx9kecMYIU+k9sILxsWGrwPZT799NOAP0A2xgavKmATUAZww6LltNNOC28koA35pC699NJYSOJtRDtKaE1YGaFiQCS8kVg04eGkXdDw/mE8GWuNDzmReC7jzdgT/qZFGInKAU/syAbcIRfVZ599FhCLROkAIGAfc8v48y4AMZ7ZokWLAF+E4g0dOjTgE+9D/wBTJN0GEJG0m+8C9xgrPKXIiUQ+JY0HIJH7jS1gxyJBpBffqZETCSgDkCH8i4TUJMKOncrwylkQxsYx9fH0IW/RoH27pk7rbxvwafD+R8WObXgD/W3661EGjyIA0rVHnRZt8Sxs+rAfx+5sgkh9WnUIcMQ9QtEIKRvW6YQSROrXtnMk5abtfz73VpQZ2qlnACAg0Wk7t0tjz7ho/u5wL7yT/vTkrEikTRgb70NOJsLn8KyiX4TV0dd+e3WO9juus3UaekiP8LDi/twJL5dDpGseKw71QlVXiFQ0QSD+3XHOvymM8Ncrrrgiks/jXcf3ku8eOyRyfsoppwTQlHHOdXKECTLkHijAA/7NFeFFDoKwYv9y4CAIIKiVgw5BIMEp7uXeSYJhwAyej6nuwp5ZvNdcTe+pMSSvHD8X+RnHvLEZAJ/MMfOpOednMwagxzT3AwcODM9MvCMF3TReTXFc8++PIZJlWZZlWZZVTTUKRAJQKAn2VVddFUmd5fHCbmOABbxngB2AJn7pxQtmq622KuVE6tChQ7r22msDULCVPZAJQEFb7N4FoACwsDgkFEoASZZ76+Q7tTWkeAbeUno+53j/AGfwnMIzh4UJSa9ZcHJv0KBBaZ999glgQmJsch4BZGiDBTSJyckPhdcVRvgYY8EiiTFk9zIWRuxy9swzz6Q//OEPMR5cJ1RMYWOAnQsvvDC99NJLAaCYG8LNmBdgEOFnBx98cICcV199NV133XXhnUQ9FlTAMDydRowYEWAJzyjAGItwFqwALdoE9NHfddZZJ5Ked+vWLbyXSJrNoh0QBgTkXckHhbcV3wE8t3hGz5490wYbbBDfATyaGA/GqrHFVvQ5/PhiQnkOoKIBktjRDG8hdksT1AEM4d3z/NWjw0PoH8+8GfBGIInjTx5+Lt11ygXpzFYHpoPX3SZC2y498LioA5QCBJEfCQ8ggA55lIA7tPfYoBEBcJQT6cSWe6Upl9+SPn7o2fAWeuqym+K+Em+fsesBUefD8dOjPkAKaKXE2sCiEV1PTb+++4kAUeRXurXneeGBpLxKeE09demN6bVb7o/3BRoR7kbfgVgPnn9FjEl4Uo2aUg6R7p9RHOqFqq4QiYU0gFpeKZwDAfgZI8DDPZLW4+0IzFRyerz2+M7ys4WfU3y/+S7yXQeCU4afOfL2EcTheXwCf/EQkjcK/REA4ppAljyCuJaH1wlICVAJKHFPXlWCUXquIBnl5MWkvsmzRlBKx/KIkpdNcQybo8kLiHFi7ICE2hCAn2+ExvJzB4DNLpP83GO+ubfaaqvFvQ033DDKAdU5P/TQQ2PXUM2RxlDHejZjzVwA9+UBls9dY5ghkmVZlmVZltVQanCIJIDEL/P8Ar7//vun1VdfPX5ZZ7HGIq1ly5YBFLQYGz58eGxvzy/3lCFZNos7kjMTrob30s477xxhbCR3JgcSiwQWDgq1koARwCl5JNGXxgqFysOuZCw4Ro0aFeAFbyC8p3gXwtZ4Nz5JrM1fxYFDLAK0yxzvRU4lwv/wkCAMjEUQ48cx8Im/nNM+C1jKAohYTABjKKtwNoAMkA6IBZQDBgHkBJnwdGLBhacT0AfvoxNPPDHGnnqEqXG8+eabR5/xmALyAZYYc401YYX0F3DGe1J32223jXelzxieTCThzj2q+B7gNcCine+KdoLDQwro2NgqQqS5o6bWAEe5AZBevOaudMF+R6bDN/pBCSLhWXToBi3TkIN7pKlDbgmIpDxHhKQBn/A2wrNn4uBr0+Udj0/dt26dOm+4fXgxnb5L+4BSAKQnL7kxPJIIRQMQAZPYma3j2lsH3AESdVpv23T2Dzum564aHd5A/dseHt5DgkwHrbVV5Gl6eeRP4pnsDEcOI3lOEU7HTmzkacKjibxKd5w8MHaZ477yNvXavm0Y8AjoRZuE1dHH9++fUgrdmzPkoXIYN2+s6qK6QiRMkIUFPf/+5LUj4IK3DiD3jjvuiF0JCb3UDoh437HDIXnb8ILje0o+MX428e8E8Ko2BRdoU+0L5qgMfRHUAW7IS6joyUS/1SbtCRpxLNiTt80nwCoPu+PfE8a5wuGoLyClPuXQoTh2zdk054wtP4OASIBAoCDzxlzys5KfKYKG/MzjZxkes4BFgDwgiZDadu3axf9haj+HcRo/jamAEcdKyN2Y42uIZFmWZVmWZTWUGgUikQOH3DskjQYA8Nd7fonnk1/SzzvvvAjjYsFDOX7hJxxLZQAmfOZGHbyV8MwBXOBxA7xQvh3BG0AG3kB5cuvGAEioEkRiEcwv9SxYAWfkP+I9CalgLMhLRNgFHjwsgAjfEwBT7iRC1oA6vH/f88+PerRBXXZUAyDhfaRQOsYUWATIUTgOY8o5HkosQMm7xNxwj3AOQji4z/jSXxaxlKHP5FbSnPDcyy67LICXIJ68rhQm9+GHH4bnEZCJPmregUQ8k2ewAOY9EfNIGB6hQvoO6FnUoXweotgYAnYsCkQSEALsvH3HhAg5G3nMGZGsmlxEhLKRiHr8ecPSqzeNC88j5UMCICm8Da8f8iY9e+XtkZSaHEN4BN3Y7aw4J2/Sb8ZOihxFEYY25Wfp/QemRv4kypGH6doj55e/vVf/SJ5NSBqhadcffUbcCzvqtHRT97PD0wgPqMkX35DuOGlA6R6fgKWfXnt3eDP9+alX0ujeA9IJ2+4ZAAlgxY5zlI12530CuO47+7IIrcPDCSjGmMTYnJ2FBc6z9MGnxaFeqOoDkXIPEHmM8H0GLnBPi/wnn3wyvO8Al0AkDO8kwR/BJn72AB6A23jeCejkz8vBD9eoK4ijcjnkENTJgYQgka7lcEnwIveAESjK26YPXMshkp6pvsqDSp5J+dg1V8thHO/ETpV4bQKygfQk/ccLE4Ce7w4JFOfnH6G4/Bzl5zT3Ad9AKP5vUpv6FOjTPOZgSfcpa4hkWZZlWZZlfRXU4BBJyoEKMES7rEk5+MmvAYDwTsnLCsgghYzhbcSnrgm4qCzHghSNJZ4naKX35zwHWXwqvI5j7WSH+My9ehgzrhXHQuOm9hkLeV/lyvtRHOu8DM/SM/gUiKvUnsY6f09Mfc8hmgBfXr/YH53zTOWSyvupZwoMNpo++LQcIp0zpgZAwiIk7dn54Wm6pqTXgJS8XDEfkq5rpzZBpZIXz4Kk2nGN5NqcL7in+4JYeDjlUErla/R3gQcUZajLNY7zEDuucY9reFjd2uPc8I7C2wnvKCAU0EwJv9VO3ucSROp2Q7knUoXv4MJUV4gkaMJiGlCp8DDuCf4I+pCji9xrG2+8cSmMlrBQefMI6OCZRL4cQj6BwNwDEtE+4baElSqUjedQj3BToAX3ARRKhM19AA/lybdDCCrlWPgTtklZ6tB+Ho4myEH4J+V0H6M8wB5AAvRSGSXdxng+YaoYbVKPMjmUas4mgMS7MjZApK5du4aXEQD8+eefjzJFiETYIgCd8Wd++E4AsDt37hy56oDutCtvMNrmjxgaY8aTunxyXzBLUKfYz4YyQyTLsizLsiyrodTgEEmL/hzo5NdygMBnDkk4ByIARAQpBFQoV2xLlgOkvA85qKjr4rU+0jvl/aDvgiuY+qV+876CMlzT+1MvH6/iu+TX8/GWiv3I7xXHR89WvfyepL4Vn8lxXk/gqPgMvaeeX3yHSqZn6rl5fxpcBYhUW3JtgRMADBBHUEeQRucAGaxYVveL4KgEYRac5+BIeZXK4E3WRm41AJZg1IJnCEwVnxP9ffat8ETCs4lcS+w2R/gaeZn++NiLpXA8ta0E42ojru/Ut9wTqY6qK0TSgppPeYdwDCBQOBlQCdhAqBJ5bwibJYQSTySgUrENwAz5um655ZbwGARIAJUIc2vbtm0kiCfMFtiE9x2eS3jBcJ/27rzzzoAXgAhgDzsW4s0HpCBkivqE/QI9gFSU5xmCSAALPPrIE0e4HXbkkUeGFyJhqXgKEi5LeCrPPP744yMXHd6At956a3h5HnjggXGPkGDylI0cObIETorj1xxNnkIKKwTwEJKIMWeaf8aVEEZtOMDck3SbMdb3gnBeQhnZiABAR3vMBe0wv4wfXkp77713zD/HzD/hckAo9cUQybIsy7Isy/oqqNEgkhb9RbCh64IE8oJR2fyaQIW8VPI28zYqPa8IJBoLQBTfWSFmORRR3wVcdCwIgwdSXi5/h/zdK71Tfr+2Olg+ZpXKIl1HOUQqPiM3zUc+L5i8jGqrT9nic/VMwafG1pwuI8q9kWoJaSuDNAsgShlkeuHf3kYCTGUQ6cV/e/8UIZKu5UAIeBNAakGZSlBLdXVeAyJllret8oJIJPC+6biz0rFbtEptV9ww8h8R8kYoHDBLbVaESEMeLBu/OefcVRziL1V9IFJxcc2nQrsABe+++25AASDSYYcdFiCBxNnkPCKcLQ8xy0O+FLYEnDnmmGOiHnUw8u6QQww75JBDItcO4W8kaCYkFI8WQBLwhjxmwAdgEJ8AJHKGsQsjXjIkxAcO4c1EP4EChJoSUqcNCkjUj9cU19lwgDbIgcZ74FkFLBo8eHAkxcezRvmByO1E+B4Aa/z48QFPimPWHE3eZbNnz4755VhhZXkIIRCJpP6aN7zLAECCSHnIIyAK8ISXEd8VxpK5JT8c8wREAkiR900bEwAHAUl4jhX72JBmiGRZlmVZlmU1lBocIkk5kBAcyCVgkgOFvFwOX4plsNx7BukaZaQinGgs1fbO9I93Kt7Tu8nrRueCKHrP4jjk9fN7emeONcYc5+NZbCMvK2kOdI1PgSEp77f6ybHCz1RX7asPak/3imF7TUGAlTKIVCGkDVgieKJzQZkc5JTgzLPz4U8R+gji5CAmBzx5O9Gv538REEd1ZQJAekYlUCSPqOK7qKzKU+4PE16IneIOXGvLSMxNTqSL2h+TPnpwetwve48MfAW0OnZk2fh9Pvv3Zd+vRVF9IFLuCSIDBgAVgEmzZ8/fvQ2wg/dPnoAez6HcCynPW0TeLuoRvoY3ESCJ5O+AHYARYIcwKDxVyLVDMnsg0uWXXx7A5r777gvwwG5v7AAGBCJXDwCDMsCNlVZaKXZq3H333eMeMIL3wRMKGMTzqMuOYoRi4aE0ZcqUaJ/nysOGRPlsToBXFJ41ACnA0QorrJCWW265yBWEB9PTTz9dY/yaqzE3ACTmjPA9xo1zwhMVwgdE2mOPPSJ0EYgkTySFo+WwUWGQ5O8jbxJzyrizwcCQIUNi7MjXBnjEkw2Ax7yR9417jenlZYhkWZZlWZZlNZQaDSJ9mQQy8vNc3CuCjuJxpfNK1xpbtT1X77ywezlgqVS+tral/H7xOG+r2EaldvP+SMVyajdvm+MivKtULr9XLN8ktAghbUXYszDLQUvxeqW2iuVyC9hTS1v5dUGdsvu19Fdl1cY7dz6W7jrlgtSzRZsIZQMi7bPSxrF7249P6JveHv1Ijbr5M8q8kLpcU+O7tCiqL0SSsbDGE2X27NklOKT8OU888URAH0APEAkYBFRSniASbwNpSGhPknlCnWiDECc8U4A2ghF4/xx99NHpuuuui7A3gA0eKlwfNmxYJM/HY2iLLbYIbyB2hLvooosCavA82if5PNcBEtQjtI0+0t/HH3887gOHeCaeTjyD0Dc8Zgi5I/ePcv0AtAip086NgAWAEt5IAC8+CYkDTmms8jEUeONTMK04zk3NNNcc0195IgkI8T7kMwLWMYZAH+YD7zHAoNqQcc515g9gBxQEOAKd2FgAwMf9QYMGxVwzr+utt17smkkoXHFMG9IMkSzLsizLsqyGUpOBSJbVHDT3nPLdxebWEtL2VTDBJQxPop/fOj52exuw9xHpjF0PKFm/vTrHzmzsNldsQzZ32MNl4/bFAzOKQ7tIqg9EEgCQ5bmQBEZYbANoyIm04YYbBggCIhFeBphhp0DCwQhdArYQXobHEHWVuBmIRD08f/BOATbhgQIYYrt4wtLIRXT77beniy++OHIf4WW08sorB5QgX5FAF8m1yalDqBlt4q0E0KIu9/EmAhLhRcR9IJA8XvQ+7GSoretpn1xIwCd5YV1yySURNoc3EpCJHEu8B2MkcFYcO503JhCpj1VKaK3wQ44198A2eSIBkYA/vXv3jusqxyfvCzRUom2Fv7FrG+GJjLtgJDthEk7I3OIpttZaawU0VKL1xjBDJMuyLMuyLKuhZIhkWXUQQKTMo6bbDTWAyVfBAEfK2aTz/5v6WvrkkefS7yc8H2FtGOd8fjZpZvr7M2/UaEc2p/2QsnHDq6s+qitEYiH97rvvhgmeaIc0eaYIOOBphCcS3iUs/oEECkvD8AoCNAAIhg8fHu1QXzlycohEGBPJmEmcjRcMAILjadOmxaL+wgsvDECEJxGQAW8YEnELVtD2PffcE+FVwCxgEfl2CHPj/oQJE9Lpp58e9XkmkIgkz+zuJpiB55JyJuFhQ3lA2XvvvReeWEAkIAgQCU8mABeQCXBCn5WUWqCMPtE29T/88MO4LijT1Iz3o//0mz7Sb67JM4nrGICPXFTMN/PGOBKqBkRS/iuM8WCeCVvE40seXuSluvnmm8OjifYpB+gD+DGvtMn4Mt/svtdY8M0QybIsy7Isy2ooGSJZVh1VlmCbkLYJs2pAk+ZuOURSOFspGfiCPEnK51QMkSsa3lpl3lv1SKgt1RUiYbn3ic4BSCyylTiZY7xMDj/88IBIgi8tW7ZMZ555ZiSsPuqoo8LjB9AERFISajxM8OABLlAPcLDLLrtE6BhwAYDFc3iuoAYhT4RDkc9o7bXXDpABRAJCKO8SO4mRoFk5lmiTkDfuA3voF1CL5+FBw+5sQCSFmgGRBLVI0t23b9/wYBJYI+kznlVKrs2ObrwH41EEbAIpfHKucWssKFJXkxcS78Ex76t5FkxkjPH4wiMMTySMcTrllFMi5E/vJigHRMJbrFOnTiWIhMeZ5pkxAfDhtUZIHOCR8Qf04RWGt1JjjZchkmVZlmVZltVQMkSyrDqKUKwyb6T2Q2qAk+ZuAkcKaQMeEdKm+xz/bdrrpWu15VWKewUvpPqGsqG6QiRAAZBHMCHPhyPPFBb+lMMTiaTIeU4kzpWUGcBC8mtyCRGeJtAgzyBBJIxE1ey8BlzAc4cFfZ6Xh529AEOUFUQibE4AiP6RF4lcSIAIvFl22mmngEg8k74CtsiXJEhE7iUgEqCKNoBIShDeokWLAFePPvpo9Jf2gUg77LBDJO8GIrVr1y7AlQCLPHEE2wSOuE8bgkrFMW8KlvcdgMQ8C+AJJjIGABbC2RhjvJEYx1NPPTXySgnC6N25hrcXO90JIjF+eB6x0x5tMi7kPyLkTWGRQKTzzz8/5qyxxssQybIsy7Isy2ooGSJZVl31wadpTutB5d41X8HcSPIwqmQAJgBSpV3dyto4Z0w5cOsyojiadVJdIVK+oOZY3jMKceIakAggwiL/sMMOi8W/4AsQiXuUBSLgyQOo0ZbtWqTn4WyAnTZt2qQ77rgjIBJ1cyjDOTmRCI8DXLBrGlvE48GSQy6ADkCLfhDOBrAgLxP9mTRpUkAkABDeTMAPknhPnz699K4kAec9dJ8cSiTOFtAinI02AVS8M1vSA8oALtp5TuF/tKewQOrLu6upmvrHTmy8KwBJIY2aC+7jiUSYoOZ7s802i3A27mluBf4YB4ARnmja9Q5PJOAdu93RNgZEItk2SbU1d0BDQhkNkSzLsizLsqzmLkMky6qHACQ5HKm0U9tXwQSL5GUUAGlBOFsZVKrkiTRhVvkY4YU07/riqD4QSbBIXj6YgA6fggSEsx1yyCHhlSOo0KVLl7gH2GFRDowQCBKsUTgbEIk6gCEgknIi6RnyjKHu1VdfHfmIgEAk1iYcDegEwKEcwALPJCASYIoyQB68m/B2AWaxuxveTIRhkcuHRN4ALvrKuxK+Rl3ub7PNNgGdgEgai0svvbSUWJucSAcddFBsX899gEs+Tuq3IJzONbZNzeQlxXto/BVWyH29B7mPgEiCQoQrnnTSSTH+1JNXF8Y843FGqJrK4+FFYu0pU6aUxoJ5JCfSOuusE0CRzyuvvDKAlSGSZVmWZVmW1dxliGRZ9VRZbiS8bL5iSbYVxha5jzKPowhzW5BwO4BSLV5JxTC2uSMmFoewzqoPRMKACsAXIEK+7bs8krgGRAKk4EGSQyQBEy3KBZ/UHtcJEwMiKcxJibXxUAFEUJZnCmLg0QKwWnfddQM0rL766rEbG20DK/AoIu8SHkJ4EgEiyKvDc2iPTzyLyInE8zbffPN01VVXhbcLfQWCnHvuuaUcTcAOvJiASIJmJOkmRA4QRT/222+/SBzN83kG48O7vf/++zE+nAMkuKcxa8oQKQ8NlHdXEXwBdkhqDmxjrEhADiQi4bYgFGGPjAPjgmcZYYLMGXAO6ATMAy5p7vAII/k6ibXxMmOMAUsa98YwQyTLsizLsiyroWSIZFn11Qef1vBG+qqFtVXyMhI0EjjKPZJK9QrJtAn/q4bqA5FYSAMUWMQrXEznLLTZaYxrABaSSwNUADOABUKXWISTVBkQBFAQhBBcAqooX5I8fwhzIucQYWcAJ8oCXTDOCZ3DO4VyhDsBg3r16pXGjx8ffdMOX6uttlok4MZjaPTo0ZHMm34rnI18O0AidnEjXxIJtxW+RR4e7vEueCpRnrA7wSHKA5d4/qqrrpp23XXXCKFjLHhPwTKNGe8MJGEcdK+xPGvqaoJ7uQcY1znPc2QRlojXmKAh0IeQRuCS2hJA5H2py25sgCcgESGJrVq1SiNGjIg6eIL16dMnvNnw8GJ+yaHFfKsPjWGGSJZlWZZlWVZDyRDJshZDxSTbX8Xd2oBDAYwK3kfamU3XShCpAcLYpPpAJC2mgScCAvJC4j7eJngMkTSZhNgAFWAQBiDAI4idtShPjh0BBdUHHgwZMiRghBI0kxC7Y8eOAYPIpZR7MlGHhT3eRCRx5hl4GgEmevbsGR5FPXr0CG8mcvTQLjux0Qfq8ly8lmhfu7ORnPvQQw+N62wlj0fR0UcfHffwsGGnMLxj2MGNd506dWrq3bt3eF3RX0ASzxo6dGh4Qam/PE8Qhmv5uOVj0NRMoE/haDlUUqgaY0AIIKF+GifGAWAH4MMzTZ5nen/aAuCR02rfffeNMWOuAX54euEtBojkGgAJMHj//ffHfAvENYYZIlmWZVmWZVkNJUMky1ockWS7ENb2VcuPBCBiJ7Z/PPNmjXtYCTIRzgZAmvf+ZV5Ii5lMO1ddIRILaQGE3HNGYACoMHPmzIAvhK4BkIAJeBMBFvAmIWTpnnvuiV3WBFIAEUq6DIwgrw5hYdQB7AAjMLxQgDI8mzp4NGm7eXZ34x4go23btgGCFFaFR8x2220X28nj5UIfleAaIz+SdmbD6C/P6969e+RS4pNk2tyjnMqyaxj3gUUk81b4HfV593322Sc8qHge7wo0EyhSKJhCAhvTs6auhreUwvLoK3OX95ljwB/eRApN45OxB6qtscYakXicsvLcwjtLuaIAg8A+QhI32WSTGDvmndBDzgFJeHqRY0r18zC6hjZDJMuyLMuyLKuhZIhkWYurYlgb4OQrkB8pD1WTJ5KOMcoo3E1li3mQqhXGJtUVIuUL6vyaIJJAEomRAUV4I+GFMmzYsDCOuUaCbCW9znMpUZ8QMzyOgAqqh3FOAmyAg7x2MPWFdginwsMIsMNzgDvUBSwRNjV27Njom7anpx6flKccXlLqLwme8Xohnw9haewaxnVgCe3SH7yf2I6e8KrbbrstgBH1Me7TLh44+TjpuRorruUJqovj3RRMwFAAUdcFwTiePHlyADrGSONDniiOSWCucWCeaEsQSGNC/ik8vvDuoi7jTFvUveuuu8JjCRhX7FtjmCGSZVmWZVmW1VAyRLKsaqgCSGJ7+yKYaS5WKReSrpNsuwiROC4CJIzr1VR9IFK+sNZxHqIk7yIACaBIkEGLcCVE5jwHQfJMyu9znpcRaNLzaFvgRceCNGpD5QVCdKz+cyyYg6dQEeioDb0bZXk/7U6mdriGKUF2Dl5oV++uvlNHMIvy6ls+xk3J6CPeQxzzHuq3YKD6rmPeUYCQekrArnHJj3OPLM2jPI6KdXStMccq/x4ZIv0/e28BJleVvV/j7g6DS5AEgru7y+AuwTVYIHiABJnBXYO7a9DG3XX+vwEat48BwgAzQ7r7fFm7eSunb1enJV2VTvpdz7Ofqrpe59xKclb22dcYY4wxxnQmlkjGdBLN6iONJRlJxSgW0SaqIZBgVCRSa5HLkuLy4jJidMgBRVFQjCxa27bc8pa+W/FzV49y36Pc9y1GW7Zpz3bVDkskY4wxxhhTKSyRjOlEeIx9UaaMjcW2S1GmBlKlBBJUUiI5HGNLWCIZY4wxxphKYYlkTCfTkkgak6e3lQu+T7PvWUGBBJZIDkfrYYlkjDHGGGMqhSWSMRWgrEiaZ8yuk1SK+14rO32t0gIJLJEcjtbDEskYY4wxxlQKSyRjKsUXP8TTyYqiZUye3lZ/1ZPNv888fz6Fbfj3rTSWSA5H62GJZIwxxhhjKoUlkjGV5IsfymclaXrbmCKThl9nS9PX+H7VwhLJ4Wg9LJGMMcYYY0ylsEQypgqUFUljgkwaiTwi+4htqoklksPRelgiGWOMMcaYSmGJZEy1aGl6258yqW7Xi7qOTKLu0fDraXadEkjbnVv8dlXBEsnhaD0skYwxxhhjTKWwRDKmmrQ0va0gk+rPuKe52Kl0/Jl11FLR7JBHqxxf1elrRSyRHI7WwxLJGGOMMcZUCkskY0YHf8qkFjOT/hRKmu5GQetm0qczog3iqCvII2GJ5HC0HpZIxhhjjDGmUlgiGTM6aYtMyqSSspQirnqybXKJKXLIIrZnvzZII0VXkUfCEsnhaD0skYwxxhhjTKWwRDKmK/DFD6nhjhej1lBR5LQ5/sxcQhC1VRK1FFE0e/j1dDUskRyO1sMSyRhjjDHGVIqSRBo6dGi69NJL0xGHH56OOOKIdNRRR0Xwvl+/fqX3sd7hcFQsBu53WLp5q77ppdUPbiZ3KhXf9zwwzjdkw0OaXU9XigMOOCDtscceDodjJNGnT59S7Lrrrtlf+cYYY4wxxowa4zQ0NCTi+++/T3vuuWdabLHFUu/evdPSSy8dwfslllgiLbnkkvHe4XBULzZYdLm0R69V00ULbZJemn+nZvJnVOLz+frEcTl+8bxdNXr27JkWWmghh8PRhlhkkUXi1RhjjDHGmM5inP/973+prq4u/fHHH5H+/uabb6a33347vfvuuxHvvPNOeuutt0rL+exwOEZPfPj48xEf3TQkfXbu7RE/9Dk/YugmAyN+X+7oCN6z/Jv+V0ewLfsRxeOOKfHMM8+k+++/3+FwtBAPPPBAuu+++yL4fMsttxT/3jfGGGOMMabDjDNs2LCUB0Kpvr4+spMEn1meLzPGmGrjmkgOx8hDtZA+/PDD+PzGG28Uf0bGGGOMMcZ0mJjOhjz6z3/+UxJIuUhSGGPM6AaJxADZ4XA0j6JE4j2ZxMYYY4wxxnQWpUwkxNF///vfmNYmacRrLpN4X5RLDofDUa1AIunJUw6Ho2kgkZSBxOd//vOf6dVXXy38tW+MMcYYY0zHCYkkMYRAIoriiG1YXi5DyeFwOKoVlkgOR8uBPCILifcIJF4tkYwxxhhjTGcyTv6BQZqKbOc1kJjq9uuvv4ZAMsaY0YWnszkcLQcSCXkkgURWkqezGWOMMcaYziRqIiGNytVEEmQi6SluEkvGGFNtXFjb4Wg5EEcfffRRvH///ffjiYavvfZa8WdkjDHGGGNMh2kmkTRtRDIpf2JbUS4ZY0w1sURyOFoOTWMjK+mDDz4IkWSJZIwxxhhjOpOYziZxlINY+u2339LQoUMjC0kUa5Q4HA5HtcISyeFoOZBHeirbxx9/nD799FNPZzPGGGOMMZ3KOCqUDXr6mt4jknhiG9lIbJNva4wx1cYSyeFoOSSReE9GElPb3njjjeLPyBhjjDHGmA7TRCIxXY0oIoHUGdPZlFFQ/KxlxfWiuLzcNqZzKLa1lpV7b0ZOubYc2fIixXbPfyfllncWxePnVOJ8baWrSiQVNc6fklVufTHy/YrLWlrvcIws8kLbCCVPZzPGGGOMMZ1J1EQSrQ0OR7aurajGEiCkikW7JbIkt3TOPEuKZfn6zriu7oraT+2rPsllobLS1Oa5eGzP/dNdyNuGe5v2LK5nWXF5jtpZvwvec6xiHxC53NWyPIrHLPZRcVudN3+f78O9QGh9fq9Umq4okRisv/feezFg/+STT0qFjfmswTzrec2fnMU21K1hOVOP9DQt6tiwjs96z3EtkhxtDclM7qfXX3+9+DMyxhhjjDGmw0RNpEqTD1A1eNYySQsNhPPItym3LBdSpn3QfrkYImhPluUSD7ROy4rryr3v7pS7RyVIWZe/F3lfKFjGdvnvJj9+8Tgt7Z//vtTP2kb767220/F0/uL30Pv8uipNV5RIhOrQ1NbWlmQPr8oGKWaHFDOM8uwj1uf7qFiyJZKjrSGJxP1jiWSMMcYYYzqTqkikfFCqQWc+YM6X54NfvS8nMHhVvSbTfmjv33//vSQDaFM9pU/9NTI5IYrv88/dGd2jgvdkEimDJ99G7ZbLnryt88yfHLaVDCqiZRxL++v3paL5EkOSibpGXbeOwSu/tXLXkAupatBVJZLqz5BRJAHEZ0kjZSeReURWEhlGeQbSu+++W8pUUgYJ27KfPueiyeEYWVgiGWOMMcaYSlEViZQPiDVwljTSQDbPtMgHtvngujjAzpdXaxA7NqD2V7tJLKgv8v5Qe4Pbuu3k97vaM2+7/LeQb6vI2z/vA33We/1m8vNynuLUt/z3peMjDLWdZFD+u+O9rlnXr3MUz6drrTRdWSIxYEcGIYgkfSSXCAmiPKMon86WCyPtJ5lkieRoT1giGWOMMcaYSlEViQQabGoQy4CTQarqISkkOFj+888/x+DpwQcfjFc+a5t8gGyx0T5yEZELo7z9ae9bbrkl3X777emVV14p7SeRYMqje1L3p+77ctk6ZPf88MMPkZlSU1OT7rrrrnTDDTekq6++Ol133XXpgQceiCcrff/99/F7yI8NP/30U8iGF154Id1zzz3pqquuin2vvfbadNNNN6VnnnkmffLJJyXBo98YnzkeEknZRVqu3xKvv/76a+n4FOf94osvSteua8m/Y3eXSPxm3nnnndIUtFz6aFAvgSRJpKwkJFIumRBHL7/8crrjjjsihgwZEo9qL57X4SgXlkjGGGOMMaZSVE0iSQzlA00+M5DW4JpXCQ0GuPwD+KKLLkqrrbZauvLKK2PQlYuO4qDctB/an7bOZQevCIn5558/9ejRIx1xxBElWZD3ldu/OdybEqP5suL9yvsff/wxBnjnnntu2m677VLv3r3TTDPNlCaZZJJ4XWuttdKAAQNC4iCM8rbnmMiH66+/Ph1wwAFpqaWWShNOOGHsO/3006cFFlgg7bHHHiGTkEHqL66Nz7/88kv8zsrBdtwT3333XUit/fbbL51wwgnpkUceKW2j71kNcZTTVSWS5BB/ZtXW1kbwmcwkxBJSiP5CGrGM7T/99NNYzmdlG7EPQumll16Ktt9///2jfwcNGpSeffbZZud1OMqFJZIxxhhjjKkUVZNIGvhq2hTk2RG8ZzkDXP4H/rzzzks777xzWnrppdMss8yS/va3v8U/iJXRoQF1uQG6GTnl2k/v//3vf8dA98QTT0xzzTVXCAn6AaGAWBBsq0wUMwLaI7+ntUztpTb79ttv0913350222yztMEGG6Sddtop7nmyiBCmhx56aNpoo41CDg0cODCkgn4j9AVZRv379499+/btm84555wQRtdcc0065ZRT0lZbbZVWWmmltMMOO6THH388ff3113EtOkYxM0r3BEHGCxlNyKPVV189ruHoo49OTzzxROm3pu9UnAZXabqqRMprGUko8TviPfIHGdivX7902mmnpRdffLE0yJdYQiLxmX6m7Q888MC05pprpkUWWSRtuOGG8Xt8+umnm53X4SgXlkjGGGOMMaZSjFaJpAGoptEMHTo0ps3wP/DHHntsDKLJhpl44oljEMZgS4Wf82NaIrWPltqN9//617/SnXfemQ477LC04oorpummmy6tv/76IfYYwIty+5tG8vbN2ygXSUgHxOiUU06ZVllllRA/CAUyhIgnn3wy7bXXXmmyySZLW2+9dbrxxhtLv5dPPvkkDR48OG288cZpoYUWCoH09ttvx3oKZr/66qshnshsWnTRRdOFF14Yx+Y6inIrD35/SBD6n/1322231KtXrzTjjDOmQw45JGSU9tc+lkiNoZpIKphNO5JhxHKmJSKCVl111ZCFNTU1sQ/bqNYR8fzzz8cUUoTRLrvsEr+/qaaaKq2wwgqRCWaJ5GhrWCIZY4wxxphKUTWJpKyFfKBJ1gt1jjTgZnB8/PHHx/Se5557LmohkZHBQAqJRIYEmUoamEs+mfZDu/F0tuKUJjJWTj/99HTUUUeFyGM62/LLL5+uuOKKGBAL9mffooSyVGpEwiZ/gqDah/udzBPaeeqpp46MIuQD/aFtmCp2wQUXxL1P+7Mtx2Lfzz77LF1++eVpm222CdFK3STkkfrzq6++iho6a6yxRlpwwQVDQCCW2JdtlIVUFEBcE78zppA+/PDDUQOJqYyIRKbG3X///U2+W7XEUU5XlUjIIGUV8TmXSkjxZZZZJi2xxBJp2223TY8++miTqWu1tbXxZx+y78gjj4xsJUQeGUlzzjlnyKSTTz45ss+K53U4yoUlkjHGGGOMqRRVkUiSRMpgECruy2CWoO4LUz/IRmKgzCsigzovyKU333yzySPoi1LKtA31h9qPoC8QDAx6yZZAbNTU1MR0q+WWWy716dMnxJ6knY6R92ee5dJdkWDRvV6uTVhOxhcFyxEH1DwiC4jtEDO6x5E5k046aUzpJDNIy9kW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Y8wYgyWSw9F6WCIZY4wxxphKYYlkjBljsERyOFoPSyRjjDHGGFMpLJFMh2loaCguMl2Iurq69L///S/997//jfedzejo/zFdIjGoLy5zODo7LJGMMcYYY0ylqJpEqq+vT3/88Ue8CgahfCZ4n38uLmMQXNx32LBhTZaZtkP70aZqY/qmKBqKkkD9ArQ9giLvAx2ruF93pHgv634WeVtqe6AP6Iv83qedWab91E+80v75cfP2ZxD51FNPpfvuuy999NFHZfslP4+uh+Pq3tA2nJ9zCbatlJwaGV1ZIjFg//DDD+OVtqfNeWUd7z/44IP07rvvxvt//vOfTYSS3ueDf46Vf9Z69uc963W+fF+d09F9wxLJGGOMMcZUiqpIJAahGhxrMK3BsOSQBqXff/99DIyee+659OCDD6Y77rgj3XLLLemee+6JATGDr59++im2t0TqGHn7v/POO+n+++9PN910U7r55pvTbbfdlm699dYmceedd6YHHnggPfPMM9E3//73v6OvJBbyPlT/dmfUBrmcURtpOZ//85//pB9//DEGey+++GJ6+OGHo63ph9tvvz09/vjj6b333ks//PBDiKT8OPDmm2+mG2+8MX4f6ive6/Npp52Wjj322HTmmWem1157rXRu9U8ui3Rs+hRJQV8jn/j96dj8Hl9++eX0+eefp6FDh8Y9oN9gftxK0lUlEoN1iR8+FyUSr0gk+pM/wySRcpH09ttvp2effTb+rLv22mvTJZdcki688MJ0wQUXxHvuCf4M5DiSR/n+uUAqrnN0r7BEMsYYY4wxlaIqEkkD6fwzg2JlsjD45PVf//pXeumll2LQtP3226eePXumaaedNk088cRprrnmSptuumm6+OKLQ3woW8O0n7w/BgwYkHr06JEmn3zyaOdJJpkkTTTRRKX3vNIH888/f9pqq63SueeeG4PjX3/9tcnx6A/1Z3eGe7KYcaflyhzSK3LojTfeSBdddFHaddddU+/evdMss8ySpphiijT11FOn1VdfPZ1xxhkxEGQfiSRxzDHHRF+1FBNOOGFaZJFF0vHHH59eeeWVJlKL90ggjim4buQQAmO77bZL88wzT5pqqqniPuAeWGqppVKfPn1CZnzyySel7ySZWPzOlaCrSqRiBhKSSEKJ5e+//36813Jtq/fs8/TTT6dLL7007bLLLmnFFVdMc845Z/wuib/85S9pyy23TGeddVZ64YUXIqOJY3388cclWZBnIClLqXidju4RlkjGGGOMMaZSjDaJlGcxAP/gJRtm5513jsHSnnvumQYNGpTOP//8dM4556Tddtstrb322mmVVVaJgRbZEL/99lvVp9OMDUja0X5klpx66qlpttlmi6B9aferrroqXXnllSHtkBUIvOWWWy6tv/76MZB96623SsfJM5Hy7JbuiESNMnNyUapg/XfffRfZXTvttFPaZJNNQtogjLi3kagHHHBA2mijjdIKK6yQ/va3v6VXX301joOwkfw54ogjQvLwuzjyyCOjv4grrrgijsMrmWX0MeeT9NH1qe/g999/j+04DkJr9913T6effnoIrssuuyzkIde06qqrpq233jp+l2RRcS25mKo0XV0i5cs0kCeri77ld0SbkhUm+VNbWxtC6LHHHksHH3xwWnPNNeM3uO+++8bv8KSTTor33AtIvG222SZdfvnl6fnnnw+JpKltOncuD4rX4+g+YYlkjDHGGGMqRdUkUj7A5LOyKggGxgy0GGSR/bDWWmvFIJXpHWQnEVdffXXaYostIiuCwSwZSwxiu3vmS0egL2hzpqXRD2RAkI204IILhqxjECLhgWhi2tR5552XlllmmRBN2267bRoyZEjpOBIREiTVykrpquSyiClreY0jLUcAIOOmm266yDo57rjjQib8/PPPMV3zySefTHvttVdkgm2++ebpuuuuK2UjcUzkDcKH/jjkkEPSE088Ufqd6fcloZf3R/5b1O+PQDKRgTT33HOn9dZbLw0cODDEiKatMc0UyYtMXGihhdIOO+wQg9RffvmlyXerNF1RIjFQZ4qZMop4pe00bY1pgfzZtdJKK4WA4886JBL7fvrppyGVmJbI+llnnTVtuOGGMX2NwT+/PfZHJi2wwAJp0UUXTQcddFB66KGHmgkjSSPOWbxGR/cKSyRjjDHGGFMpqiKRijDYVEYEA2wGzfxPPANp/rf9hBNOKGU5aBDMQIvlU045ZUgMarUwoHQmUvuh3fPsoZqampB38847b2TGMCCWbKB/mLpGf9DuM888c2TOUEdJx8rlhTORmhZ8V9vonldQG+eUU06JqUrULWLAh7BTphGC7+9//3tMSeM3QVZKMaOJ3wvShwwWpB5ySeeTcCJa6gv9ttiGwSa1k/h9HXbYYZH5xDUo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e8VVV12Vttlmm9ju8MMPb7a+M6Ij38fRPK6//vq0zjrrpJqammbrOiOaSSQGZoihP/74I/6X/5tvvmkWX3/9dfryyy/TZ599lr744ot473A4HNWO9957Lz333HMOh6NMPP/88+mll16K12eeeSY99dRT6ZFHHmnyl74xxhjTnaiUROLv2QUXXDCddtpppWUvvPBCmmGGGdLWW2/dbPvOiquvvjpNOumk6Ywzzmi2rqU46KCD0pRTTpkeeuih0rJ+/fq1KpEI/k1RSYnUke/jKB+33nprmmOOOdJdd93VbN2oRlmJRIbRd999l4466qi03nrrhcVae+21S7H++uunDTbYoNlyh8PhqGasuuqqaYUVVnA4HGVixRVXTCuttFK88nn55ZdPyy23XJO/9I0xxpjuRCUk0vvvv5969epV0YyjSockEjKsuC6PzpRIDzzwQHiF4vKuFmPKdZaLAQMGhMhEaBbXjUo0k0hkISGR+F9+JNH444+fxhtvvDTuuOPGDUNMOOGEaeKJJ451LHc4HI7REfozyeFwtBz8VvT3OH9vG2OMMd2VSkikY489Nv6ebU3AdOWQRCKTubguj86USJtuumkkrBSXd7UYU66zXPCUXqZUbrXVVs3WjUo0k0h66hpT1viffv7BOcEEE8SrhBKfEUn67HA4HA6Ho2sGf2dPNNFE8fc2YYwxxnRXKiGR5pprrrTEEks0Wfb222+nPfbYI6aNkQ3MMh5usdZaa4WEWX311UNMkCXC39HUJFL9moEDB6bpppsuttt2223T/fffH8uZfrbjjjvGGJwpaXzecsstYzvqHOncyKx11103romYd9550wUXXBDrLrvssshMZp+bbrqptI8kEtfMFCiuafbZZ0+HHnpo6eEcREsS6fzzz0+LLLJI6tmzZ5p77rnTdtttF22Qb6OgHAVZW/ybZOqpp069e/eO85b7PhQpp834jzDabPPNN0+zzDJLTHlbfPHFY8rWySefnJZZZplYNuuss8a15Oe777770sorr5zmn3/+CGYyPPbYY6X1t9xyS1pyySXjGFz/QgstlB5//PEWr5N97rzzzvi+tC/9O88885TqOI3qNe+6666RsMPxOc7000+fJplkksguf/jhh0vbjayf8+A7cLxXX3212bqORjOJpIK1v/32WzTejTfeGEFxJuKGG25o8t7hcDgcDkfXDf2dTVx55ZVN/tI3xhhjuhOdLZGoIYT02GGHHZqtIxZYYIGSRFIggVZZZZUQEYgj5AP/6YNA0TbIG4573nnnNdn30ksvTWuuuWbpM7UPixKJY2+yySZN9jnmmGNKnxEWLUkk/q3w7rvvppdffjntv//+sYxXbVdOIl1xxRWxjKlTfFYtqNayX8iQKWb4lPs+BFJr2WWXTYMHDw4pNGjQoGhHhBXf5+67745rn3POOaNoOE+mZT8yq6aaaqq00UYbxTIyc5Ax7Md7xB6C6NRTTy2dC1F0zz33jPQ6aVNEnj7vvPPO8Z92r7zyyihfM4HIWnjhheP6uc477rgjpN5ss80W/cM2rfWzAmFFm9JPxXUdjWYS6ffffw+BRPBekS/T++I2DofD4XA4ulbkf2cTxhhjTHelsyWSBEpReihakkhkFOXLyDpZdNFFS5+ROGSfLL300k22W2ONNeIpafpcTrrMOOOMaaeddip9Rk5wPH0emUQqFtamWDgSRtlI5SQS3w8JguzQMp7iRvYL9aLy4+VRTs6U+z4EQobspnwZ2VtcX77s4IMPjv1VA4jj8DmXQkg7lpEowwNHeJ9nAr355pshl/S53HXSTvn0xTPPPDOOg+zRso5eM4FEQkDl25111lmxnYq3t9bPCuRSsc9GNZpJpCafjDHGGGOMMcaYsYDOlkgSEtRFKq4j2iqRmE6FOMiXMZUtFyA8ZZXpWHnGSjnpsvHGG8dUqr/+9a8hSvLtifZIJF3DE088EZ/LSSQk02KLLdZkP4mRfNpYMcrJmXLfhygnZMjEYRpZvqz4PSjPw+d8ah1Z2ixj2iDii+lkU0wxRWRcDRkypMnxiHLXWYyzzz47jslUNS3r6DUT5SQSWWtst9tuu8Xn1vpZQbYT++25557N1nU0LJGMMcYYY4wxxoz1dLZEYhoUA/Tjjjuu2TpiVCTSgw8+GMfWtDAkx/HHH99km3LShUwa6uowTYt1SIv8Me/tkUiIB5ZzLXwuJ5H4PpwL6aFgKhZTr8j0yY+XRzk5U+77EB0VMrQ9oiW/NuoScW1nnHFGbPPoo4/GdVD7iH05LtcxsutkKuIWW2yRVltttXhqPTWJKi2RXn/99dgOecTn1vpZIWmWZy2NalgiGWOMMcYYY4wZ6+lsiXTOOefEAP3II49sto4YFYlEUBCaaW1MdaJwMkWb8/UtSReCqWQXXnhh1CeiWLaWt0cikeXC8hdffDE+l5NISIzid2xLlJMzLX2fjgoZPW0+36aleO2112J/ts/rORWvkzagT8gIUvZPNTKRyAZju+K901I/K5j+yH777LNPs3UdDUskY4wxxhhjjDFjPZ0tka699toYoOfFp/MYVYmkmks8yatcJkk56XL55Zc32aZ///6xjer8tEciITzmm2++0udyEmm55ZYLgZHXRGpL8MSySkskTat74IEHmmynePbZZ9O9997bZBmFy8lW0ufidfKQEo7Jq5ZVQyKp36iNxOfW+rm4X7mi2x0NSyRjjDHGGGOMMWM9nS2ReGw606U23XTTZuuIUZVIZLqQgcQ5ytXrKSddevToEbJHn7feeuso3K3PbZVIJ554Ypw3LzpdTiKRBcMysnd4mhjLqEFEDR9tUy4oMI1Qeeutt0qPny/3fYiOChnqSE022WRRswmRRHuSucO1Ib2oN0Wxcj3x7L333ou6U6o7VO46Nc2Q6+EzdZ94Ol8lJRJT2Xr27Bn3E9fIstb6uXh86iYV13U0LJGMMcYYY4wxxoz1dLZEIqiHg3jIlz388MNpl112SVNOOWVk6ey+++4hG/r06RNihuweCjuzLcJk+umnj2lh5abFDRgwIB5LX1xOltLmm28egoAaRGRDIUl4nD2iguwl5NRaa61VKnBNTSUyh9gHeaInfSFTmLrGOp4gxuPke/funS655JLS+ZgWhShiX6TMYYcdVlpHJg6SgyeyTTvttJHJc8oppzS75jyYCsh35slu1BYis6b4fRA3tNl4440X3wl5hfzZb7/90kwzzRQFsanbxHS7QYMGxXVJaEnKUCcIecO2k08+ecgXjomMYRtkDXKG796rV6/I+MoLcRevkzbed999YxmCiswlFVin7W6//fZRvmYkEvfE6quvnpZffvk011xzpc0226yJNBpZP+dBDSWuvZihNCphiWSMMcYYY4wxZqynEhJJmT0tTZlyONobSKQVV1yx2fL2BhIOkdnSdMuOhiWSMcYYY4wxxpixnkpIJIKaOWSNFJc7HB2J4nS2jgYZU2RedWYWEmGJZIwxxhhjjDFmrKdSEonpTzwJjFo67S0w7XAUozMkElPlmJ6XT4HrrLBEMsYYY4wxxhgz1lMpiUR8+OGH6aSTTopCxsV1Dkdbg6lnU001VZpuuunSzjvvnB59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41XT1DiG2pjjsC39q6ev5cdXX0lMcT1sL8mEONp8883TXHPNFX0088wzp6WWWioNGDAgffnll6X7g304rqZFSlqpwDrbFSUjwfkQh8cde2zq2bNnmnHGGSOmnXbatOOOO8Z+o9IflkjGGGOMMcYYY8ZqKiWRFAzchwwZkk477bR08MEHp9122y1Ey0477ZR23nnndMABB0S2jgQFYuKxxx4LcbD77ruXtmVfslKee+650vQqZaZIQEnSKEuIZZJOZJogcxZYYIE03njjpXHHHTdtvPHGkZGE6JIYeuaZZ9LZZ5+ddthhhzgv75VVkwsYzsln3it76emnn05XXHFFWmONNdI000yTxhlnnJAVfMcXX3yxtK8Eko5XbLNKhASPxJGWaT3XTnZO37590y677BLtTtBfe+21V3yvF154oZRFhKQ79dRT0z777FPq00MOOSSde+650X+cg/Opb/J+0nnVrpI+ZAhxzCWXXDLEzqSTTpp69+6djj/++JIQUvYX5+G89NHf/va39OSTTzaRXPpe+fdFVpF5huxDVs0///xpsskmS+OPP37acsstS2Kto31iiWSMMcYYY4wxZqymUhKJ40jy3HfffWnfffeNTKCJJpooBA5Btg6ZJgMHDixljCB0mBJGltCss84awmfqqadOK6ywQoiDRx55JLJZOIfEhDJ7lOXCMokaHRdBxHGXXXbZkDscd6ONNgqJRBYR2yCw7r777rTddtuFWOAat91221KWC8dHYChDin1Yh3TgMzKJ4s3IDbJp2H+hhRZK++23X3r11Vdje7WLpFe1RBLnJDuI95JfeV8z5Q6BQ/vQ3uqjKaaYIs0777zpuOOOC9GkjC9kzB577BEiRtvRl4cddli64447YjtlGOXZQJxLGWV8b9qU7CFleHGvbLjhhmm22WYLicQxkUiSglw7/UXmEAKIfkQA3X777XEezqnsJLWr2lgZUzU1Nemoo45KK664YppkkklKx9A15RKqPWGJZIwxxhgzFtHwxQ/FRcYY0+2plERSRgcZJgiFJ554Igbq0003XZpggglCJs0333zp6KOPTvfff39J9Kig8jnnnJM22GCDNOGEE6ZVVlklnXjiiZFtgkBACnAOtlONHgmAPJNE7/WdyDJCHEgikYmEmGI6G8ekXg4ZS0gkSRTeS4AQOrbeS1Yo4wlZhDDr0aNH7M8r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LcvybL8lx6Ns27KCSKVSqVQqlUqlrU4c4J///OcNJEXe//KXv5w4yL/61a8mjnLa33DDDcNPf/rT9pr3N954Y9su7UvzUw8HelhgTH/yk59Mxrq3LPf6ox/9qL3/xS9+MWvOAhMs64FDaf0yVu6F3AOub+P84x//eNb177N1c0Efc2de+vnz+Yc//GFbdtlllw3vete7htNOO2245JJLZsEh2wbw9lAo96d92jcQNb4uXAP9vbsUmrnm+lkQ6fq/OWviCI+d46UyECggqIdFPlseOPTVr351Fkj6yle+0l6vvPLKBvm0s8x2y5cvn7QB/770pS9NzHx+/vOfb+az7S6//PJ2LNnefsfHWVY2lxVEKpVKpVKpVCptdQoo4pjGxpEVef+DH/ygOUdvf/vbh+OPP3448MADh8c//vHDfvvtNxx66KHDK17xiuEjH/nI8P3vf38CnJYyCmJ71cc+9rHhkEMOGZ7whCcMj33sY2fZ4x73uGbWmYMTTzxxOPfcc5ujCjL0MGoMOErrl7ECY6655pphampqOOOMM4bjjjtuOPjgg9vYP+lJTxqOPvro4eyzzx6+8IUvNLjaQzrbf/SjHx323nvvYZ999mk2nr8999yz2bHHHjtcfPHFc953AUq5L+3nM5/5zPDqV796eMYznjEccMABbf71/9SnPrXdh5deeunwne98px3/UoHDMUS69pTzJo7w2DneGixRQQE7YBHgY1lA09VXX93agkzWJSrpqquuanPwtre9bXjpS186PP3pTx/22muv4RGPeMTwyEc+cth///2Hk046aXjPe94zfO5zn2t9BFqNj6OsbF1WEKlUKpVKpVKptFUpzir1IKmHP145sFJtOLkvfOELh8MOO6w50IEaHKcHPOD/t3cmcFfPaf9/nmeesa/zGLswY4nKLoqUFjOy7yFlGSJKaJGQFgppoUKhlJIplRIhrXRLyb7MDBqyC+NvbKPb99/7quv4nt85d/c5932rc+4+79frep1zfts59+93fofvu+u6vvXD0UcfHdq3bx+ef/55y4bgWJIWuZMUPTxyDhER5557bthll13CRhttFH7/+9+HBg0apMQEkoIBbMOGDcORRx5pYm/s2LE24M2WHSNyA1mDWLjvvvtM8rRs2dKuA4+c9yZNmoTGjRubxLv77rtNPLi48/N+zz33hPXWWy/suuuu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;clipPath=inset(0.4% 57.33% 56.4% 0%);" parent="1" vertex="1"> + <mxGeometry x="122" y="82" width="279.7" height="118" as="geometry" /> + </mxCell> + <mxCell id="795Xv0Ka93fOG331V9Xn-20" value="" style="rounded=1;whiteSpace=wrap;html=1;arcSize=4;" parent="1" vertex="1"> + <mxGeometry x="621" y="79.5" width="284" height="151" as="geometry" /> + </mxCell> + <mxCell id="795Xv0Ka93fOG331V9Xn-2" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,iVBORw0KGgoAAAANSUhEUgAABJEAAAHoCAYAAAD5W34cAACAAElEQVR4XuydB5iV1bWGTTP2buyxRGNFNHYMEcUGoiiKgg0RFOzYqWIHLIiKPYiKEkWxoCioFCsR0RhbTJPYk1yvN7m5aQbcl3fBd7LPP2eQGc4MM+b7nmc95y9773//ex+G2e+stfZSybIsy7Isy7Isy7Isy7K+REsVL1iWZTVV/eMf/7DZbHU0y7Isy7Isy6qWDJEsy2o2YkH8y1/+0mazLaL99a9/Lf4zsizLsizLsqx6yxDJsqxmI0Mkm61uZohkWZZlWZZlVVOGSJZlNRsZItlsdTNDJMuyLMuyLKuaMkSyLKvZyBDJZqubGSJZlmVZlmVZ1ZQhkmVZzUaGSDZb3cwQybIsy7Isy6qmDJEsy2o2MkSy2epmhkiWZVmWZVlWNWWIZFlWs5Ehks1WNzNEsizLsizLsqopQyTLspqNDJFstrqZIZJlWZZlWZZVTRkiWZbVbGSIZLPVzQyRLMuyLMuyrGrKEMmyrGYjQySbrW5miGRZlmVZlmVVU4ZIlmU1Gxki2Wx1M0Mky7Isy7Isq5oyRLIsq9nIEMlmq5sZIlmWZVmWZVnVlCGSZVnNRg0FkV5//fX09ttv17huszWWvfnmm2HF64trhkiWZVmWZVlWNWWIZFlWs1FDQKRRo0alXXbZJb322mtxvvvuu6fvf//7DQaVZsyYkdZaa63UtWvXGvdqs2KdcePGpY4dO6allloqXXnllTXKyyZNmpROOOGEtOKKK6bWrVvXuF8ta+gx+0+wmTNnpl133TWNHTu2xr3FMUMky7Isy7Isq5oyRLIsq9mo2hBpwIABaeutt04vv/xy6RpA6Xvf+16DAZEXX3wxrbHGGqlz58417tVmleqMHz/+SyGSbOONN25QiNTQY/afYsBCYNzQoUNr3KuvGSJZlmVZlmVZ1ZQhkmVZzUbVhEgjR45M3/72t9O0adNq3GsOJoh01VVX1bhXtGpBJMKtttxyyxrXm5o1l35WsokTJ6ZvfetbacyYMTXu1ccMkSzLsizLsqxqyhDJsqxmo2pBpDfeeCM8e4444oga95qLCSJdffXVNe4VrVoQ6bLLLkurrLJKjetNzZpLP2uz9u3bpw033DD94he/qHGvrmaIZFmWZVmWZVVThkiWZTUbVQsi4b0DgCEfUn6d8DaAyze+8Y3StWuuuSatu+66Uf7kk09OW221VVpmmWXS6quvnvr16xdlpk+fnvbaa68os9lmm6W+ffuW6g8aNCi8Ylq2bBn5bo4//vjIUbTbbruVPfvyyy+P0LqddtopQppatWoV13/+859XrCOIdMghh0Sfll122bTaaqulww47rCw8D6sEkV566aXUqVOntNFGG8VzseJ45Na/f/+05pprxtjwLoSwcb3SmPXo0SOtsMIKAUJ69uwZz2DM+Bw+fHi6+eab0z777BOgZ+WVV069evUqexbw5Iwzzoh2W7RoEZ8aa4ywue7du0efd9hhh7TJJpuk3r17L7SfGDmlGFvGgs999903xoF7hAWut956MaZnnnlmPJd3oC36x3h36dIlvguMNfP9s5/9LOoOGzYsoORyyy2XjjzyyCiz9NJLp8033zzeNX+32uY5txEjRlT8ftbHDJEsy7Isy7KsasoQybKsZqNqQSRAC4t0ctAU7x111FFlQATr06dPlL/22mvTk08+mZ544omAE1//+tfT1KlTowyJuQEiQKRim9tss0168MEHS+eUyYHQfffdl772ta9F25wDSYrQp1hHEOmss85Kr776asAm4AOAA0CR1y1CpHfeeSdtt912AV8EnE4//fQAH0899VRZ3dwOPPDAih4+lcaM5wFWbrzxxvTII48EEFl77bWj3JAhQ9L9998fY9KmTZt4jwkTJpTqkgycvlCP87vvvrss/9M555yTvvvd78auepyTM4q+fVk/mTPGiuMXXnghffOb3wwYpftnn312POeiiy5KDzzwQPSROlwDhtEP+nnSSSfFtYEDB5bqduvWLa5Nnjw55o8wScaA933ssceizKLMM0YbembxXl3NEMmyLMuyLMuqpgyRLMtqNqoWRNp2221rQA9ZJSAiiPTTn/60dO2mm26Ka7feemvpGot+rt15552la4CS7bffvqy9IhC6+OKLA0gBQ3Qtf1alOrUl1j722GPjeg6tihAJjyjK4LWja88991xcwwMoby+32uBMpTHjeTw3v4YnF8/IPaUEiABgnBNqCAhr27ZtWV28mNi9jOMOHTqEFw8wTPfz8aqtn+xql59vsMEGaY899iidCyIBmHTtjjvuiGvk0NI14A/vm++wJ4iUt//MM89EObzFOF+UecbwcKKtSoCprmaIZFmWZVmWZVVThkiW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pTb79ttv0913350222yztMEGG6Sddtop7nmyiBCmhx56aNpoo41CDg0cODCkgn4j9AVZRv379499+/btm84555wQRtdcc0065ZRT0lZbbZVWWmmltMMOO6THH388ff3113EtOkYxM0r3BEHGCxlNyKPVV189ruHoo49OTzzxROm3pu9UnAZXabqqRMprGUko8TviPfIHGdivX7902mmnpRdffLE0yJdYQiLxmX6m7Q888MC05pprpkUWWSRtuOGG8Xt8+umnm53X4SgXlkjGGGOMMaZSjFaJpAGoptEMHTo0ps3wP/DHHntsDKLJhpl44oljEMZgS4Wf82NaIrWPltqN9//617/SnXfemQ477LC04oorpummmy6tv/76IfYYwIty+5tG8vbN2ygXSUgHxOiUU06ZVllllRA/CAUyhIgnn3wy7bXXXmmyySZLW2+9dbrxxhtLv5dPPvkkDR48OG288cZpoYUWCoH09ttvx3oKZr/66qshnshsWnTRRdOFF14Yx+Y6inIrD35/SBD6n/1322231KtXrzTjjDOmQw45JGSU9tc+lkiNoZpIKphNO5JhxHKmJSKCVl111ZCFNTU1sQ/bqNYR8fzzz8cUUoTRLrvsEr+/qaaaKq2wwgqRCWaJ5GhrWCIZY4wxxphKUTWJpKyFfKBJ1gt1jjTgZnB8/PHHx/Se5557LmohkZHBQAqJRIYEmUoamEs+mfZDu/F0tuKUJjJWTj/99HTUUUeFyGM62/LLL5+uuOKKGBAL9mffooSyVGpEwiZ/gqDah/udzBPaeeqpp46MIuQD/aFtmCp2wQUXxL1P+7Mtx2Lfzz77LF1++eVpm222CdFK3STkkfrzq6++iho6a6yxRlpwwQVDQCCW2JdtlIVUFEBcE78zppA+/PDDUQOJqYyIRKbG3X///U2+W7XEUU5XlUjIIGUV8TmXSkjxZZZZJi2xxBJp2223TY8++miTqWu1tbXxZx+y78gjj4xsJUQeGUlzzjlnyKSTTz45ss+K53U4yoUlkjHGGGOMqRRVkUiSRMpgECruy2CWoO4LUz/IRmKgzCsigzovyKU333yzySPoi1LKtA31h9qPoC8QDAx6yZZAbNTU1MR0q+WWWy716dMnxJ6knY6R92ee5dJdkWDRvV6uTVhOxhcFyxEH1DwiC4jtEDO6x5E5k046aUzpJDNIy9kW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Y8wYgyWSw9F6WCIZY4wxxphKYYlkjBljsERyOFoPSyRjjDHGGFMpLJFMh2loaCguMl2Iurq69L///S/997//jfedzejo/zFdIjGoLy5zODo7LJGMMcYYY0ylqJpEqq+vT3/88Ue8CgahfCZ4n38uLmMQXNx32LBhTZaZtkP70aZqY/qmKBqKkkD9ArQ9giLvAx2ruF93pHgv634WeVtqe6AP6Iv83qedWab91E+80v75cfP2ZxD51FNPpfvuuy999NFHZfslP4+uh+Pq3tA2nJ9zCbatlJwaGV1ZIjFg//DDD+OVtqfNeWUd7z/44IP07rvvxvt//vOfTYSS3ueDf46Vf9Z69uc963W+fF+d09F9wxLJGGOMMcZUiqpIJAahGhxrMK3BsOSQBqXff/99DIyee+659OCDD6Y77rgj3XLLLemee+6JATGDr59++im2t0TqGHn7v/POO+n+++9PN910U7r55pvTbbfdlm699dYmceedd6YHHnggPfPMM9E3//73v6OvJBbyPlT/dmfUBrmcURtpOZ//85//pB9//DEGey+++GJ6+OGHo63ph9tvvz09/vjj6b333ks//PBDiKT8OPDmm2+mG2+8MX4f6ive6/Npp52Wjj322HTmmWem1157rXRu9U8ui3Rs+hRJQV8jn/j96dj8Hl9++eX0+eefp6FDh8Y9oN9gftxK0lUlEoN1iR8+FyUSr0gk+pM/wySRcpH09ttvp2effTb+rLv22mvTJZdcki688MJ0wQUXxHvuCf4M5DiSR/n+uUAqrnN0r7BEMsYYY4wxlaIqEkkD6fwzg2JlsjD45PVf//pXeumll2LQtP3226eePXumaaedNk088cRprrnmSptuumm6+OKLQ3woW8O0n7w/BgwYkHr06JEmn3zyaOdJJpkkTTTRRKX3vNIH888/f9pqq63SueeeG4PjX3/9tcnx6A/1Z3eGe7KYcaflyhzSK3LojTfeSBdddFHaddddU+/evdMss8ySpphiijT11FOn1VdfPZ1xxhkxEGQfiSRxzDHHRF+1FBNOOGFaZJFF0vHHH59eeeWVJlKL90ggjim4buQQAmO77bZL88wzT5pqqqniPuAeWGqppVKfPn1CZnzyySel7ySZWPzOlaCrSqRiBhKSSEKJ5e+//36813Jtq/fs8/TTT6dLL7007bLLLmnFFVdMc845Z/wuib/85S9pyy23TGeddVZ64YUXIqOJY3388cclWZBnIClLqXidju4RlkjGGGOMMaZSjDaJlGcxAP/gJRtm5513jsHSnnvumQYNGpTOP//8dM4556Tddtstrb322mmVVVaJgRbZEL/99lvVp9OMDUja0X5klpx66qlpttlmi6B9aferrroqXXnllSHtkBUIvOWWWy6tv/76MZB96623SsfJM5Hy7JbuiESNMnNyUapg/XfffRfZXTvttFPaZJNNQtogjLi3kagHHHBA2mijjdIKK6yQ/va3v6VXX301joOwkfw54ogjQvLwuzjyyCOjv4grrrgijsMrmWX0MeeT9NH1qe/g999/j+04DkJr9913T6effnoIrssuuyzkIde06qqrpq233jp+l2RRcS25mKo0XV0i5cs0kCeri77ld0SbkhUm+VNbWxtC6LHHHksHH3xwWnPNNeM3uO+++8bv8KSTTor33AtIvG222SZdfvnl6fnnnw+JpKltOncuD4rX4+g+YYlkjDHGGGMqRdUkUj7A5LOyKggGxgy0GGSR/bDWWmvFIJXpHWQnEVdffXXaYostIiuCwSwZSwxiu3vmS0egL2hzpqXRD2RAkI204IILhqxjECLhgWhi2tR5552XlllmmRBN2267bRoyZEjpOBIREiTVykrpquSyiClreY0jLUcAIOOmm266yDo57rjjQib8/PPPMV3zySefTHvttVdkgm2++ebpuuuuK2UjcUzkDcKH/jjkkEPSE088Ufqd6fcloZf3R/5b1O+PQDKRgTT33HOn9dZbLw0cODDEiKatMc0UyYtMXGihhdIOO+wQg9RffvmlyXerNF1RIjFQZ4qZMop4pe00bY1pgfzZtdJKK4WA4886JBL7fvrppyGVmJbI+llnnTVtuOGGMX2NwT+/PfZHJi2wwAJp0UUXTQcddFB66KGHmgkjSSPOWbxGR/cKSyRjjDHGGFMpqiKRijDYVEYEA2wGzfxPPANp/rf9hBNOKGU5aBDMQIvlU045ZUgMarUwoHQmUvuh3fPsoZqampB38847b2TGMCCWbKB/mLpGf9DuM888c2TOUEdJx8rlhTORmhZ8V9vonldQG+eUU06JqUrULWLAh7BTphGC7+9//3tMSeM3QVZKMaOJ3wvShwwWpB5ySeeTcCJa6gv9ttiGwSa1k/h9HXbYYZH5xDUo+4lXprAxlY3sqHXWWSfq83z77bfNvnMl6aoSif6kD7/44otYJqmE0LnrrrtCECFhkW+PPvpoqa4R09yQStdff31kIJHtRxYgYpd1bMP0XUTS4osvHtMdyVaiRhXn03k4p6avSV6xvnitju4RlkjGGGOMMaZSVEUiadCbD6jzgTVTaRigMigdPHhwFJdVXRkNUBkgMSWEQS6ZGQy6qCnT0gDZtAztqQwu2pisF+qvkGHC1BkGIZrqJBmBSKJOFZkSZFUwFSuXUcV+7a7oPs9DbcI9rfuazB7kARk/3PdkIKktJeGY1oZEWmKJJWLKoUSNjtm/f/80++yzp0MPPTQykbQ+/22VE3p5v/HKNSEjmGqF1EIiMfDkd6nvw+tXX30VxbWRSGQrUWeJ79HSeSpBV5RIBIN1Bu1kIvFnFRlE1C4io4jsPvqJ306vXr1CJPE7I4OMaYKIuZqamsi+5DP3hWoe8ecix0WyL7nkkiFxmVKIRGK9ai1JGOi9BVL3DkskY4wxxhhTKaomkUYmHIrBoJYBrGQHEoNBriQSNZN4ghXZMdrHtB3JDIkGBAQSabHFFkt9+/aNwSnrlcnCwJ1B7V//+tcQTWS+kCmRi6a8X02jqClKHdqSdgU+s57sIe51ZRFpHdshFCiQzXQ3pr6pvXllm379+kVmyuGHHx79oX2LfZAvU59rOqk+M72KKYszzjhj1CNDEjKNVHJIoomaS0gMhCL78BvUsapBV5VIyvxRdhGZk8hZfisUTFehcwqmk/XH74gMs/322y+mEbIv7anpcHxGIH322WdxfKavIZHmmGOOtPHGG0d2E9vmBbslDiQPJJUc3S8skYwxxhhjTKWoikQCBqISSbl80GdC02a0nOwXBtjsx/Qapu/w5Kr9998/aiIx3UaZGabtqC8IBAASiaev8SSvvffeOwYh9APTqqiVw6PmERZkn1D4nAEyg/m8rpX6j34zjaJORaeFZI6kjLKSivcwbUm7k3006aSTRh0d6hFJHkkI0SdkplAjhz4U5aSRluW/t3wbahvde++9pSyjo446KqZRsZzr/Oabb9INN9wQIpHizhS7Z/qdfqM6VqXpyhIJqYMIYuCumkhkVZJtRu0rnrBG21KsnulpjzzySIgmCpoXpQ/T42h/RABZTbfcckvUQ0L0UguLfdkOiZRnQakeUvF4ju4VlkjGGGOMMaZSVFwiaeCqrAeJpHzwnAulfDmDcAaoDFQprM00EKaDkDHB1BrVe6nWAHZsQn2BTGAgSz0khAQ1WShwThYMcfLJJ8fUG54Ats8++0Q/kKFC20tGFPvPNNYbUraX2lq/AUISqQjrmNpG5gntPddcc6XTTjstnoZXFE5H9euXpp9++vhdkKWHaEJQEGS3IBrIHsp/Jy397rgWxAVT2hCFTFlEJHFuajOdeOKJadddd416PNROQuJyDGWsVavfu6pEyqWNahJJ6AwePDgyvKhfRV0xhF++n7KQNOjP6xzxHuF0/PHHp6WXXjrqkZEN9txzz5WynnjVMVxU20FYIhljjDHGmEpRFYkk4dBWJJ54JduIwRFPqlp++eXj0eN51oVpPxIKCmryME1m/PHHj6ffTTPNNCGUqOMywwwzRAYFWRBMqUJmSCIhDtrbt90RyTpCskXypgjtyf2OwNlggw1KBay1bZ5FREFu5MS6664bT01D8CAq6Df6iyLpV1xxRRSu1+8pD2VLqS/JOkJIDBgwIApB8+Q3JBVZNNwT8803Xzw5jCLeeiobSE7pcyXpihKJgToyhymfiDjJHH4rLEci8TtiyihZXDU1NbH8jTfeiPZm2hpSnFeOxXGYxvbll19GFhISj3sBkUsWEvtzbAQT5ytKJIkponitju4RlkjGGGOMMaZSVFwiQT7A1IBTg9p8m2ImEuuZ0kE2BINkMiQYQH399ddNMl+qMXgdW6H9aFPqtCCSGKyS6UAmDHVxmMJEFgQyg3UUXWY6GyKJdi+KEfdHIxI1eq92yZcV24nPPPL9zjvvDFmDBGIaE8tyCaX9yArjd7HLLrvEb4SMlbvvvjudffbZISvIKlMRdKSEfjPaP/+tEQw6Ke7M74xpa2SiUcD5nnvuCRlFfR/qIe24445xjxSnxBW/TyXoihIpn0qWTyHT09KuueaakH1k+5E1pkwkZRKxDwIo34djvf3223EvUKOKukoUUKcWHJKJc6qwNvsr80mZTFpfvFZH9whLJGOMMcYYUymqIpGEBtPFwSwwIFUNGZaTHcHAjGk5W221VRSgZSDLVB/VTlINnmoMXsdGaDfaD4lEBsvCCy9cqolEP9DGFE5m6hJZSAgExASSggFuLkegXL92RyRU8vbJ26T4nuDe//bbb9Mdd9wRsgBRg8QhG4XpnLrfdTxeqaWDzOGR8GQr8bRC6hQhIlhGNhF9yvREnhSWS6jiNfCUNWoi8eTD7bbbLp100kkhI8gE5LeIuOUpYkxpo8AzTxxDUrBex6gGXVUikUVEe9BmWqZX/gybaaaZIpOLfqXGmMQTEkjFsek3Bv0spwYc7U2he4QgfcJxXnzxxSbSqHg+jqHMJGcidd+wRDLGGGOMMZWiahKJQaYkQ7mMFZ5OxYCUdTB06NAYCO+xxx5p5ZVXjv+RZ1qOsh/Y31OpOk7eH9REIguJJ0ZRh4eBad6u2rZPnz7xNDBEEhkyRSQnin3bnci/P0E76p7Weok2bUuQ2cUT1mjjnj17hjCora0tbZNLJEIiNf+sJ7zpvPx26NfVV189hIR+Ozqm4HoQhUyPm3baadOBBx4Yj5lHXrGdrpdsmRtvvDEts8wy8cQ4stSQJ/pe1aArSiRCWUFMP+M9bSUpRCYSvxskEplIkkhsw29N2UTKYkIi3X///enoo4+Omlhkmj366KORgcQ2ZGeyn47PPnkGEvtbIHXvsEQyxhhjjDGVouISKR9IawCbh2C9BsbUB2GgxbQaMh+uv/76+AexBtF5FpIG0ab9qA9qampCNvTo0aOUiZQXTFYfnnDCCVFrhwHxBRdc0KRgc7F/uzN5G0jwkGlUTh7xniwg7neye8i4o20RBtQdyo/H9rS5jpXf+/pd6Bx8RkLQXwsuuGAaPHhwk37hvYp7czymL3JuHkHPlEWynBC5ElUcl2l1PFoeiYhIooA318n+1erzriqRNJ2NP6f0ygAe0cO0w7ywNtJWkodtJH4I2pPfI31HEW1+j5dffnlMIc0zjPLQtDU9zY1+UkZS8Tod3SMskYwxxhhjTKWoikSS8NHnPPLBNNswcKZmyHHHHRd1WZhWwzQfpukwoCX4H3wGW2Re6BjVGsSODdDOeXaMCmsvsMACUX+FQSl9xpPxJCto91NOOSUtscQSka3CI94lDyQZLPMaye9ryNsyv+8lQ5lqxtPVKJzM09HI7lFWHtswKKRP+EybM6Xziy++CGlA5gvb6nwKtqWWFVPPyDAjGya/Ph1LUorMF4TFlFNOGdPpyEziPMpe4pW6Smy3wgorxHGZbsf5+W7artJ0VYmk7KPa2tr4rCesEUhwspCQtEgkJBEDfGUSSSKxH+sopM30NaYWkpHGk9iUecR0NmpfMd1N55XAosg2y7h/LJG6d1giGWOMMcaYSlFxiQT54DKXDbzXNBwGobwyEOOx8osvvngpI4OBLhIJwUR2xKWXXhp1XqjTogG5aRu0F4N+QkgiMdDl6XcMPtQfalv2I1OFJ7UtssgiISXyfi2Kk+6OMnwkjdRWaideua+Zook4ou7XmWeeGfJGGXn8PhA5CFV+E6qNhEC67rrr0gEHHBDSj4FiLqgkiegvBNJGG20U9Y507mJmFMd8/vnn48lfk046aTwJEZGLnNJ1sy31mchYYirbUkstlc4777yYisX+/D45bqXpqhIpl0HIHE09488zCpuvv/760W7bb799tK2ylLQtr4ihyy67LLZjChvti0BiHdvzeskll8SxBg8eHE9oy7OYNIWO7VQzqXidju4RlkjGGGOMMaZSVEUigQa2eWjKFINQBrW1tbXxv/D77rtvZEU8++yzIY000CUjiUEVUz0YQDOY1sDYtB1NY5LMoBYPT2cjEwmJpJpIbIPEoIg20ohHyDM1CnHB9KtiZo2O151RW+geV3voHibUTp9//nk8bQvZQ/0iZB5T27Q9EgcpgGCizSX1+J0wlWzjjTeOaWXUKWIZ+7AN+5D9stZaa6Wll146ntzG4+T5jTFVlPpiTE3kyWsIB64TAUFmEVlm1CBjPVlGFFbnPuCVujxMdWM6G8We+X1yvZw3zzasJF1VImnAnj8tjT5hOU+323LLLdOyyy6b1ltvvZgSyHRB2u+mm24KycT2vKeQNu1L+zPtjWwzCSf2YTm/Vaa46Tys4zebZyUpC6p4nY7uEZZIxhhjTCP8+9fhcIx65FRFIkkgaaBJMJhGILGM9cgiBtFrrLFGPN584MCBISr4X3oFg1imVFEr6aCDDipJpO4uLjoCMoI+IJuLwetcc80Vg1MeCc+glywH5BEDWeQCj5JHWFCnBUHB4EQiKhdI3b0vdK/n7aHgfif0WyD7Z6eddorMEuRdTU1Nk/sdycB0JkQQ06DU3kwrIxNls802iylSh/btG0II4cB0J55iyHQoZb5QJPu7774LKYUYQlrNMMMMIa6YGsX18PvjPQKJKYtkLyGqHnvssajHwyu/PX6fyCum32m6m753NeiqEglxg8jhN4PIQRASLOP3RMF65BBtO2jQoPgNEbynLxnwM/2QKY3IJqbxDhkyJAQTUwg5Bttxv0w11VTRx0gqZT5JNrGM+0MFu4vX6egeYYlkjDHGNMLgt/j3pMPhaF+QiJBTcYmUC6S8UDMh+QBkQlCAluk3ZEMgNSgKTO0VBl4ET62ac845Y3B8xBFHxGDJWUgdg3ajP5gyw6PgJ5tssjTJJJNEAWCmEiKMeO3Vq1cMfpFHhx9+eEyjYuCqosu5MDGN6N7OxamWax0ZPEgEMrt4/Puss86aevfu3eR+X2yxxeL3QJ0iJJIEFCIFWXTqqadGvyAe+E2wD33G09gQrUyPe+SRRyKLiH3ps1deeSWmq0033XSRzYeY5ZrIYEJ6ILI4LtlPHBOBxdQ1ro3zIKB4Mh+SQtPr2F8ZVpWmK0skXhE3mkpGGxH0Fb+brbfeOqaDzjvvvNGW1J7iCZSIIoQRoha5N80000RWIPcCf+YtvPDCESzj9zn55JPHtDbVUVImkgpv++lsDkskY4wxphFLJIdj1KPqEgk0oNaAUwPp/P0333wTGRMMYA8/7LAQFgTTZxhs8RrLhwc1ZJgSwmPRLS/aj9qc/mAAO2DAgKiHE208vM2POuqo1K9fv/hMUI+Hwa4eTa4i5xyjnCRxn4zI9CrKFdqG9iKLh0ykY489NtoeKapXtTt9wTJeyUjSsahnRQYZUzuRE0wBJYuF7difLD6WI4z4XUneIooQr2Qtcd7bbrstxANwTfQrGUtcF/uTecTUUV3bWWedFdlKn3zySakGkkSiZGKl6coSqShuVNgasUStKzK7DjzwwMhK6t+/f4gg6iPRT2Sd8Wcf2WFMXWQbYtddd42n9vXp0yfW8YrIIztJU9ZUEwmRxPkklxzdNyyRjDHGmEYskRyOUY/RIpGKUkHyQSJJ9XckmYQGp4SW88ogWk+kMu2n2KaC9szlXmtSiG1V00piKj9GdyaXpqDX/N5nG8SOJJy2U1vm7/PPOSxH6OTzVDle/mQ91uXnAI7DufP9VPsoX6br1LmL941+u8XrqhRdVSIxYFdNIj11jexKFbz+9NNPS7WKkHASPSxjPctYp6e66bhMa+R4ym7KC2hrulptbW1ELpH8dLbuHZZIxhhjTCOWSA7HqEfVJRKDy2LR3XyQrM/FwSiv/OiRFFomaZELJ5YV5ZMZOWo3yYzictB6RVGI0J/qV17pK/Vp3rfdkWIb0Eb5VE5JoaLM4zVvS9ZJAOW/AckhlhFFCau+03b5tvk1KotIsJ2mzOXn03H1PfLsquLvttJ0VYlEIG9qa2ubFLrWYJ71eqWGEQJI089YpmlwCCJeVeeI4ynLCCEgWaVjs0zHkajSNDoX1u6+YYlkjDHGNGKJ5HCMeowWiaTBaj6Azt9DucGxhJHWc5ziYLw4EDdto9gvxVB7K9TOanveF+WC+rI794XaQ22gdpRo0Xq1ZXFftuUvO8k7tauOk4sh9UG+Pv9t5KFzF8+XH6v4GwWtK94TOmZ+DcXjV4KuLJEkgcplFClLiIE9wkgSSbWUyDhiHftre9ZLKim7SccoSiRea2sbnwanJ8QVr8/RfcISyRhjjGnEEsnhGPWoukQSGoTmYqiYxVAcwOawXzEriT8UOIbpOBIDuWhoSQhIIJRbZxqhbfL2VEaQ4L0yjVqCdUxHK05RUy0qwe+BZfmxir8fXYOWqY+FfpP5+VgmcVTcXrAsl0vF71kpuqpEUnaQPkskaTAv0cP7Tz75JOSQpBH7SSqxjzKQePokT0kkK6lYLJtjSRTp3BJP5a7H0b3CEskYY4xpxBLJ4Rj1GKlEamnQqIHiqKLj6FjFAa+2KZ4fitvmg1jTcfI+V1u21KaddR+M7eRtSXvl7ak2bKmNQfd2LmVYVhR4HKe4LD+3Po/sfFqfn694jJbQNq2dozNBIkmgdKXgD9f8s2oSlfssGZTvJwFEIJSUbcR7ZTG1dHytK7fM0T3DEskYY4xpxBLJ4Rj1KCuRNAjUQLAYRYFjjDGjg64qkRyOrhKIRElIPlsiGWOM6c5YIjkcox5lJVK5KTbIo7zeiTHGjG5++OGH0lQth8PRNPhLXplr+vzGG28Uf0bGGGNMt8ESyeEY9WgmkZRplBftLZeFVFzucDgc1Y6uWhPJ4egKQeZRXsTdmUjGGGO6O5ZIDseoRzOJlNcykUjSgE1IMuVCyeFwOKod33//fbPpOw6Ho2noL3zeOxPJGGNMd8YSyeEY9WgmkfIPuTzSoA00rS0XS8YYU22YzqaiwQ6Ho3wgj/SkPp72Z4wxxnRXqiGR+A+b4jKHo5rx5ptvNlvWmVFWIuXTRUT+WRKp3HQ3h8PhqFYwna04YHY4HCPio48+ir/s9bS+t956q/T3ujHGGNPdqKREYsr49ttvn0444YT4/OKLL6aZZ545lhW37ay45ppr0hRTTJH+/ve/N1vXUvTt2zdNM800aciQIfH5nHPOSUsttVQaZ5xx0tNPP91se8VVV12Vttlmm9ju8MMPb7a+M6Ij38fRPK6//vq0zjrrpJqammbrOiOaSSQGZoihP/74I/6X/5tvvmkWX3/9dfryyy/TZ599lr744ot473A4HNWO9957Lz333HMOh6NMPP/88+mll16K12eeeSY99dRT6ZFHHmnyl74xxhjTnaiUROLv2QUXXDCddtpppWUvvPBCmmGGGdLWW2/dbPvOiquvvjpNOumk6Ywzzmi2rqU46KCD0pRTTpkeeuih0rJ+/fq1KpEI/k1RSYnUke/jKB+33nprmmOOOdJdd93VbN2oRlmJRIbRd999l4466qi03nrrhcVae+21S7H++uunDTbYoNlyh8PhqGasuuqqaYUVVnA4HGVixRVXTCuttFK88nn55ZdPyy23XJO/9I0xxpjuRCUk0vvvv5969epV0YyjSockEjKsuC6PzpRIDzzwQHiF4vKuFmPKdZaLAQMGhMhEaBbXjUo0k0hkISGR+F9+JNH444+fxhtvvDTuuOPGDUNMOOGEaeKJJ451LHc4HI7REfozyeFwtBz8VvT3OH9vG2OMMd2VSkikY489Nv6ebU3AdOWQRCKTubguj86USJtuumkkrBSXd7UYU66zXPCUXqZUbrXVVs3WjUo0k0h66hpT1viffv7BOcEEE8SrhBKfEUn67HA4HA6Ho2sGf2dPNNFE8fc2YYwxxnRXKiGR5pprrrTEEks0Wfb222+nPfbYI6aNkQ3MMh5usdZaa4WEWX311UNMkCXC39HUJFL9moEDB6bpppsuttt2223T/fffH8uZfrbjjjvGGJwpaXzecsstYzvqHOncyKx11103romYd9550wUXXBDrLrvssshMZp+bbrqptI8kEtfMFCiuafbZZ0+HHnpo6eEcREsS6fzzz0+LLLJI6tmzZ5p77rnTdtttF22Qb6OgHAVZW/ybZOqpp069e/eO85b7PhQpp834jzDabPPNN0+zzDJLTHlbfPHFY8rWySefnJZZZplYNuuss8a15Oe777770sorr5zmn3/+CGYyPPbYY6X1t9xyS1pyySXjGFz/QgstlB5//PEWr5N97rzzzvi+tC/9O88885TqOI3qNe+6666RsMPxOc7000+fJplkksguf/jhh0vbjayf8+A7cLxXX3212bqORjOJpIK1v/32WzTejTfeGEFxJuKGG25o8t7hcDgcDkfXDf2dTVx55ZVN/tI3xhhjuhOdLZGoIYT02GGHHZqtIxZYYIGSRFIggVZZZZUQEYgj5AP/6YNA0TbIG4573nnnNdn30ksvTWuuuWbpM7UPixKJY2+yySZN9jnmmGNKnxEWLUkk/q3w7rvvppdffjntv//+sYxXbVdOIl1xxRWxjKlTfFYtqNayX8iQKWb4lPs+BFJr2WWXTYMHDw4pNGjQoGhHhBXf5+67745rn3POOaNoOE+mZT8yq6aaaqq00UYbxTIyc5Ax7Md7xB6C6NRTTy2dC1F0zz33jPQ6aVNEnj7vvPPO8Z92r7zyyihfM4HIWnjhheP6uc477rgjpN5ss80W/cM2rfWzAmFFm9JPxXUdjWYS6ffffw+BRPBekS/T++I2DofD4XA4ulbkf2cTxhhjTHelsyWSBEpReihakkhkFOXLyDpZdNFFS5+ROGSfLL300k22W2ONNeIpafpcTrrMOOOMaaeddip9Rk5wPH0emUQqFtamWDgSRtlI5SQS3w8JguzQMp7iRvYL9aLy4+VRTs6U+z4EQobspnwZ2VtcX77s4IMPjv1VA4jj8DmXQkg7lpEowwNHeJ9nAr355pshl/S53HXSTvn0xTPPPDOOg+zRso5eM4FEQkDl25111lmxnYq3t9bPCuRSsc9GNZpJpCafjDHGGGOMMcaYsYDOlkgSEtRFKq4j2iqRmE6FOMiXMZUtFyA8ZZXpWHnGSjnpsvHGG8dUqr/+9a8hSvLtifZIJF3DE088EZ/LSSQk02KLLdZkP4mRfNpYMcrJmXLfhygnZMjEYRpZvqz4PSjPw+d8ah1Z2ixj2iDii+lkU0wxRWRcDRkypMnxiHLXWYyzzz47jslUNS3r6DUT5SQSWWtst9tuu8Xn1vpZQbYT++25557N1nU0LJGMMcYYY4wxxoz1dLZEYhoUA/Tjjjuu2TpiVCTSgw8+GMfWtDAkx/HHH99km3LShUwa6uowTYt1SIv8Me/tkUiIB5ZzLXwuJ5H4PpwL6aFgKhZTr8j0yY+XRzk5U+77EB0VMrQ9oiW/NuoScW1nnHFGbPPoo4/GdVD7iH05LtcxsutkKuIWW2yRVltttXhqPTWJKi2RXn/99dgOecTn1vpZIWmWZy2NalgiGWOMMcYYY4wZ6+lsiXTOOefEAP3II49sto4YFYlEUBCaaW1MdaJwMkWb8/UtSReCqWQXXnhh1CeiWLaWt0cikeXC8hdffDE+l5NISIzid2xLlJMzLX2fjgoZPW0+36aleO2112J/ts/rORWvkzagT8gIUvZPNTKRyAZju+K901I/K5j+yH777LNPs3UdDUskY4wxxhhjjDFjPZ0tka699toYoOfFp/MYVYmkmks8yatcJkk56XL55Zc32aZ///6xjer8tEciITzmm2++0udyEmm55ZYLgZHXRGpL8MSySkskTat74IEHmmynePbZZ9O9997bZBmFy8lW0ufidfKQEo7Jq5ZVQyKp36iNxOfW+rm4X7mi2x0NSyRjjDHGGGOMMWM9nS2ReGw606U23XTTZuuIUZVIZLqQgcQ5ytXrKSddevToEbJHn7feeuso3K3PbZVIJ554Ypw3LzpdTiKRBcMysnd4mhjLqEFEDR9tUy4oMI1Qeeutt0qPny/3fYiOChnqSE022WRRswmRRHuSucO1Ib2oN0Wxcj3x7L333ou6U6o7VO46Nc2Q6+EzdZ94Ol8lJRJT2Xr27Bn3E9fIstb6uXh86iYV13U0LJGMMcYYY4wxxoz1dLZEIqiHg3jIlz388MNpl112SVNOOWVk6ey+++4hG/r06RNihuweCjuzLcJk+umnj2lh5abFDRgwIB5LX1xOltLmm28egoAaRGRDIUl4nD2iguwl5NRaa61VKnBNTSUyh9gHeaInfSFTmLrGOp4gxuPke/funS655JLS+ZgWhShiX6TMYYcdVlpHJg6SgyeyTTvttJHJc8oppzS75jyYCsh35slu1BYis6b4fRA3tNl4440X3wl5hfzZb7/90kwzzRQFsanbxHS7QYMGxXVJaEnKUCcIecO2k08+ecgXjomMYRtkDXKG796rV6/I+MoLcRevkzbed999YxmCiswlFVin7W6//fZRvmYkEvfE6quvnpZffvk011xzpc0226yJNBpZP+dBDSWuvZihNCphiWSMMcYYY4wxZqynEhJJmT0tTZlyONobSKQVV1yx2fL2BhIOkdnSdMuOhiWSMcYYY4wxxpixnkpIJIKaOWSNFJc7HB2J4nS2jgYZU2RedWYWEmGJZIwxxhhjjDFmrKdSEonpTzwJjFo67S0w7XAUozMkElPlmJ6XT4HrrLBEMsYYY4wxxhgz1lMpiUR8+OGH6aSTTopCxsV1Dkdbg6lnU001VZpuuunSzjvvnB59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41XT1DiG2pjjsC39q6ev5cdXX0lMcT1sL8mEONp8883TXHPNFX0088wzp6WWWioNGDAgffnll6X7g304rqZFSlqpwDrbFSUjwfkQh8cde2zq2bNnmnHGGSOmnXbatOOOO8Z+o9IflkjGGGOMMcYYY8ZqKiWRFAzchwwZkk477bR08MEHp9122y1Ey0477ZR23nnndMABB0S2jgQFYuKxxx4LcbD77ruXtmVfslKee+650vQqZaZIQEnSKEuIZZJOZJogcxZYYIE03njjpXHHHTdtvPHGkZGE6JIYeuaZZ9LZZ5+ddthhhzgv75VVkwsYzsln3it76emnn05XXHFFWmONNdI000yTxhlnnJAVfMcXX3yxtK8Eko5XbLNKhASPxJGWaT3XTnZO37590y677BLtTtBfe+21V3yvF154oZRFhKQ79dRT0z777FPq00MOOSSde+650X+cg/Opb/J+0nnVrpI+ZAhxzCWXXDLEzqSTTpp69+6djj/++JIQUvYX5+G89NHf/va39OSTTzaRXPpe+fdFVpF5huxDVs0///xpsskmS+OPP37acsstS2Kto31iiWSMMcYYY4wxZqymUhKJ40jy3HfffWnfffeNTKCJJpooBA5Btg6ZJgMHDixljCB0mBJGltCss84awmfqqadOK6ywQoiDRx55JLJZOIfEhDJ7lOXCMokaHRdBxHGXXXbZkDscd6ONNgqJRBYR2yCw7r777rTddtuFWOAat91221KWC8dHYChDin1Yh3TgMzKJ4s3IDbJp2H+hhRZK++23X3r11Vdje7WLpFe1RBLnJDuI95JfeV8z5Q6BQ/vQ3uqjKaaYIs0777zpuOOOC9GkjC9kzB577BEiRtvRl4cddli64447YjtlGOXZQJxLGWV8b9qU7CFleHGvbLjhhmm22WYLicQxkUiSglw7/UXmEAKIfkQA3X777XEezqnsJLWr2lgZUzU1Nemoo45KK664YppkkklKx9A15RKqPWGJZIwxxhgzFtHwxQ/FRcYY0+2plERSRgcZJgiFJ554Igbq0003XZpggglCJs0333zp6KOPTvfff39J9Kig8jnnnJM22GCDNOGEE6ZVVlklnXjiiZFtgkBACnAOtlONHgmAPJNE7/WdyDJCHEgikYmEmGI6G8ekXg4ZS0gkSRTeS4AQOrbeS1Yo4wlZhDDr0aNH7M8r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LcvybL8lx6Ns27KCSKVSqVQqlUqlrU4c4J///OcNJEXe//KXv5w4yL/61a8mjnLa33DDDcNPf/rT9pr3N954Y9su7UvzUw8HelhgTH/yk59Mxrq3LPf6ox/9qL3/xS9+MWvOAhMs64FDaf0yVu6F3AOub+P84x//eNb177N1c0Efc2de+vnz+Yc//GFbdtlllw3vete7htNOO2245JJLZsEh2wbw9lAo96d92jcQNb4uXAP9vbsUmrnm+lkQ6fq/OWviCI+d46UyECggqIdFPlseOPTVr351Fkj6yle+0l6vvPLKBvm0s8x2y5cvn7QB/770pS9NzHx+/vOfb+az7S6//PJ2LNnefsfHWVY2lxVEKpVKpVKpVCptdQoo4pjGxpEVef+DH/ygOUdvf/vbh+OPP3448MADh8c//vHDfvvtNxx66KHDK17xiuEjH/nI8P3vf38CnJYyCmJ71cc+9rHhkEMOGZ7whCcMj33sY2fZ4x73uGbWmYMTTzxxOPfcc5ujCjL0MGoMOErrl7ECY6655pphampqOOOMM4bjjjtuOPjgg9vYP+lJTxqOPvro4eyzzx6+8IUvNLjaQzrbf/SjHx323nvvYZ999mk2nr8999yz2bHHHjtcfPHFc953AUq5L+3nM5/5zPDqV796eMYznjEccMABbf71/9SnPrXdh5deeunwne98px3/UoHDMUS69pTzJo7w2DneGixRQQE7YBHgY1lA09VXX93agkzWJSrpqquuanPwtre9bXjpS186PP3pTx/22muv4RGPeMTwyEc+cth///2Hk046aXjPe94zfO5zn2t9BFqNj6OsbF1WEKlUKpVKpVKptFUpzir1IKmHP145sFJtOLkvfOELh8MOO6w50IEaHKcHPOD/t3cmcFfPaf9/nmeesa/zGLswY4nKLoqUFjOy7yFlGSJKaJGQFgppoUKhlJIplRIhrXRLyb7MDBqyC+NvbKPb99/7quv4nt85d/c5932rc+4+79frep1zfts59+93fofvu+u6vvXD0UcfHdq3bx+ef/55y4bgWJIWuZMUPTxyDhER5557bthll13CRhttFH7/+9+HBg0apMQEkoIBbMOGDcORRx5pYm/s2LE24M2WHSNyA1mDWLjvvvtM8rRs2dKuA4+c9yZNmoTGjRubxLv77rtNPLi48/N+zz33hPXWWy/suuuuoV69eimhdOqpp6YezzvvPNt/8eLFaRLJj8P9yD1IfP755yaI+vTpY/KWa819iEg6/vjjQ/Pmze2xU6dOluGE0F2TmUil40vCt30fDp9dN6ogeiIly9OS5WQ8R+64IOI52yN/kLEzZ84MCxcuNInEd4FtyD5asGBBGDZsmEk7zj/iqGnTphZHHHFE2G+//UwO8nv46KOPhpdffjmVkeQlcApFeSGJJIQQQgghCgoGlz7AjIVSLB5YT/nNxIkTQ+vWrcP6669vg+dbbrklLFmyxLId+Bd5BksHHHCAiQ4GzqyTvMgPhFFccsYjJVME2TDIgRo1atgglYHpt99+a7Ju2bJllu1AlszBBx8ctthiC8uEGDdunGWiSOZVjA8//NC+9/vss499rxF1nFNkAoJp/Pjxdk9wvpGpZKUgeVz6cC3JUtpss81M8rCeMja/phyDQDzFZWcujuLsQK4f+yAveK+6deva92HKlCl2D3IcsmYQR4cffrh9XgTXK6+8Yp9lTVJIs7N5VhESiNdxGZu/5jmSCYnn5Wlc63333ddk3LRp01Lb8Eg2JuWHiKOtttrKJDpZR5Qjzp071+QTgvAPf/hDqFmzZhg8eLAtj/snJT+nQpEtJJGEEEIIIURBEYuj+Ln3UvFl9G5hMM2/upMF06tXLxucIjEYADN4pcSNwe12220XunXrFp599lmVs+WJZ57E18TlwqeffmpZJjvuuKNJPErcfHvPUCED7MILL7RsJQTCXXfdlboGbKeeSPnB9xppVKtWLcsqISMJkcD3HpBJyITf/e53JnW6d+9uGXsuYQkk0iabbBLOOecck05IPb+v4u3i+8QFEstjiURWEULjoIMOMoHB56HPDvcn2/C5kCCDBg0y0YgEmTp1avjkk09Sx14TFJpE4hGB4yVrPCKVOFesYxm9j3hOWSL3Fhl9derUsXLFRx55JCWhOB4ir1+/fnY/IusQSJTxInIRULNmzQo333yzZZ4hfclimzx5sjKQFHmHJJIQQgghhChYYoHhGTE+sGXgO2/evHDbbbdZ6cbs2bNTMoJtGDSWlJRYTx4kEyKDTJnk4FisHpcLMX4OkUh/+tOfwvbbb2+ZD5Q0+fZcLy93QvAhkRjA3n777WnH8b46Ijc+/vhjEwpkG1E+hmgg48fhnD722GNh2223tYyTSy65JCxZsiR1DVlPVt6GG25oEmnChAmpHkUeng0YX3cXR+BCifX04RkzZkzYfffd7XgID+ShN1LneGQ6cS9S6rb33nvb9nzuNcHPJX+3krZCkkhxphHPKSmLJRLrfBnnE+nWt2/fsP/++4fddtvNMsjoeUR2EVlefB/4/aOU7fLLL7dyQvbhvTgmx0MmPfTQQ3afcr/Sz4x9PStKMkmRa0giCSGEEEKIgsWzj3h0ceEDWx4ZPNNYmxIfBqre+wUoqWLghESitIe+MfzrvcgPlwqOCyLPREIi7bTTTuGEE06wbAdfj0Sg1InrQ88qMl/IRKLPTkxSUInVw/3A7GfIG7J5kHAuTx36VXFN9tprL+sV5hKJYPs777wz/Pa3v7U+SkgksoW4Xp6RlA3el3DYjvdlQIm8oEyKckXKSLkX43uV0kZKp5C9Bx54oMncNZGJFDfV/uG0fuGjwZPTBsLJwfGaCN6XLCOeI4joS+QzpCGOPAMJmTRnzhwTbu3atQu1a9cOm2++ufWyohSR7Mqdd97ZAlFIVhGijsw/HpmRDUnl2Uzz58+3zMxmzZrZvvwukoXG+/H+RPKzKhTZQhJJCCGEEEIUFPHg0wVGLJB4HpfT+LJ4kMsyBrJIDRoEk5Vx3XXX2UDK9xO5EUukpNRDBCCRKGejlIn+K57FgphAXjBQReAxCL7ppptskAt+3XQt8sPPW3xfuNQDMm4od9tmm22sqTklTPQniu8bpM8GG2xgjei5PshXz/TzzDC/tzw8+yguP2Q5gohMGN6L7wLZUfTxoZyNfVzmdu/e3Rp4k0XDegTjr03pwGlpM7PRWDseCCcHx2sqEEY8IorIFPJZ1/hMBBlICCBEENl9zMDHPYQw2nrrra0skNeUtXXo0MHELMKJsrU4i4n38Ewkyt0oNUTkUs5GrzJ6VykDSZFvSCIJIYQQQoiCggFqMrMCYoHEQJesCR9I+6DXYRt6x9x///2W/UATYhoI86/ya3J68epAfH4RCH7+eE1pFeIAScfMbJRJMZBl4Eqj34cffth6ViEPmIKeGaXYPz6uRFJ+xGLHX3NOvVE1557eOEikVq1aWVkTYolz7YKInkiUF1L2hFBykeDlVNwnSNj4WrtI8vvO70ce2f6KK66wmRDpyUOmE1KDLBtKTocOHWo9s84666wwYMAAk49r4povP3NgmkRKDoSTg+M1FV4+5j2RfBY2P/9e5kaWEI/0chsxYoT1naIckMbaZHOxHduTReQyiuNzTK4JfyP3IcueeeYZE3yNGjWyWdporD1r1iy7X9nepZNCUV5IIgkhhBBCiIIjHqA6ngnhy3lEanhmUSyffMYoBq00H6b/BwKDjIvkcUX5xOfXzzHLkAHMGEV/HUpt6MFzyCGHWDArHk2UiSuvvNJkgs8S5vvrOuSP3wdxthDfa5dz9L1B2HHeyUJCUHiZGvtwz9Dc/H//939N/FGChkwiQ+Wwww6z2dWuueaaMGnSJJOE/j6exeT3D8spJ+V43G9kzSCvKJeiZA1x698BZufjPhw+fLjJ3bjs9NemdHxJWN7g+vCfw67NGAgnB8drKuIZ0WKJ5DO2uRBiPcsRQAhazucee+xh5W1kEbHOZRPSiOOwn2c4EUgiMsHIQkIgcZ0pcaSHUryNytkUuYYkkhBCCCGEKCh8YOziwgeb2TJXeO1SIhYczNJGCQgDJjJhGFhT0iNxUTGS18KXIZHIPKFHC6U2p556qgkjslIuvfRSy4RhRikaLvfv399EHhkuEF8vkTvxfeBCiQwjek+RmUKWCiKI60CZGeVkcekn+9AHiSbNlCDScJ5ST7an9JPGy2QUIaKmT59u9w34vebH8GxAjk2PplmzZtlxuN5k/9FzhybP3H98L7gXu3TpYhk0X3311Rq/D79+Y0nGQDg5OF5TEUukZPh6rqWLJCQSAg6JtOeee1oJGxLJj+GZRDzPJqLICKT0jRn9aMhOJhoZSv6ensmU/JwKRbaQRBJCCCGEEAVFLHp8oBwPOJPywbcnGNCSFcGsRYgLBsmU0iAufGa3pAwR5ePnzc+dh/dEYrYnHpEWLjaQF5Qz0XuFDJc//vGPNpMeWQ+QbNQs8ofzTFYPQgcJQIYRUo/yQcQDmV8ufeJ7hr5UXBeEE/10aEyPhEK+9uzZM9SvX9+aL9MQnT5i8f3Cc96TLCS/58iAuf766625Ot8DGth/9tln9p4ffPCB9WgiQwlxhVBiIOryd01RSLOzeSlb8jlZRV5WFoukOBOJZunIOMoUXRZ5Y2wXR95fyY/Tu3dv+y0kQ/CWW26xzCQkEtuTxeQCKvk5FYpsIYkkhBBCCCEKilgSubyIRVI2oeRygxmrKNugXIOZp5jCmkGUz2AliVQxOGecQ89oAZ5zvslcobF206ZNbVYwP78IIjJOGKh27tzZtmFbevD4MWOxIfKH+4IG5nzHybyjbAw5RLYPEsd7Gvk95NfPhRFlT0uWLDEhhBjienEsMojoc3XSSSfZjF4uYIFHz0LiuEuXLrVMF5o9I6/4HBzD13NsBAc9ePiOUOqGVKL86teCEjaC2dmcQpJIZUWcjUS4XKInEr9rnDsykcj080wkzzbynkq8RgrxmqbcSCMywyhZpB/VE088kTYbmwSSIt+QRBJCCCGEEAVFUi7EmRRJ+RNLJqabZ/DMgIkSnUGDBtkAKe6/4pkTyeOIsvHz77Oy+TnnNf1tKH1CEFGuhETyc+vXhddku9AviWngyaKIr6nID86dn2O+22T6UOrUtm1byzZB6JCBFJewxRIplkrxfREvGzhwoPXeIfOFvkreg8nvwfhYTFN/6623hl122SWccsopJi48A4rge0JJ3KxZs0xK7brrrnZMeij9GiCO4mbazNAGxSCRygr6iZGJ5I21KU0jE4l1SYnk2UtkkN1xxx2WmYZQJxuJjCbEYVJWKRT5hCSSEEIIIYQoKOJBcrwszqRIrmMwO3fuXMvCoLSKsimmGCcLgn0cjqHZ2fKD85ctE4XliDsGqZxzmvYikZxYNNCTiiyUrbbaypqcs4zr4A2fRe7E9wFlmiUlJda02kvYyEDy+8XvpVjYZZOx4PcRj5SDNmzY0OQgJW9+zbOVHyI42IbvAE26n3vuOctocihrJFtp8eLFtn6nnXay+5TP+mtQ2ml0tZNINMGmLLdu3bpWEkjvqWnTppkwyhaIvREjRlhPMu45spEoLaV0bcmSJalG3j67m4un5PsqFNlCEkkIIYQQQhQUPpj1mdd8YOvL46wKBrYMDimN6datm2UhMY01PV88e4JyHzJmRo8ebY2CyxpEi+z4eY+fE5xfsmAQGDvssIOVqpGFktyO5/TqIbOF5tsuJbg2hMgPzh3nHklK7yGkHOVnlDvRo4om116++fjjj9u5R/bxmn5hlEbRWJkeRt6fKr6/uCY0Qed6IS14Dn7NEX8upciEQmL16tXLri2ZRtxjfA6Xj3wWZnlDNp1++umWjda1a1f7HL8GSCRmY0Mg8egUs0RCCnFemU2Pnkhc78mTJ6dK1zwQQ8g6St3OPffccPLJJ1vm38SJE00isQ3CaNasWeGGG26w30SO77O8Jd9XocgWkkhCCCGEEKLgYIDqMz/FAsPFgw9Q2YaB1P333x/OOussmwmKgTEDRt+PATT/kt+mTZvUgFhUjFgMcR3IMKGRMhkrlLUhkWIJyHVg0NqxY0fLiGAQTIlNUjKJ/ECM0hi5R48edk4pF+Q8+33DeoQRTbIRCcgD1pG5NHbsWJuFjd46SARKz1weIaYYJCIpEIM0p6c8jvsNOcU6yqgoRaNEjSwj3pdSK45HXyRK2xAZZCMhkBBN7MdnPOaYY6wki++AC6xfg59L/h6WnzkwlYUExSyR+KycU5qT06CeDCP6SiGGyPxC5DHzIds+9thjoXv37nZf8ntIs3vW0QPJy9wQjpQ+Ity9CXcxnQ/F2g1JJCGEEEIIUXB4toWLIIizIDxzgqAPEr1bLrvsMpu6nIEt2zF4ZX8Gq5SCMCtU3759o3cR+eDSJ5Z6ZJgwGK1Ro0Zo0qSJlbNxfVwgIRvIECOj5f/+7/8sC2nOnDl2DARD3PBc5A4CBwGAJECOIgYQR8C5RCBRssR6zj29cgBJRGkhGXsbbrhhaNeuXZg5c2aakKVfEaWJZAzRJJtyJ59pj/dk1jYa13Pf8T4EpWk09aakrV69eiaMOBafBUlF1gxSg89CSRuzg3HMNUkxSyRED+efe43rgrAlm2zWrFl2jWiYjRjifuvXr1/Yb7/9QuvWrS0LDclHGRvfB64l1/+aa64xoce2HJvlRPJ9FYpsIYkkhBBCCCEKDs9USZbZuEBi0OtZEwx6t9hiCxNJZF20b98+dOjQwYIGtPyrPSVXBL2SvJ+MyA0//8nSQjIgKEuiYfbmm29uDZMpV+KcM3vUpZdeGs4//3wrcTrzzDNtOTNDMZ08+3tGmV9TkRt87xcsWGAiCFlA0DiZ7/uVK847gRwi26h27dqW+cNMbFw7eoQh8chgoucR9wvXiOtF9tEll1xi+1100UXWd4cMFrKX2I/Mp2uvvTast9569t5kwpBthKylnBSZwf70ZiKDCdHEcZG7yCxmB6MXEhKD7ECufVVBM21mY1sdxSyREHIIIuQPvcVq1aplEgiByDJmPCRDjD5JXIMtt9wy7LPPPiabuL5sxzXlt5D9yBhDFCLVfZa2YjofirUbkkhCCCGEEKKgcEkRv07KBrImyHCgjOOmm26yZrNIJMKfM3hmSmyeH3rooTY4fvDBB01AxRlOYvW48PHZ2XzZpEmTbEBK5omfbz/nft4PP/xwG7gyvTvZJwgJrqWLPD+2JFLuLFu2zEQQ4ojvNd93P988j4PlZ599tg38/BpS2oZsQCDQT4leVmzH9ogFpM+IESMs8wVh5fcfGS1cR7KJKE/kGEgk7kWykciOmjFjhh2XbCPK7DgmnxFZdeONN1rWE/dttgbdlYHSNeuBtOIRoZSNYpZI3ix7/PjxJuI4p1xvxDila/TG4v6i9BCBiGSqU6eOPVJmiFBCNiIVCa4hUs8zzfhOkKmUfF+FIltIIgkhhBBCiIIiLply4swVlw8MRBnE0jTbyzEIytf8OQNhBl88UrbhU4+L/OCc+XXx84cQYjBBqRTnl6wV+rb4+eY6kOXANggGRAPXEOnAvpSy+bFF7nAPIET4fpOdUtZ337//ZLGQSeTXkPP/xRdfWPYQ63w/gmvJcu4Trhclclwn9iXjiPJFri/beM8jzxBkW64rmWYck+145Jh8B+ifxeeu6kxAMpDi2diIbBSzROKz8vvF/UTpIo2yaZpOrzcyAv1ccw0R62T8UW7IdmSMIfwQfATLKS+kdxLi6b333rP3QFQl31ehyBaSSEIIIYQQoqBwYeThQslL2lxmZCtx8ywjF07xcXzfqhzArku4vEuGl7r5FPDxeSY888ivGdshKJASVZ2Rsq7AeYzPX3wf+DVJ3h9cA2QS+/g18euVvJ7xtSJc/LAszuTzZX6/+XX3/Xju65LrWV4VMBtbLJDiZtoxxSyRCD4vgfjzErR4ZjYXuiz3Hkhsi2BCELENy3mObOIRMaUMJEW+IYkkhBBCCCEKDh/A+oCXgSf4oDQpKggGyGRDsNylhu/nx4wH1SI3/PzGr10yxNcj3jZ5vVwixCKB6+UZMiJ3/PzG94HfK5CUNr7P929/GL6Z8WL4fsyc8FP/qaF0wKOhtOOosLzFwJXR4LqVIubw6yyWtxgQlq9Y/9NV94cf+z0Slv91flg+fn746dk3066Zv1/yXvPgs8UzLbI9EtEz0aoCspGWN7jeytnKopglEjII6YM8ciHky3m+ZMkSk0FknpGRxHMyNFnu+3lGGI8E6zy7yTOdku+rUGQLSSQhhBBCCFFwxKKCQWcy+8HD18fbxQPW+Hgsk0DKH89YSZ7vWBT5c5d3nmkSX8f4uhGxBNE1yR0/x5w3npORFEucNFn3/jKTRT+1GJBR8lWZQDiZeBowNZTO/1va9wKS19k/X1n3Z1VAL6Sy+iFBMUsklzyEf24EEsFzRBFiKM5KcinEctazbfI4Lqf8PZLvq1BkC0kkIYQQQghR0PhgOdugMxYU/joWTjHxIFfkTiwBXArF4ii5bVxWCNm29dfx8URu+Dl2QeNCyVi6LCz/FaRReWFSqeOolTOkJUROfP3jz14ZcpmNLUl1kkgukDw8u+jdVWVs7OPrXCDFx4kzmXydQpFrSCIJIYQQQgghRBFDH6BUOVq+UberxfLmfcLy1kNWxorntjy5bY5BmdzPJb8MNKsaStfsfVb83avLPoopZomkUBRSSCIJIYQQQgghRBGSszxCErUeEko7jg6l9860QPLkFFMWpcL2vXnySsmUfI8swWf7eUJ+GUPlkdFIe8XrXJBEUiiqJiSRhBBCCCGEEKJYoJRr4LQMYZMRdbumpFGGGKqKcKm04j3Kk0pVKZM8C8mDz5ILkkgKRdWEJJIQQgghhBBCFAHlySNkzq8mjcoLpFI5WUrIJP6GyuLZSPkcSxJJoaiakEQSQgghhBBCiEKGhtktBmZIGQ+ygazkLCl21las+Cyrk0n5yJ+y4H3yQRJJoaiakEQSQgghhBBCiAKFMrCkhClYeZQMZFLrIRmfm7ASt5LcRBCZR7k20C4LSSSFompCEkkIIYQQQgghCo3VZB+ZPEoKm0IOSt06pjfEdpFUXlZSXMJXOr7ifZUkkRSKqglJJCGEEEIIIYQoIBAvWWddo1n22up5VAWRTSS5TEKaJWGf5LYsqwiSSApF1YQkkhBCCCGEEEIUCGWVr1EWlpQyRRll9EvKVt7G63g2NsraKookkkJRNSGJJIQQQgghhBAFQFaBVOTZR1ljNeVtnIO0c0JZX4Prw/IzB6YtzxdJJIWiakISSQghhBBCCCHWMnHvn5RUad6nsBtnVzZW/G1IsgyRVFKxkrXVIYmkUFRNSCIJIYQQQgghxFoEaZJVICWlS3WMLCLpp1pXhp8Xvp08TZVCEkmhqJqQRBJCCCGEEEKItQQiJUMgVZf+R7lGtj5JNTtUqUiSRFIoqiYkkYQQQgghhBBibbB0WaZAWlcykJIxcnbGuSAjqaqQRFIoqiYkkYQQQgghhBBiLbC8xUAJpCiWtx0eftqtXdo5Ke04KnnaKoQkkkJRNSGJJIQQQgghhBBrmIxG2nW7ZkiVdTFK+z+akZHE8soiiaRQVE1IIgkhhBBCCCHEmiRLGVvpvTMzhMq6GqU3T047N8zYVlkkkRSKqglJJCGEEEIIIYRYgyTL2Eo7js4QKet6JBttk7lVGSSRFIqqCUkkIYQQQgghhFhDIEjSspBUxpY9pizKzEZauix5OnNGEkmhqJqQRBJCCCGEEEKINQQyJC3DRmVsZQYZWmkiqcXA5OnMGUkkhaJqQhJJCCGEEEIIIdYAzDSWJkVaD8kQJ4ooyEaq2zXtnLG8IkgiKRRVE5JIQgghhBBCCLEGSGYhIUkyxIkiLcjUqopsJEkkhaJqQhJJCCGEEEIIIX5lfp5QoiykCkbcZLuiM7VJIikUVROSSEIIIYQQQgjxK5MsZVMWUu5RevPk9HNXkn9JmySSQlE1IYkkhBBCCCGqBcuXL7dwfv7551BaWmqPonIkz2G288rreBnbcD3iZclt1iViCVKZGdlKS/6WiuSy+PXyZ98Ky+e/lbG9L09uG+9f1vslj1XWPhzf3zu5rkKRnKmtAiVthSSReG+Pt956yyJeznNfHq/3x3/84x8WbPvmm2/aI6+z7ePbxcdMfh6FIp+QRBJCCCGEENWC77//Pnz33XcmL4iffvop/Pjjj/YYs65KjIqSFD88T55XliGMXC7xPL4evg37JMXSukCylI3MmgxRkmMgZ3565s2UqCF+nPe6hQmiFfGfZ94I38951R5tm0go/Th35bYmj+av3Pa72a+k7R8LoOT7+XPfPymKeM0xOZ69/2oEVT6RUdK2dFnyNK+WQpJIb7/9toWLH0QQj7xmucuh119/3R59Pa95/Oc//xneffdd2+61116zxyVLlth2b7zxhoXvyzF5Tz8e63gefx7JJUU+IYkkhBBCCCGqBciJb775xgZYEyZMCIMHDw4lJSXhww8/NKGxLsqLqsJFEufwP//5Tyrry8PlEcGg9qqrrgodOnQIAwcOtMHuDz/8kHac+HlSUlVHqrKUzUXQZ1Pnh5fuHh+mXNs/3Numa+h/xiWh5zGtQt+T/xKGXdApTO9xR3h77HSTSS6GeEQCfTV9Yfj76MfCU72HhpFtrw39Trs43HjCeeHG48+z40zo3NeO/c2MF9Oyj1xYJSUSwXGRRiaZVrzPe3992j7b7JvvCW+MnJL2OVwuJf+21UWypK104LTkaV4thSSRVheejeRCifvnnXfeSWUtsfz999+3bRFCrPNsI377FixYEMaMGRP69OkT2rZtG4477rhw/PHHh1NOOSWcffbZ4YYbbgjjxo0LCxcutOP5sZOfQ6EoKySRhBBCCCFEUYPAIDPmvffeC3PmzAl33nmnDZYYPD300EP2P7xkxCA/PCtG5I9nd3EekT7+2oPlDNQnTZoUatasGXbeeWe7Bs8//7zJPZdFninmsS5IpLRSrEo21P5hzmvh40fmhSd7DQ3D/tLZxE/v484N3f98dujc6OTQ7pCjw+WHHhO6H312mHb9wLB0wiyTTkgbRM4Xjy0ILwwdl5JHNxzdMlz/p7NC18anhQ71jg0X1G4YujQ6Jdxz4dXhHw88Hr6b9UqaNPLsJj6LZyfFcmrJQ0+ZgPrrVTeFzg1PDneee6WJpH/PfKlSEimjpC3PBtuFJJE888czglwc+TqeI5AQPJ61xDruLQTQ3LlzwwsvvGASacmSJSaRyDJatGhRuO+++8LFF18cWrZsafKoYcOG4Ygjjgj16tULderUCc2aNQvt27cPEydOtGPwHv6+yc+pUGQLSSQhhBBCCFHUkOWybNmyMGLEiNCiRYuw7bbbho033jjUrl07jBo1yv4l30UTokPkj2chlSXhOLdffvlleOmll8KgQYPCnnvuGTbddNOw//77h3nz5oWvv/46TTZ5NlN1l0eAAEnLoKlEKRvx+bSS8MxtI8JF+zYOZ+92SLj6yFNNKP3zoRnhX08usuwixNLx2+xtYumpG++05UgeHp+/Y0zo36JtOGarPUOnI04KYzv0DO8++KSJqVeGT7RMpvNrHRFa1zwsTOs+yCRULI7iMLG0SiDxnOwmjteu7tHhhG1rhaM2/0PodWzrMKvvcBNY8X7JY+USGSVteVBIEsmzipBAvI7L2Pw1z5FML774ogkiMvxOPPHEULdu3dC1a9fw2GOPpbbhcfHixWHo0KHhpJNOCttvv739FpKNScYRcv3ee+81ub7XXnuFPfbYI/To0SM8/vjjqc+RLHFTKMoKSSQhhBBCCFHU8D+1Q4YMCcOGDbPyKUqpDjjgAMuGGTt2rP1LvQukuPG2yB3kEbIOCcRzygM5p473QHrkkUdCt27dwplnnhl23313CwavDIrj7CMXSJ7NVJacqg5UZT8k4pMpz4Snb7rbJM+Vhx0fpnS7zSQQGUOsR/qM79gnHLt1zXDJAc3CiIu72T6Inv/31OIws++w0OfEC8LJO+4TRrfrHv42elr4dubLJnk+njzPJBRZSaxn39fveyStDxLv4RlIXspG2duLd403YTW5a78wqeut4aYTzg+NN64RejQ/J8zsc7f1XUqVxa3KSEr+beVFacfRaecyHwpNIvGIwPGSNR6ROcgi1pEhxG8X2yBnn3766dC4cWPLJuI3jnstzmQi469fv36hefPmlgXYu3fvMGvWLFuPhGL/AQMGhMMPPzzssMMO4bLLLrOyX+5N77uU/JwKRbaQRBJCCCGEEEUN/wJ/9dVXh8mTJ1s5B5kvZ5xxRth7772tnI2BmHoiVY6kRKI8jXPq67wsDYnXpk0bk3rHHHNM2G233aw3EoNZSJausV91LzNMSqTK9EMiyERacPsYkzOUpH00aa4JGl+PoCkZNDqcuH3tcM4e9cJtp18SPnh4ti1HFrHuvjbXWAnbq/dMtH2sz9K81y1T6e0xj4dbT21jmUy3n90+LBoy7peyNS9ji7KPeP2vJxaFGTfeZX2Ynh88Nnw5/fkwvefg0GTTna1PE9KL9477J1WFRGJZrhSSRIozjXjuZWtJiUS8+uqrljF02223hQMPPNCyiM4555xw66232u8bJW7cX2Qb3XXXXdYH6YQTTrDfQ47jZXP0SmL7o48+Ouy4447h0ksvDQ8//LDK2RR5hySSEEIIIYQoar799ltrns0g8aOPPrLBFKUc++67r2Ui0WzWJYeoOLEAisURcgmhhAxiAHvaaafZwLhXr17hoIMOCkceeWS45557UllHyWyw6n5dqrKpNoHs+fqpF8L7E2aGT6c8az2SkkIGkXNajf1Dqz3rm0RCNCF+2JesIfZ7d9yT4ZunVzbO9mbYrKMJNplKlKMNPufysPjOv2Z8hqRE4jmfCQnFMSl/QyI13WyX0PPYVpaJhETyz1nRcrbSe2cWvUTifck84vnLL78cXnnlFcsUihtpI76RSQjxBx98MFxxxRVWGrrllluG9ddfP/zud7+zbCPKRol27dpZZtKzzz5rwW8gZXBe6saxZsyYEfr372/9kRBRPJ89e3Zq9jZJJEWuIYkkhBBCCCGKHhccX3zxhQ2ikEi1atUKI0eOtIFZdc50+bVJyiPvjeRSCHn02WefWckNWUdXXnll+Oqrr6xH1Z///GfLRkIoIfs862hdknoZEimLHMknvMG1l4SlysNWNapG4lCydtL2dazJ9gPtbrDsJdZ7byMXSp5d5I2ukUCUpdHHiP3JdHpz5NQM6RNnJaU+z6rwbCOykkwiHbNSIpEtFa9P/l25RIZEmlCSPN1lUigSiXBxQ5YR2Uc+6xqfieA3CwFE4+unnnoq3H777dbPqEaNGuH3v/99qF+/fjjrrLOsJO2SSy6x3kdkI3E8z2ziOAiq5557zgQTpW6nn366ZSnReHv69Omp7VXOpsgnJJGEEEIIIURR4711eKS5M2UblLPRj4cMGP6H10vZkuVUonw4d549hDSiF5I3yeY5556BBU19e/bsaT2Q/v3vf4dp06aF888/3wa9ZEqQJUbWksundUXsLW8x8BfxUbdrhhipSMQSxkrR5r5uUojX749/2mZGO2G7WiaDaMLtjbVdFqXk0yqhxDr2J0OJ0jMacpPFxOxuVgq3avvkexOsY3/PZnKZhESinM17ItFzyd8veYycIzFDW+nAacnTXSaFJJF8djbviYT0QeZ4OZuXuZGVxCNiHClLZh9lup07dw6PPvqobcf2RNwcm78NAfXEE0/YbG30KTv11FMtAwnpRAkcx2VGS7ZVY21FPiGJJIQQQgghqg1IpJKSEvsXd8o8HnjgAStnizNpEBgSSbmDQPJz5sIuzkbiOaUyxx57rPVt4fwjlxiY3nHHHZaJRBYFmRJkisVlbetCRhKziLn0WN56SKYYyTNc2riMIShpQySxnpnQbjnlonBerQbWOJuyNysli7bnOfuQHeTlcGxDjyTKz65pcrr1Q3rr/kdteeq9V+3nWU+EHzOWUrFE4nh8Jn+fSkmkkvSZ7hB0uVJoEolHzzpyieQzpcWzthHPPPOMCXEmDEAEIWWnTJmSyl7yJtwci2Mg0q+77jrrS0Yj7j/+8Y/2e3jYYYeF66+/3uSSvweldP5Zkp9TocgWkkhCCCGEEKLocRHhEsnL2UaPHm2DK3DhoQbb+RGXn7lEigUSpWtjxowJ++yzj2Uh0Z8KSYQwYhry/fbbLxx11FEmlFzoxceo7tciTXpUkURKZfxEWURkGyGM7j6/U+ja5LQw6Ox21oD73zNfSpWusb9LJJa5fGLdO2OfsFnVLjv4z9ZHiQymLx5bkNrP3juLREr7XB4r1j9+wx2hySa/SCRmj4u3qahIIpurOkmkZLDcy8vYjmVIpOHDh5tEQgZdfvnlJpF8n6SIIguJEjjK3cjKRCYxsxv9kPhtvOGGG6xMjr5JyCSO4SV2CkV5IYkkhBBCCCGKmmQ5GxKpZcuW1libUg4GWKyjHw9yQ1QMzqH3QPJzTkNtBhSDBg2ywe24cePC119/bcEMblyLunXrmmCitI0eLUlplHxd3UjLRGreJ0OKVCYQSEgdytQQSJSfdTripNCl0SnhpWETwlfTF6a2jbOFYoGD8CEj6YmeQ6yhdof6x4ZJV99ijbI5btq283/pqxR/DrbxUjk/5mPdbw9HbrxTqrE2vZo8C8klWPLvySXSytk6jkqe7jIpNInkIil+7s21fbmLpDgTaa+99gpdunQJU6dOTWUtkU3kJW3eX4nj8DeynP5HN910U2jQoEHYZpttLDsQyUTj7rgXU/JzKhTZQhJJCCGEEEIUPS44aPA8f/58K59CXNx///3WV8TXJ2cGE7nhoodz6H2NWEazbJr2XnDBBWHTTTcN9erVCyeffHI46aSTLMh+YCapLbbYIhx88MF2bTyjaV3h1+iJ5OECCIE0pdttoe1BR4U7z70yzL31PssiQjC5BMoqkFa8/viRedaIm8ylm044PzzZa6jN3EaGEmIoWTrnAih53HgZz5FIjTbaMZWJREaUb+OR/HtyiTSJVKQ9kcqKWObEcon7ht8yeiIhkTp16mQSyUWT9zSKM5l4znrELU3vn3766TBkyJDQsGFDE0nnnntuGDVqVEpUJT+LQlFWSCIJIYQQQohqAYLo888/t34gzFxEORuDJJdIXsq2LpRQVSWx9OH8eWNtziMZR2Q4nHjiiSaM6IuERDrllFPskdf0YWFWqZ122ska+jKYjxudV/frkTY7WxVIpFjAIHqYeY3SsQEtLg1XHX6CCaEvpz9v8ifeNpZILoMQTSWDRodbT2sT+p12cXiwQ6/w0aS5dlzfJtkwOymM4uPG610i9T7u3DDnlntS5Wzx9sm/rbyoLrOz5RtkIlEqeuCBB5pE6tixozWuT/4NXpLmZXA8JxOJ58ii559/3srbkLqUtg0YMCDjvRSK8kISSQghhBBCVBsYKNLnA4lEeVWciQQIC59mXuSG9y6KX3/33Xcmk5B2Z555pgWla/Q84howOxtZSvRHIlOJget2221njbfJjPBsJoLjVOcMMbJl0sTHlEUZciSfcLGDhKHk7I0Rj4TOjU4O1zZrEV648yGTSiZyVmUPJfe3Y8xf2dvoxbvGh+F/6RJa7n6ozejG7Gw2i1qi5xHHISspObtb8pis9x5LiC0k0o3Hnxfm9Rth7xcfK/keuUTpzZPXSYk0a9YsKxndf//9TY4zOxv9xuiDRNmah8sjlvO75yVtr776qskkllFWuskmm4TatWuHvn372j3r/ZSS76tQZAtJJCGEEEIIUfR4ptGyZcssEwmpwWBr7NixNkiKt6vumS9VTXJ2Ns9G+vjjjy1DgrK1iy++OHzyyScmjuJsL2QTAw4aAW+55ZbhwgsvtKnJ40yk6t7oHNGRVoJ178wMOZJPIGGQSJSHzR8wKvRv0TYMOuuyMOXa/iaQ6D3kjbQXDn4wTOs+yDKTPAMJgcM2H0+eF0Zc3M0kz7C/dA4vD3s4JZB4pMyN0rYXho77JRvJM5NWZRv5c/9crPc+SjY72yY7hxuObhlm3HiXHTPOVkpKqFwiKZHC0mXJ010mxSyREONII7L69t5775RE4m9ADpFlxDYPPfRQ6N+/f+jVq1eYPXu2rUcOsR6R9PLLL4dWrVqFrbbaysra2NZ7KEkiKXINSSQhhBBCCFHUuBhCRnz66ac2eDr99NOt7GPYsGH2P70uKSSR8sclkmcO+evFixdbZhEzP1199dWW4eUCKd6WBtvdu3cPG220kQ1c6cvimUhQ3a8F8qMqJRKBkHl7zOPh/rbXhUsP+lOY3LWf9TFCzpAJRJ8kYtSl14frjjozLJ0wKyVwEEz0UKLZ9Y0nnBduPbVNeGX4xJRoQgQtm/ZcWHznX23dhM59bR/K0RBLZC/xXt5zySUS4YKLz4C8arrZLtbkG8HF54mzqJJ/Uy7B7HZpEikPilki8Vm535o1axb22GOP0KZNm/Dwww+bFKI5NjL3iSeeCH369LHfvvr169tv38KFC1N9kyhlmzx5spWeUl7aunVry9T0/knFdD4UazckkYQQQgghRLUAGUF2DJkuxx9/vPXgueqqq6wUJJ5RjCyauDxLrB4/by6JfBlZD40aNbKB7S233GLL2MbLBWPh1Lt377D++uvbNbniiivCRx99ZFlK60ImEtkyaRKp4+gMOZJvIHnoX4TkueWUiyyL6NuZL9s6BA3Ch95GrL94/6ZhyUNP/ZI59OxbVl6GfKKZNj2UyEzyJtrInr+NetQadSOZJnW91ZZ/OHF2eLjzzaHFHw6y/kk07/b3jIPjf/n4gjChU5/QbLNd7f2RXWzLcbLN7pZrMLvduiiRiBdeeMGE7c4772z33eDBg61Z9ujRo8Pw4cNttjVk7VFHHRW23npryw584IEHLEMJ2TRlypTQrl07m+GNUrY77rjDSlDff/99ZSEp8gpJJCGEEEIIUdR88MEH1mSWf1VHVrRs2dL6IW2++ebh8MMPD23btrXsF/7lnn481V5aVDEugzyYAW/MmDHWd2rbbbcNu+66q2U/cH6XLFmSOr88IosY5B533HHhN7/5Tdh4443DIYccEq655hob2LKdR7UlIZEq21wbGfPmyKmh5zGtwoX7HBku2rdxuPnkC8Pd53cKw//S2YIZ2vqfcUk4v9YRtt4lEhlMH06aE8a07xGO22YvEzw9mp+zat8uFned1zH0PemCcPWRp1qvpYldbrGMo7fHTrfyN7KLuv/57PBU76Hhmxkvpo77z4dmhAW3j7Gso3vbdLV9G29cI5y8wz6hQ/1jw+jLrjcxVTJwlO2X/LtyiXQZNyp5pldLMUsksomQQddee21o2rRp2G233axpffv27UPPnj2t6Tb338iRI610lEyk5s2bW1kvWUuUkZJ5RMN77tsuXbqEGTNmWIkbx9cMbYp8QhJJCCGEEEIUNQyEKONgsMTAiRmM6IdE7xCmxG7SpIlJjm7duoXp06cndxfl4NlELoZo1ktGA/1ZkHU1a9a07AfEEANd8G0ZmF522WWhQYMGth1Rp04dk3tkUawrLG8xMF2AVKKk7avpC62BNiIHSXTOHvVCq5r1Q6s969vzOFjOdpSzkSGEgHpj5JQw8pJu1kw7bdsV+7eueZgFz/9Sp5EJpid6DrHMpncffNKyiy6o3TAMPudy68dkEmnFcXnkM427orf1WLr80GNsOz82z6+of1zoeWyrMPbyHlYKl/y7yotkP6R8mmpDsUskfucoR+vatWvYb7/97D7it43fNWY9RMpS1oZM79Spk5WtIWwp60U68VuIYKdBN9mZHJNgv9dff10SSZFzSCIJIYQQQoiihpnAKMngf2wZaNE75Lnnngvz58+3JtuIjTfeeMNmJqLxtsiPOFOIrCTON+UvnGfKYei1QoYXWUj0P4pL32i0zXWhFIdrwrb0aeH1l19+mSqVq9aZSCFLX6RKlLRRDvavJxdZydlr9062rKS37n/UHhFEPHq8ft8j4R8PPG7lat4Ym+cfPDzbSuBY7/txrPh4HJ8MJoQP+1Hm9tnU+bac/f/1xCIrTyPIVGKmOGZ3Y5+/jZ6W9jnYh0ymv49+zNb7TG35REYpWx5NtaGYJZLHokWLTAAx4yHiaOrUqWHOnDmWSURGJr9/3Gf0hUM4TZgwwcrYJk6caK+ffPJJ+01EGvGbGDfVLsbzoVg7IYkkhBBCCCGqBV52BWTO0PvIG0JDtS+b+pVw0ePlbMnG2fE59awlP++s4zoQvq1Lpvi6VHuquKSNEjJEDA2v7TWCaNWMZ/EMaN7I2mdRi2dQY1/vkeTL/XVyH97Dt7GZ31YJKf8MfozU+0fHivsfsa3NAFeBnkjpEi6/UjYoZomE5CEDEFmE/PFlBK95RJJ7dpEv9wyjOMvI9+NYvOa4xXQuFGs/JJGEEEIIIUS1wJs6eymVl2CJyoHscSkXiyCXQDFsw8xrft49G8lnY/Nrsy42N0d8pImQSpS0uahxyYOcQQyxLimB4v147Q202Y/nRCyKWMfsasge3y4lkFYspyTO9yP7iO2yfT4/jgum5Db5RGVL2aDYJRKSiOfIH4LMP+K1114LL730kpWlIYuQQr6Ov5EsQZ+BLc46igPh5FJJoSgvJJGEEEIIIUTRkxQbyawjniNCPFNJ5I6fSz+/8WuXSvHr+BrEy/waeKmbX5/ktaquIENiEcJ09UlZkkuksoFWzbaGqHHZ4+uTWUQeJoNWZSjZLGmrMoriGdPibfy5r/f3dLHkx7D3Tbxf6jirIhZVyW3LCzK34nNXEYpZIiGH4ubXfHZek2kUCyJ/Hc+25qLIs5k4BtLIM5pYlnw/hWJ1IYkkhBBCCCGqjLUhA1xClPXevk4SqfLE5zqbRIqvQXKZX4O41C25TXUnrcF23a4VykZy6ZOW7RNlHLkYctHjy/21SZxIHMWSKPledrxy1vuxyxJDsUSK3391x0s7diILqSKlbHy/kEhJcZTMyEmuL5RwYYQA8s/Ja7KQWP/OO+9YxHLIpROSyLOPeExKJPVDUuQT/j1yJJGEEEIIIUSlyCYEYvGgUKzLUTq+JD0bqflNaXJFkRnx+TKJtGJZ8ryWF4hLGrl7/x/P7OG5SxbP1JFQUSjKDmSlJJIQQgghhKg0lCh53xvCs368tEkIEazBdlo2ElLk5skZ2TeKlUHJX1VkIblE8jKvuBTMhVKyXEyhUGSGC1dHEkkIIYQQQuQNoohGyd9//70kkhDlgBxJy66p5Ext1TVK752ZkYVUUfgtSkokbyYdSyRvLp0cOCsUipXh94cjiSSEEEIIIfLGhZGV60S9boQQ2UnO1FbRJtvVOZY375N2jioyI5vD7xI9kbwUxwfDPGdZ3DcoWb6jUCh+CTL4eHQkkYQQQgghRN545hElbXHmEWJJjayFyMLSZRlZNmTeJEXKuhqlHUenS7YWA5NnMC/iTCREUbaeSHGmhUKhyB7e3N2RRBJCCCGEEHlD1pH3RPIsJGQSy5BLQohMyKxJE0mUtU1ZlCFU1rXIVsbG8opSVk8kn53MxZH3Q1IoFGUH94t6IgkhhBBCiEqDNPKSNh7pkeSvhRDZSTbZXtf7I2UTSKUDpyVPW97wO/T111+nytl8mnsXR2qsrVDkFn6fOJJIQgghhBCiQsR9kLy8TQJJiHJgtrYG10kkEVMWZQikypaxudTm94ieSO+++66VrzEYjoVRMgspOXBWKBQrw+8VRxJJCCGEEEJUCAZoS5cuTcUHH3yQ9lqhUGSPjxa+liFP/n3GbeHTKc+uM/H5yCfD9816pJ2DH+pdk3Gu8o333nvPxBEZSK+99lqYP39+ePbZZ8MzzzwT5syZE+bNm2cxd+5ce2Q5z1mnUCgyg3uEe8mRRBJCCCGEEHnDv/YPHTo0HHnkkRZNmjQJzZo1C40bN04tUygUZUeHesdkiKTPdmuzYvmx1T561D0x42//YPeLQosGR2Wcp4oEv0NNmzYNjRo1CoceemgqDjnkkDKfKxSK7FGvXr0wbty41H//JZGEEEIIIUTeIJGuvPLK8N///d/hv/7rv8L//M//hN/85jep1wqFovxotUnNTJlS47xwxsa7h4Yb7FAto/1m+2b8zQTrkuenIsFvEL9H6623Xvjtb3+bWlbWb1NZyxUKxcrgHrnrrrtS//2XRBJCCCGEEHlDD6QuXbqEDTfcMKy//voKhaKC0WOrehlC5YOdzw8jt2kWmm62S7UK/qbk3/pOjVah6aa7ZJyXysbGG28cNtpoI3vO7xSxwQYbpMK3i58rFIrsMWzYsNR//yWRhBBCCCFE3vzwww/WE+nTTz9VKBSVjH/d92SGXCF+OKpn+NcDT4cvH19Q1MHf8ONBXTL+vh/rd1ux/vmM81EV8dlnn2UsUygUFYsvvvgi9d9/SSQhhBBCCCGEWNtkm7WNqNs1lHYcnTmzWZEEnz3jb9q18rOwCSHWDpJIQgghhBBCCFEILF0WSgdOyxAuJl1aDwml987MkDQFG1MWheXN+2T8HcTPE0qSf7kQokiQRBJCCCGEEEKIAgIJkzUrqQhkEp+N7Knk57bPvuJvQpQJIYoXSSQhhBBCCCGEKDRWk5VkQZlbAckkK1srQx4R/C1CiOJHEkkIIYQQQgghChTkS1lZSSmZdPPktSOUpiwqs+eRB5+dbYUQ1QNJJCGEEEIIIYQoZJYusz5CNKNOSpqkULJyt5snZwqfqohV0qg8cSR5JET1RRJJCCGEEEIIIYqEnGTSKqHkM7t5ppJlK01ZlCmHkoEsWrW97VtOqVocpR1Hqe+RENUYSSQhhBBCCCGEKDaWLstNJpUVqyQTM6jZLGo5SqKywnoeSR4JUe2RRBJCCCGEEEKIYmVVqRsZQJWSSnkG5WqII5WsCbFuIYkkhBBCCCGEENWFSColxU9lwqWRZlkTYt1GEkkIIYQQQgghqiOUlyGV6HM0oWSlXEIEdRyVylxCDlmseG7LV4kizzJSppEQIkYSSQghhBBCCCGEEEKUiySSEEIIIYQQQgghhCiX/w+8zBe6WGG5MAAAAABJRU5ErkJggg==;clipPath=inset(42% 0.33% 0% 56.33%);" parent="1" vertex="1"> + <mxGeometry x="623.13" y="82.5" width="279.73" height="156" as="geometry" /> + </mxCell> </root> </mxGraphModel> </diagram> diff --git a/.docs/images/data-versioning.png b/.docs/images/data-versioning.png new file mode 100644 index 0000000000000000000000000000000000000000..01fe62af37e22534cca302ae9d184b215b31692b GIT binary patch literal 45988 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 literal 0 HcmV?d00001 diff --git a/.docs/images/screenshots/dashboard-managed.png b/.docs/images/screenshots/dashboard-managed.png new file mode 100644 index 0000000000000000000000000000000000000000..d5a0086672021d5b85c47f1d31f9952f38943b9d GIT binary patch literal 115429 zcmeAS@N?(olHy`uVBq!ia0y~yU}a!nU{>H@VqjqS{3~J&0|NtNage(c<IR&g^$ZLQ zoCO|{#S9GG!XV7ZFl&wk1LL7CPZ!6KiaBrYvPJ~|mOuV+qSmFZmMIH56jns6SfR14 zBG>h3Uv@%y%=+s)Zrr_l_ikrHQj<cLN3=<h*Wdkbp5LwSGc=QMe)zenrs7!SoXwjL zm))B;V@_PCFdqXLIAp4~Gq8b~4VxGkdB7}&R3;_~2<sFJiva@z!wHY0U8|y`W_|j^ zrE06lpx}G+X5`0CPEE~|ATFyj12Y3dLyv@%MBR@Min_X6m#DKaEb;X8JbB}W$|vU( zPk#=Fg8~N_7#I|kkF}{eI_7&-X)!qb%DS>bQcg1LQZQqH0mL2-CW!@GoEQ$jcd}x9 zleX%_$%i>Sr*(cgGcqtZWVSM}X{@cg%&;!*?xVZAx2xKUDzr2<)=fUvyJqd$o?f1- zSFdJz1YNrRp@XCTKf`+We*2mq5ii`QIWg>>skL*a#-&!@#F^4g#$7)$7#J7=q7)k# zy|h^jJh+$Uzn^D2%i3h=>7t?{OH0cfi`ZrJ--P$K&pYlvPcMc|+_Yi!wCTIA?y%V{ zGj-l(L!HNGmg|_!`Dg2QLhn>FGstaCAh!t|P!P?X6V)qa=o1$g_vLKSj&1Mn)PBAu z>*=l-$q;;b)BKQaUpDWar*!+9c7xZ9yG0jH=Vv4^Ffb$t9AH=~$|TXXF8%wuzcIf) z@K5~Bum1h^woR4M&6RyJwso)0Sau#$a%2d8y=$h{MT^Wo6JJ`kJ$-s3)$PU8oB8`T z^Bw|47)L_GrByj>8`^fcy}eZ`BrGg6Sx8x_ZvXOlg>Njb_uJ;#*_O{@c9jX2ULLmC zz4w8<lD_`>HEY%^T=?<6;Q`Oi&Q3{5$;e21)@Rq=TC3jT({W_jeLdveI`t>BUz@k3 z+WDR6@;aX=T_>HXWpZgk`gWVomf2+w%0Dg#B_S_EL*^Zo#qNIZx~8lB{qnh5P)siB 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%0Ds3pd}0c`|p- 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 Yx9@(~c<brz-=Jk8p00i_>zopr0K5R1LI3~& literal 0 HcmV?d00001 diff --git a/.docs/index.md b/.docs/index.md index 6ea36fd462..6b4674bf5d 100644 --- a/.docs/index.md +++ b/.docs/index.md @@ -16,16 +16,16 @@ author: Martin Weise Documentation for version: [v1.7.3](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases). -DBRepo is a repository for data in databases that are used from the beginning until the end of a research -project supporting data evolution, -citation and -versioning. It implements the query store of the -[RDA WGDC](https://doi.org/10.1162/99608f92.be565013) on precisely identifying arbitrary subsets of data. +DBRepo is a repository for data in databases that cover the entire data life cycle supporting data evolution, -citation +and -versioning. It implements the query store of the [RDA WGDC](https://doi.org/10.1162/99608f92.be565013) on precisely +identifying arbitrary subsets of data. ## Why use DBRepo? -* **Built-in search** makes your dataset searchable without extra effort: most metadata is generated - automatically for data in your databases. +* **Built-in search** makes your dataset searchable without extra effort: metadata is generated automatically for data + in your databases. * **Citable datasets** adopting the recommendations of the RDA-WGDC, arbitrary subsets can be precisely, persistently - identified using system-versioned tables of MariaDB and the DataCite schema for minting DOIs. + identified using [data versioning](concepts/data-versioning) of MariaDB and the DataCite schema for minting DOIs. * **Powerful API for Data Scientists** with our strongly typed Python Library, Data Scientists can import, export and work with data from Jupyter Notebook or Python script, optionally using Pandas DataFrames. * **Cloud Native** our lightweight Helm chart allows for installations on any cloud provider or private-cloud setting diff --git a/.docs/kubernetes.md b/.docs/kubernetes.md index 0881fe7ca3..d551be901d 100644 --- a/.docs/kubernetes.md +++ b/.docs/kubernetes.md @@ -14,7 +14,7 @@ helm upgrade --install dbrepo \ -n dbrepo \ "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" \ --values ./values.yaml \ - --version "1.7.3" \ + --version "1.8.0" \ --create-namespace \ --cleanup-on-fail ``` diff --git a/.gitignore b/.gitignore index c7f9e18556..7aac91c7e1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ target/ !**/src/main/**/target/ !**/src/test/**/target/ +# TODO +.docker/ # generated ready schema.xsd diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 92270eee73..819ca4288e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,18 +2,18 @@ variables: BUILD_VERSION: "" HOSTALIASES: "./hosts" DOCKER_HOST: "unix:///var/run/dind/docker.sock" + TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: "/var/run/dind/docker.sock" DOCKER_VERSION: "27" - TESTCONTAINERS_RYUK_DISABLED: "false" ALPINE_VERSION: "3.21" PYTHON_VERSION: "3.11" JAVA_VERSION: "17" NODE_VERSION: "18" SONARQUBE_VERSION: "10.0" BUN_VERSION: "1.1.40" - DOC_VERSION: "1.7" - APP_VERSION: "1.7.3" - CHART_VERSION: "1.7.3" - SUPPORTED_VERSIONS: "[\"1.7.0\",\"1.7.1\",\"1.7.2\",\"1.7.3\"]" + DOC_VERSION: "1.8" + APP_VERSION: "1.8.0" + CHART_VERSION: "1.8.0" + SUPPORTED_VERSIONS: "[\"1.7.0\",\"1.7.1\",\"1.7.2\",\"1.8.0\"]" CACHE_FALLBACK_KEY: "${CI_DEFAULT_BRANCH}" # This will supress any download for dependencies and plugins or upload messages which would clutter the console log. # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work. @@ -79,8 +79,8 @@ lint-docker-compose: - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-search-service-init'" - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-storage-service'" - "IGNORE_VOLUMES=1 IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-storage-service-init'" + - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-dashboard-service-init'" - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-ui'" - - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-upload-service'" lint-helm-chart: image: docker.io/alpine:${ALPINE_VERSION} @@ -149,19 +149,20 @@ build-metadata-service: only: - merge_requests - master + needs: + - build-java-lib + dependencies: + - build-java-lib script: - - "mvn -f ./dbrepo-metadata-service/pom.xml clean install $MAVEN_OPTS -DskipTests" + - "mvn -f ./dbrepo-metadata-service/pom.xml clean package $MAVEN_OPTS -DskipTests" # Compiled classes are needed for SonarQube in later stages artifacts: when: always paths: - - ./dbrepo-metadata-service/test/target/classes - - ./dbrepo-metadata-service/services/target/classes + - ./dbrepo-metadata-service/oai/target/classes - ./dbrepo-metadata-service/repositories/target/classes - ./dbrepo-metadata-service/rest-service/target/classes - - ./dbrepo-metadata-service/api/target/classes - - ./dbrepo-metadata-service/oai/target/classes - - ./dbrepo-metadata-service/entities/target/classes + - ./dbrepo-metadata-service/services/target/classes expire_in: 1 days build-analyse-service: @@ -176,7 +177,7 @@ build-analyse-service: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" -build-lib: +build-python-lib: image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} stage: build only: @@ -188,6 +189,19 @@ build-lib: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" +build-java-lib: + image: maven:3-openjdk-${JAVA_VERSION} + stage: build + only: + - merge_requests + - master + script: + - "mvn -f ./lib/java/dbrepo-core/pom.xml clean install $MAVEN_OPTS -DskipTests" + artifacts: + when: always + paths: + - ./lib/java/dbrepo-core/target/classes + build-data-service: image: maven:3-openjdk-${JAVA_VERSION} stage: build @@ -195,11 +209,9 @@ build-data-service: - merge_requests - master needs: - - build-metadata-service + - build-java-lib dependencies: - - build-metadata-service - before_script: - - "mvn -f ./dbrepo-metadata-service/pom.xml clean install $MAVEN_OPTS -DskipTests" + - build-java-lib script: - "mvn -f ./dbrepo-data-service/pom.xml clean package $MAVEN_OPTS -DskipTests" # Compiled classes are needed for SonarQube in later stages @@ -231,6 +243,17 @@ build-search-service: script: - "cd dbrepo-search-service && pipenv install --system --deploy" +build-dashboard-service: + image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} + stage: build + only: + - merge_requests + - master + before_script: + - "pip install pipenv" + script: + - "cd dbrepo-dashboard-service && pipenv install --system --deploy" + build-images: image: docker.io/docker:${DOCKER_VERSION}-dind stage: build @@ -241,8 +264,9 @@ build-images: - "apk add --no-cache make" - echo "$CI_REGISTRY_PASSWORD" | docker login --username "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY_URL script: - - docker build -q --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service - - docker build -q --network=host -t dbrepo-data-service:build --target build dbrepo-data-service + - docker build --network=host -t dbrepo-core:build --target build ./lib/java/dbrepo-core + - docker build --network=host -t dbrepo-data-service:build --target build dbrepo-data-service + - docker build --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service - docker compose build -q --parallel build-helm: @@ -266,9 +290,9 @@ test-metadata-service: - merge_requests - master needs: - - build-metadata-service + - build-java-lib dependencies: - - build-metadata-service + - build-java-lib script: - "mvn -f ./dbrepo-metadata-service/pom.xml clean test verify $MAVEN_OPTS" - "cat ./dbrepo-metadata-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -321,7 +345,7 @@ test-analyse-service: script: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-analyse-service/ && coverage run --rcfile=.coveragerc -m pytest tests/test_determine_dt.py tests/test_determine_pk.py tests/test_s3_client.py && coverage html && coverage xml && coverage report > ./coverage.txt + - cd ./dbrepo-analyse-service/ && coverage run --rcfile=.coveragerc -m pytest tests/test_determine_dt.py tests/test_determine_pk.py && coverage html && coverage xml && coverage report > ./coverage.txt - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" artifacts: when: always @@ -370,17 +394,10 @@ test-search-service: - build-search-service dependencies: - build-search-service - before_script: - - "cp -r ./dbrepo-search-service/init/clients ./dbrepo-search-service" - - "cp -r ./dbrepo-search-service/init/omlib ./dbrepo-search-service" - - "cp -r ./dbrepo-search-service/init/tests/rsa ./dbrepo-search-service/tests" - - "cp ./dbrepo-search-service/init/tests/test_keycloak_client.py ./dbrepo-search-service/tests" - - "cp ./dbrepo-search-service/init/tests/test_opensearch_client.py ./dbrepo-search-service/tests" - - "cp ./dbrepo-search-service/init/friendly_names_overrides.json ./dbrepo-search-service/friendly_names_overrides.json" script: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-search-service/ && coverage run --rcfile=.coveragerc -m pytest tests/test_app.py tests/test_jwt.py tests/test_opensearch_client.py tests/test_keycloak_client.py && coverage html && coverage xml && coverage report > ./coverage.txt + - cd ./dbrepo-search-service/ && coverage run --rcfile=.coveragerc -m pytest tests/test_app.py && coverage html && coverage xml && coverage report > ./coverage.txt - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" artifacts: when: always @@ -392,6 +409,60 @@ test-search-service: junit: ./dbrepo-search-service/coverage.xml coverage: '/TOTAL.*?([0-9]{1,3})%/' +test-dashboard-service: + image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} + stage: test + only: + - merge_requests + - master + variables: + PIPENV_PIPFILE: "./dbrepo-dashboard-service/Pipfile" + needs: + - build-dashboard-service + dependencies: + - build-dashboard-service + script: + - "pip install pipenv" + - "pipenv install gunicorn && pipenv install --dev --system --deploy" + - cd ./dbrepo-dashboard-service/ && coverage run --rcfile=.coveragerc -m pytest tests/test_integration_app.py && coverage html && coverage xml && coverage report > ./coverage.txt + - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" + artifacts: + when: always + paths: + - ./dbrepo-dashboard-service/coverage.xml + - ./dbrepo-dashboard-service/coverage.txt + expire_in: 1 days + reports: + junit: ./dbrepo-dashboard-service/coverage.xml + coverage: '/TOTAL.*?([0-9]{1,3})%/' + +test-dashboard-service-init: + image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} + stage: test + only: + - merge_requests + - master + variables: + PIPENV_PIPFILE: "./dbrepo-dashboard-service/init/Pipfile" + needs: + - build-dashboard-service + dependencies: + - build-dashboard-service + script: + - "pip install pipenv" + - "pipenv install gunicorn && pipenv install --dev --system --deploy" + - cd ./dbrepo-dashboard-service/init/ && coverage run --rcfile=.coveragerc -m pytest tests/test_app.py && coverage html && coverage xml && coverage report > ./coverage.txt + - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" + artifacts: + when: always + paths: + - ./dbrepo-dashboard-service/init/coverage.xml + - ./dbrepo-dashboard-service/init/coverage.txt + expire_in: 1 days + reports: + junit: ./dbrepo-dashboard-service/init/coverage.xml + coverage: '/TOTAL.*?([0-9]{1,3})%/' + test-search-service-init: image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} stage: test @@ -407,7 +478,7 @@ test-search-service-init: script: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-search-service/init/ && coverage run --rcfile=.coveragerc -m pytest tests/test_app.py tests/test_keycloak_client.py tests/test_opensearch_client.py && coverage html && coverage xml && coverage report > ./coverage.txt + - cd ./dbrepo-search-service/init/ && coverage run --rcfile=.coveragerc -m pytest tests/test_unit_app.py && coverage html && coverage xml && coverage report > ./coverage.txt - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" artifacts: when: always @@ -419,7 +490,7 @@ test-search-service-init: junit: ./dbrepo-search-service/coverage.xml coverage: '/TOTAL.*?([0-9]{1,3})%/' -test-lib: +test-python-lib: image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} stage: test only: @@ -428,9 +499,9 @@ test-lib: variables: PIPENV_PIPFILE: "./lib/python/Pipfile" needs: - - build-lib + - build-python-lib dependencies: - - build-lib + - build-python-lib script: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" @@ -490,7 +561,7 @@ release-images: - test-analyse-service - test-auth-service-init - test-data-service - - test-lib + - test-python-lib - test-metadata-service - test-search-service - test-search-service-init @@ -504,8 +575,9 @@ release-images: - "docker logout ${CI_REGISTRY2_URL}" - "echo ${CI_REGISTRY2_PASSWORD} | docker login --username ${CI_REGISTRY2_USER} --password-stdin ${CI_REGISTRY2_URL}" script: - - docker build -q --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service - - docker build -q --network=host -t dbrepo-data-service:build --target build dbrepo-data-service + - docker build --network=host -t dbrepo-core:build --target build ./lib/java/dbrepo-core + - docker build --network=host -t dbrepo-data-service:build --target build dbrepo-data-service + - docker build --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service - docker compose build -q --parallel - docker tag dbrepo-analyse-service:latest "${CI_REGISTRY2_URL}/analyse-service:${APP_VERSION}${BUILD_VERSION}" - docker tag dbrepo-dashboard-service:latest "${CI_REGISTRY2_URL}/dashboard-service:${APP_VERSION}${BUILD_VERSION}" @@ -635,10 +707,10 @@ scan-sonarqube: - master needs: - build-data-service - - build-metadata-service + - build-java-lib dependencies: - build-data-service - - build-metadata-service + - build-java-lib script: - 'sonar-scanner -Dsonar.token="${CI_SONAR_TOKEN}"' allow_failure: true diff --git a/.scripts/check-service.sh b/.scripts/check-service.sh index 1af6d7eea1..f5d144abaa 100755 --- a/.scripts/check-service.sh +++ b/.scripts/check-service.sh @@ -7,6 +7,7 @@ compare "services.$1.restart" compare "services.$1.container_name" compare "services.$1.hostname" compare "services.$1.environment" +compare "services.$1.depends_on" compare "services.$1.healthcheck" compare "services.$1.logging" diff --git a/Makefile b/Makefile index b32b8e6e15..00c00d6208 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: all -APP_VERSION ?= 1.7.3 -CHART_VERSION ?= 1.7.3 +APP_VERSION ?= 1.8.0 +CHART_VERSION ?= 1.8.0 REPOSITORY_URL ?= registry.datalab.tuwien.ac.at/dbrepo .PHONY: all diff --git a/dbrepo-analyse-service/.gitignore b/dbrepo-analyse-service/.gitignore index 4ae9f6930d..daf1899e30 100644 --- a/dbrepo-analyse-service/.gitignore +++ b/dbrepo-analyse-service/.gitignore @@ -43,3 +43,4 @@ htmlcov/ .coverage .coverage.* *,cover +coverage.xml diff --git a/dbrepo-analyse-service/Dockerfile b/dbrepo-analyse-service/Dockerfile index 1432cd52c6..a140efd513 100644 --- a/dbrepo-analyse-service/Dockerfile +++ b/dbrepo-analyse-service/Dockerfile @@ -15,16 +15,15 @@ RUN pip install pipenv && \ pipenv install gunicorn && \ pipenv install --system --deploy -RUN adduser -D analyse-service --uid 1000 +RUN adduser -D dbrepo --uid 1001 WORKDIR /app -USER 1000 +USER 1001 -COPY --chown=1000 ./api ./api -COPY --chown=1000 ./as-yml ./as-yml -COPY --chown=1000 ./clients ./clients -COPY --chown=1000 ./*.py ./ +COPY --chown=1001 ./api ./api +COPY --chown=1001 ./as-yml ./as-yml +COPY --chown=1001 ./*.py ./ # non-root port EXPOSE 8080 diff --git a/dbrepo-analyse-service/Pipfile b/dbrepo-analyse-service/Pipfile index 0a8881e78e..408aef69eb 100644 --- a/dbrepo-analyse-service/Pipfile +++ b/dbrepo-analyse-service/Pipfile @@ -21,15 +21,13 @@ numpy = "*" pandas = "*" minio = "*" pydantic = "*" -dbrepo = {path = "./lib/dbrepo-1.7.3.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.8.0.tar.gz"} opensearch-py = "*" [dev-packages] coverage = "*" pytest = "*" requests-mock = "*" -testcontainers-minio = "*" -testcontainers-opensearch = "*" [requires] python_version = "3.11" diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index 7f5a9de58a..fc18ab664d 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6af4b2ce324df97cc0877129f7986549d6e07a877998431609e062e2b63a40ca" + "sha256": "b7c8a1b53fbd95813c0accfa6e5351d63059e0ad816bff0a1cb82e5fb7beced2" }, "pipfile-spec": 6, "requires": { @@ -180,20 +180,20 @@ }, "boto3": { "hashes": [ - "sha256:295648f887464ab74c5c301a44982df76f9ba39ebfc16be5b8f071ad1a81fe95", - "sha256:90fa5a91d7d7456219f0b7c4a93b38335dc5cf4613d885da4d4c1d099e04c6b7" + "sha256:82f4599a34f5eb66e916b9ac8547394f6e5899c19580e74b60237db04cf66d1e", + "sha256:fc462b9fd738bd8a1c121d94d237c6b6a05a2c1cc709d16f5223acb752f7310b" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.37.13" + "version": "==1.37.23" }, "botocore": { "hashes": [ - "sha256:60dfb831c54eb466db9b91891a6c8a0c223626caa049969d5d42858ad1e7f8c7", - "sha256:aa417bac0f4d79533080e6e17c0509e149353aec83cfe7879597a7942f7f08d0" + "sha256:3a249c950cef9ee9ed7b2278500ad83a4ad6456bc433a43abd1864d1b61b2acb", + "sha256:ffbe1f5958adb1c50d72d3ad1018cb265fe349248c08782d334601c0814f0e38" ], "markers": "python_version >= '3.8'", - "version": "==1.37.13" + "version": "==1.37.23" }, "certifi": { "hashes": [ @@ -425,9 +425,9 @@ }, "dbrepo": { "hashes": [ - "sha256:ad01d6dc5d99f3c0c9caf3fb11b51502bec5390c72ff28b6b725e2755f5a2f7c" + "sha256:7b9a70cf1bd9d623e52ada74d5585df53716353d509f5d905f1b431dd91c28d6" ], - "path": "./lib/dbrepo-1.7.3.tar.gz" + "path": "./lib/dbrepo-1.8.0.tar.gz" }, "events": { "hashes": [ @@ -852,109 +852,109 @@ }, "mistune": { "hashes": [ - "sha256:4b47731332315cdca99e0ded46fc0004001c1299ff773dfb48fbe1fd226de319", - "sha256:733bf018ba007e8b5f2d3a9eb624034f6ee26c4ea769a98ec533ee111d504dff" + "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", + "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0" ], "markers": "python_version >= '3.8'", - "version": "==3.1.2" + "version": "==3.1.3" }, "multidict": { "hashes": [ - "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", - "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056", - "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", - "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", - "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", - "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", - "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748", - "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", - "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f", - "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", - "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6", - "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada", - "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", - "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2", - "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d", - "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", - "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef", - "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", - "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", - "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60", - "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6", - "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", - "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478", - "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", - "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7", - "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56", - "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", - "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", - "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30", - "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", - "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", - "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0", - "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", - "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c", - "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", - "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", - "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", - "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", - "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", - "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2", - "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", - "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", - "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", - "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", - "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657", - "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581", - "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492", - "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43", - "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", - "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", - "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", - "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057", - "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc", - "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", - "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255", - "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1", - "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972", - "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53", - "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1", - "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", - "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a", - "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160", - "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c", - "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd", - "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", - "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5", - "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", - "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", - "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", - "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", - "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4", - "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", - "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", - "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28", - "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d", - "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a", - "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", - "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", - "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429", - "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", - "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", - "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", - "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392", - "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167", - "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c", - "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", - "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", - "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76", - "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875", - "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd", - "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", - "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db" + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" ], - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.0" }, "numpy": { "hashes": [ @@ -1110,107 +1110,107 @@ }, "propcache": { "hashes": [ - "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e", - "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe", - "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc", - "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829", - "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863", - "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f", - "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649", - "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6", - "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c", - "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a", - "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c", - "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545", - "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e", - "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe", - "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075", - "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57", - "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf", - "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d", - "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc", - "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0", - "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1", - "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64", - "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340", - "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db", - "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b", - "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641", - "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626", - "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7", - "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92", - "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07", - "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e", - "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787", - "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a", - "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810", - "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d", - "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0", - "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b", - "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043", - "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3", - "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7", - "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d", - "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf", - "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138", - "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c", - "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d", - "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46", - "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6", - "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa", - "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e", - "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05", - "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663", - "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f", - "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c", - "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f", - "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7", - "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f", - "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7", - "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9", - "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667", - "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86", - "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51", - "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0", - "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a", - "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c", - "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568", - "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af", - "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25", - "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5", - "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe", - "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf", - "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9", - "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf", - "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767", - "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90", - "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c", - "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d", - "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929", - "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e", - "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32", - "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14", - "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8", - "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b", - "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc", - "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa", - "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce", - "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b", - "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e", - "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf", - "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9", - "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac", - "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f", - "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374", - "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e", - "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d", - "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e", - "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121", - "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5", - "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54" + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" ], "markers": "python_version >= '3.9'", - "version": "==0.3.0" + "version": "==0.3.1" }, "pycparser": { "hashes": [ @@ -1257,118 +1257,117 @@ }, "pydantic": { "hashes": [ - "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", - "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236" + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.10.6" + "markers": "python_version >= '3.9'", + "version": "==2.11.1" }, "pydantic-core": { "hashes": [ - "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278", - "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", - "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", - "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f", - "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", - "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", - "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54", - "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630", - "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", - "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", - "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", - "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", - "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", - "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", - "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", - "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", - "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", - "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd", - "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", - "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", - "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", - "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", - "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", - "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", - "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", - "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", - "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", - "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", - "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", - "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", - "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", - "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf", - "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", - "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", - "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76", - "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362", - "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", - "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", - "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320", - "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118", - "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96", - "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", - "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046", - "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", - "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", - "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", - "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", - "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67", - "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", - "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", - "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35", - "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", - "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", - "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b", - "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", - "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", - "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", - "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145", - "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", - "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", - "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", - "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", - "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", - "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", - "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5", - "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", - "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", - "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", - "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", - "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da", - "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", - "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", - "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993", - "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656", - "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4", - "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", - "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb", - "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d", - "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", - "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e", - "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", - "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc", - "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a", - "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9", - "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506", - "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b", - "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1", - "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", - "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", - "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", - "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", - "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", - "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", - "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", - "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308", - "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2", - "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228", - "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b", - "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", - "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad" + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" ], - "markers": "python_version >= '3.8'", - "version": "==2.27.2" + "markers": "python_version >= '3.9'", + "version": "==2.33.0" }, "pyjwt": { "hashes": [ @@ -1388,10 +1387,10 @@ }, "pytz": { "hashes": [ - "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", - "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e" + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" ], - "version": "==2025.1" + "version": "==2025.2" }, "pyyaml": { "hashes": [ @@ -1471,112 +1470,123 @@ }, "rpds-py": { "hashes": [ - "sha256:09cd7dbcb673eb60518231e02874df66ec1296c01a4fcd733875755c02014b19", - "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c", - "sha256:0fced9fd4a07a1ded1bac7e961ddd9753dd5d8b755ba8e05acba54a21f5f1522", - "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31", - "sha256:11dd60b2ffddba85715d8a66bb39b95ddbe389ad2cfcf42c833f1bcde0878eaf", - "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4", - "sha256:1b08027489ba8fedde72ddd233a5ea411b85a6ed78175f40285bd401bde7466d", - "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b", - "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e", - "sha256:1eedaaccc9bb66581d4ae7c50e15856e335e57ef2734dbc5fd8ba3e2a4ab3cb6", - "sha256:243241c95174b5fb7204c04595852fe3943cc41f47aa14c3828bc18cd9d3b2d6", - "sha256:26bb3e8de93443d55e2e748e9fd87deb5f8075ca7bc0502cfc8be8687d69a2ec", - "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122", - "sha256:28358c54fffadf0ae893f6c1050e8f8853e45df22483b7fff2f6ab6152f5d8bf", - "sha256:285019078537949cecd0190f3690a0b0125ff743d6a53dfeb7a4e6787af154f5", - "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93", - "sha256:2a54027554ce9b129fc3d633c92fa33b30de9f08bc61b32c053dc9b537266fed", - "sha256:2c6ae11e6e93728d86aafc51ced98b1658a0080a7dd9417d24bfb955bb09c3c2", - "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd", - "sha256:35d5631ce0af26318dba0ae0ac941c534453e42f569011585cb323b7774502a5", - "sha256:3614d280bf7aab0d3721b5ce0e73434acb90a2c993121b6e81a1c15c665298ac", - "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c", - "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70", - "sha256:3d8abf7896a91fb97e7977d1aadfcc2c80415d6dc2f1d0fca5b8d0df247248f3", - "sha256:3e77febf227a1dc3220159355dba68faa13f8dca9335d97504abf428469fb18b", - "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5", - "sha256:3ee9d6f0b38efb22ad94c3b68ffebe4c47865cdf4b17f6806d6c674e1feb4246", - "sha256:4233df01a250b3984465faed12ad472f035b7cd5240ea3f7c76b7a7016084495", - "sha256:4263320ed887ed843f85beba67f8b2d1483b5947f2dc73a8b068924558bfeace", - "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f", - "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935", - "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64", - "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad", - "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957", - "sha256:5c9ff044eb07c8468594d12602291c635da292308c8c619244e30698e7fc455a", - "sha256:5e9c206a1abc27e0588cf8b7c8246e51f1a16a103734f7750830a1ccb63f557a", - "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6", - "sha256:633462ef7e61d839171bf206551d5ab42b30b71cac8f10a64a662536e057fdef", - "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba", - "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722", - "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10", - "sha256:721f9c4011b443b6e84505fc00cc7aadc9d1743f1c988e4c89353e19c4a968ee", - "sha256:72e680c1518733b73c994361e4b06441b92e973ef7d9449feec72e8ee4f713da", - "sha256:75307599f0d25bf6937248e5ac4e3bde5ea72ae6618623b86146ccc7845ed00b", - "sha256:754fba3084b70162a6b91efceee8a3f06b19e43dac3f71841662053c0584209a", - "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731", - "sha256:7938c7b0599a05246d704b3f5e01be91a93b411d0d6cc62275f025293b8a11ce", - "sha256:7b77e07233925bd33fc0022b8537774423e4c6680b6436316c5075e79b6384f4", - "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b", - "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707", - "sha256:7f9682a8f71acdf59fd554b82b1c12f517118ee72c0f3944eda461606dfe7eb9", - "sha256:8d67beb6002441faef8251c45e24994de32c4c8686f7356a1f601ad7c466f7c3", - "sha256:9441af1d25aed96901f97ad83d5c3e35e6cd21a25ca5e4916c82d7dd0490a4fa", - "sha256:98b257ae1e83f81fb947a363a274c4eb66640212516becaff7bef09a5dceacaa", - "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a", - "sha256:a1c66e71ecfd2a4acf0e4bd75e7a3605afa8f9b28a3b497e4ba962719df2be57", - "sha256:a1e17d8dc8e57d8e0fd21f8f0f0a5211b3fa258b2e444c2053471ef93fe25a00", - "sha256:a20cb698c4a59c534c6701b1c24a968ff2768b18ea2991f886bd8985ce17a89f", - "sha256:a970bfaf130c29a679b1d0a6e0f867483cea455ab1535fb427566a475078f27f", - "sha256:a98f510d86f689fcb486dc59e6e363af04151e5260ad1bdddb5625c10f1e95f8", - "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057", - "sha256:ad76f44f70aac3a54ceb1813ca630c53415da3a24fd93c570b2dfb4856591017", - "sha256:ae28144c1daa61366205d32abd8c90372790ff79fc60c1a8ad7fd3c8553a600e", - "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165", - "sha256:b5a96fcac2f18e5a0a23a75cd27ce2656c66c11c127b0318e508aab436b77428", - "sha256:b5ef909a37e9738d146519657a1aab4584018746a18f71c692f2f22168ece40c", - "sha256:b79f5ced71efd70414a9a80bbbfaa7160da307723166f09b69773153bf17c590", - "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4", - "sha256:b92f5654157de1379c509b15acec9d12ecf6e3bc1996571b6cb82a4302060447", - "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e", - "sha256:c1f8afa346ccd59e4e5630d5abb67aba6a9812fddf764fd7eb11f382a345f8cc", - "sha256:c5334a71f7dc1160382d45997e29f2637c02f8a26af41073189d79b95d3321f1", - "sha256:c617d7453a80e29d9973b926983b1e700a9377dbe021faa36041c78537d7b08c", - "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6", - "sha256:c6760211eee3a76316cf328f5a8bd695b47b1626d21c8a27fb3b2473a884d597", - "sha256:c698d123ce5d8f2d0cd17f73336615f6a2e3bdcedac07a1291bb4d8e7d82a05a", - "sha256:c76b32eb2ab650a29e423525e84eb197c45504b1c1e6e17b6cc91fcfeb1a4b1d", - "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8", - "sha256:c9e799dac1ffbe7b10c1fd42fe4cd51371a549c6e108249bde9cd1200e8f59b4", - "sha256:cafa48f2133d4daa028473ede7d81cd1b9f9e6925e9e4003ebdf77010ee02f35", - "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5", - "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5", - "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc", - "sha256:d6adb81564af0cd428910f83fa7da46ce9ad47c56c0b22b50872bc4515d91966", - "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d", - "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef", - "sha256:d9f75a06ecc68f159d5d7603b734e1ff6daa9497a929150f794013aa9f6e3f12", - "sha256:db7707dde9143a67b8812c7e66aeb2d843fe33cc8e374170f4d2c50bd8f2472d", - "sha256:e0397dd0b3955c61ef9b22838144aa4bef6f0796ba5cc8edfc64d468b93798b4", - "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149", - "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35", - "sha256:e5963ea87f88bddf7edd59644a35a0feecf75f8985430124c253612d4f7d27ae", - "sha256:e768267cbe051dd8d1c5305ba690bb153204a09bf2e3de3ae530de955f5b5580", - "sha256:e9cb79ecedfc156c0692257ac7ed415243b6c35dd969baa461a6888fc79f2f07", - "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219", - "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7", - "sha256:f35eff113ad430b5272bbfc18ba111c66ff525828f24898b4e146eb479a2cdda", - "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013", - "sha256:f7356a6da0562190558c4fcc14f0281db191cdf4cb96e7604c06acfcee96df15", - "sha256:f88626e3f5e57432e6191cd0c5d6d6b319b635e70b40be2ffba713053e5147dd", - "sha256:fad784a31869747df4ac968a351e070c06ca377549e4ace94775aaa3ab33ee06", - "sha256:fc869af5cba24d45fb0399b0cfdbcefcf6910bf4dee5d74036a57cf5264b3ff4", - "sha256:fee513135b5a58f3bb6d89e48326cd5aa308e4bcdf2f7d59f67c861ada482bf8" + "sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046", + "sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724", + "sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33", + "sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc", + "sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032", + "sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a", + "sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7", + "sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c", + "sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718", + "sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc", + "sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d", + "sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272", + "sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f", + "sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d", + "sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b", + "sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb", + "sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef", + "sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b", + "sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45", + "sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4", + "sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796", + "sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3", + "sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c", + "sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9", + "sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f", + "sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029", + "sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9", + "sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399", + "sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586", + "sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda", + "sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91", + "sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b", + "sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a", + "sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c", + "sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405", + "sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5", + "sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143", + "sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a", + "sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c", + "sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78", + "sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0", + "sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350", + "sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7", + "sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba", + "sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664", + "sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a", + "sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56", + "sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e", + "sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d", + "sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1", + "sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964", + "sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791", + "sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124", + "sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e", + "sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120", + "sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad", + "sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc", + "sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c", + "sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e", + "sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba", + "sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797", + "sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149", + "sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5", + "sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240", + "sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034", + "sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25", + "sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7", + "sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d", + "sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793", + "sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba", + "sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d", + "sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d", + "sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391", + "sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e", + "sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f", + "sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7", + "sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd", + "sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f", + "sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb", + "sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea", + "sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e", + "sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052", + "sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd", + "sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47", + "sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d", + "sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9", + "sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8", + "sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875", + "sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65", + "sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e", + "sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114", + "sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44", + "sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9", + "sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a", + "sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205", + "sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164", + "sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58", + "sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3", + "sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6", + "sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97", + "sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6", + "sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae", + "sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727", + "sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098", + "sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c", + "sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1", + "sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8", + "sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d", + "sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103", + "sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30", + "sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d", + "sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5", + "sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07", + "sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83" ], "markers": "python_version >= '3.9'", - "version": "==0.23.1" + "version": "==0.24.0" }, "s3transfer": { "hashes": [ @@ -1588,11 +1598,11 @@ }, "setuptools": { "hashes": [ - "sha256:199466a166ff664970d0ee145839f5582cb9bca7a0a3a2e795b6a9cb2308e9c6", - "sha256:43b4ee60e10b0d0ee98ad11918e114c70701bc6051662a9a675a0496c1a158f4" + "sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54", + "sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8" ], "markers": "python_version >= '3.9'", - "version": "==76.0.0" + "version": "==78.1.0" }, "six": { "hashes": [ @@ -1620,19 +1630,27 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" }, "tzdata": { "hashes": [ - "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", - "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639" + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" ], "markers": "python_version >= '2'", - "version": "==2025.1" + "version": "==2025.2" }, "urllib3": { "hashes": [ @@ -2007,73 +2025,73 @@ }, "coverage": { "hashes": [ - "sha256:056d3017ed67e7ddf266e6f57378ece543755a4c9231e997789ab3bd11392c94", - "sha256:0ce8cf59e09d31a4915ff4c3b94c6514af4c84b22c4cc8ad7c3c546a86150a92", - "sha256:104bf640f408f4e115b85110047c7f27377e1a8b7ba86f7db4fa47aa49dc9a8e", - "sha256:1393e5aa9441dafb0162c36c8506c648b89aea9565b31f6bfa351e66c11bcd82", - "sha256:1586ad158523f4133499a4f322b230e2cfef9cc724820dbd58595a5a236186f4", - "sha256:180e3fc68ee4dc5af8b33b6ca4e3bb8aa1abe25eedcb958ba5cff7123071af68", - "sha256:1b336d06af14f8da5b1f391e8dec03634daf54dfcb4d1c4fb6d04c09d83cef90", - "sha256:1c8fbce80b2b8bf135d105aa8f5b36eae0c57d702a1cc3ebdea2a6f03f6cdde5", - "sha256:2d673e3add00048215c2cc507f1228a7523fd8bf34f279ac98334c9b07bd2656", - "sha256:316f29cc3392fa3912493ee4c83afa4a0e2db04ff69600711f8c03997c39baaa", - "sha256:33c1394d8407e2771547583b66a85d07ed441ff8fae5a4adb4237ad39ece60db", - "sha256:37cbc7b0d93dfd133e33c7ec01123fbb90401dce174c3b6661d8d36fb1e30608", - "sha256:39abcacd1ed54e2c33c54bdc488b310e8ef6705833f7148b6eb9a547199d375d", - "sha256:3ab7090f04b12dc6469882ce81244572779d3a4b67eea1c96fb9ecc8c607ef39", - "sha256:3b0e6e54591ae0d7427def8a4d40fca99df6b899d10354bab73cd5609807261c", - "sha256:416e2a8845eaff288f97eaf76ab40367deafb9073ffc47bf2a583f26b05e5265", - "sha256:4545485fef7a8a2d8f30e6f79ce719eb154aab7e44217eb444c1d38239af2072", - "sha256:4c124025430249118d018dcedc8b7426f39373527c845093132196f2a483b6dd", - "sha256:4fbb7a0c3c21908520149d7751cf5b74eb9b38b54d62997b1e9b3ac19a8ee2fe", - "sha256:52fc89602cde411a4196c8c6894afb384f2125f34c031774f82a4f2608c59d7d", - "sha256:55143aa13c49491f5606f05b49ed88663446dce3a4d3c5d77baa4e36a16d3573", - "sha256:57f3bd0d29bf2bd9325c0ff9cc532a175110c4bf8f412c05b2405fd35745266d", - "sha256:5b2f144444879363ea8834cd7b6869d79ac796cb8f864b0cfdde50296cd95816", - "sha256:5efdeff5f353ed3352c04e6b318ab05c6ce9249c25ed3c2090c6e9cadda1e3b2", - "sha256:60e6347d1ed882b1159ffea172cb8466ee46c665af4ca397edbf10ff53e9ffaf", - "sha256:693d921621a0c8043bfdc61f7d4df5ea6d22165fe8b807cac21eb80dd94e4bbd", - "sha256:708f0a1105ef2b11c79ed54ed31f17e6325ac936501fc373f24be3e6a578146a", - "sha256:70f0925c4e2bfc965369f417e7cc72538fd1ba91639cf1e4ef4b1a6b50439b3b", - "sha256:7789e700f33f2b133adae582c9f437523cd5db8de845774988a58c360fc88253", - "sha256:7b6c96d69928a3a6767fab8dc1ce8a02cf0156836ccb1e820c7f45a423570d98", - "sha256:7d2a65876274acf544703e943c010b60bd79404e3623a1e5d52b64a6e2728de5", - "sha256:7f18d47641282664276977c604b5a261e51fefc2980f5271d547d706b06a837f", - "sha256:89078312f06237417adda7c021c33f80f7a6d2db8572a5f6c330d89b080061ce", - "sha256:8c938c6ae59be67ac19a7204e079efc94b38222cd7d0269f96e45e18cddeaa59", - "sha256:8e336b56301774ace6be0017ff85c3566c556d938359b61b840796a0202f805c", - "sha256:a0a207c87a9f743c8072d059b4711f8d13c456eb42dac778a7d2e5d4f3c253a7", - "sha256:a2454b12a3f12cc4698f3508912e6225ec63682e2ca5a96f80a2b93cef9e63f3", - "sha256:a538a23119d1e2e2ce077e902d02ea3d8e0641786ef6e0faf11ce82324743944", - "sha256:aa4dff57fc21a575672176d5ab0ef15a927199e775c5e8a3d75162ab2b0c7705", - "sha256:ad0edaa97cb983d9f2ff48cadddc3e1fb09f24aa558abeb4dc9a0dbacd12cbb4", - "sha256:ae8006772c6b0fa53c33747913473e064985dac4d65f77fd2fdc6474e7cd54e4", - "sha256:b0fac2088ec4aaeb5468b814bd3ff5e5978364bfbce5e567c44c9e2854469f6c", - "sha256:b3e212a894d8ae07fde2ca8b43d666a6d49bbbddb10da0f6a74ca7bd31f20054", - "sha256:b54a1ee4c6f1905a436cbaa04b26626d27925a41cbc3a337e2d3ff7038187f07", - "sha256:b667b91f4f714b17af2a18e220015c941d1cf8b07c17f2160033dbe1e64149f0", - "sha256:b8c36093aca722db73633cf2359026ed7782a239eb1c6db2abcff876012dc4cf", - "sha256:bb356e7ae7c2da13f404bf8f75be90f743c6df8d4607022e759f5d7d89fe83f8", - "sha256:bce730d484038e97f27ea2dbe5d392ec5c2261f28c319a3bb266f6b213650135", - "sha256:c075d167a6ec99b798c1fdf6e391a1d5a2d054caffe9593ba0f97e3df2c04f0e", - "sha256:c4e09534037933bf6eb31d804e72c52ec23219b32c1730f9152feabbd7499463", - "sha256:c5f8a5364fc37b2f172c26a038bc7ec4885f429de4a05fc10fdcb53fb5834c5c", - "sha256:cb203c0afffaf1a8f5b9659a013f8f16a1b2cad3a80a8733ceedc968c0cf4c57", - "sha256:cc41374d2f27d81d6558f8a24e5c114580ffefc197fd43eabd7058182f743322", - "sha256:cd879d4646055a573775a1cec863d00c9ff8c55860f8b17f6d8eee9140c06166", - "sha256:d013c07061751ae81861cae6ec3a4fe04e84781b11fd4b6b4201590234b25c7b", - "sha256:d8c7524779003d59948c51b4fcbf1ca4e27c26a7d75984f63488f3625c328b9b", - "sha256:d9710521f07f526de30ccdead67e6b236fe996d214e1a7fba8b36e2ba2cd8261", - "sha256:e1ffde1d6bc2a92f9c9207d1ad808550873748ac2d4d923c815b866baa343b3f", - "sha256:e7f559c36d5cdc448ee13e7e56ed7b6b5d44a40a511d584d388a0f5d940977ba", - "sha256:f2a1e18a85bd066c7c556d85277a7adf4651f259b2579113844835ba1a74aafd", - "sha256:f32b165bf6dfea0846a9c9c38b7e1d68f313956d60a15cde5d1709fddcaf3bee", - "sha256:f5a2f71d6a91238e7628f23538c26aa464d390cbdedf12ee2a7a0fb92a24482a", - "sha256:f81fe93dc1b8e5673f33443c0786c14b77e36f1025973b85e07c70353e46882b" + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==7.7.0" + "version": "==7.7.1" }, "docker": { "hashes": [ @@ -2099,11 +2117,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "minio": { "hashes": [ @@ -2250,11 +2268,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" }, "urllib3": { "hashes": [ diff --git a/dbrepo-analyse-service/app.py b/dbrepo-analyse-service/app.py index 1a2a058048..a0329d32e3 100644 --- a/dbrepo-analyse-service/app.py +++ b/dbrepo-analyse-service/app.py @@ -1,20 +1,17 @@ -import os import logging -from typing import Any, List - +import os from json import dumps +from typing import Any, List -import requests.exceptions +from botocore.exceptions import ClientError from dbrepo.api.dto import ApiError +from dbrepo.core.client.auth import User, AuthServiceClient from flasgger import LazyJSONEncoder, Swagger, swag_from from flask import Flask, Response, request from flask_cors import CORS from flask_httpauth import HTTPBasicAuth, MultiAuth, HTTPTokenAuth from prometheus_flask_exporter import PrometheusMetrics -from botocore.exceptions import ClientError - -from clients.keycloak_client import KeycloakClient, User from determine_dt import determine_datatypes from determine_pk import determine_pk @@ -100,15 +97,19 @@ template = { }, "type": "object" }, - "ErrorDto": { + "ApiError": { "properties": { "message": { "example": "Message", "type": "string" }, - "success": { - "example": False, - "type": "boolean" + "status": { + "example": "BAD_REQUEST", + "type": "string" + }, + "code": { + "example": "error.dashboard.create", + "type": "string" } }, "type": "object" @@ -149,10 +150,6 @@ template = { "type": "integer", "example": 4 }, - "dfid": { - "type": "integer", - "example": None - }, "enums": { "type": "array", "example": None, @@ -188,7 +185,7 @@ template = { "info": { "title": "Database Repository Analyse Service API", "description": "Service that analyses data structures", - "version": "1.5", + "version": "1.8.0", "contact": { "name": "Prof. Andreas Rauber", "email": "andreas.rauber@tuwien.ac.at" @@ -200,11 +197,11 @@ template = { }, "externalDocs": { "description": "Sourcecode Documentation", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/" }, "servers": [ { - "url": "http://localhost:5000", + "url": "http://localhost", "description": "Generated server url" }, { @@ -219,7 +216,7 @@ app.config["JWT_ALGORITHM"] = "HS256" app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKEY", "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB") + '\n-----END PUBLIC KEY-----' app.config["ANALYSE_NROWS"] = int(os.getenv('ANALYSE_NROWS', '10000')) -app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost/api/auth") +app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://auth-service:8080") app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") app.config["S3_ACCESS_KEY_ID"] = os.getenv('S3_ACCESS_KEY_ID', 'seaweedfsadmin') @@ -234,41 +231,28 @@ app.config["SYSTEM_PASSWORD"] = os.getenv('SYSTEM_PASSWORD', 'admin') app.json_encoder = LazyJSONEncoder +auth_client = AuthServiceClient(app.config["AUTH_SERVICE_ENDPOINT"], app.config["AUTH_SERVICE_CLIENT"], + app.config["AUTH_SERVICE_CLIENT_SECRET"], app.config["JWT_PUBKEY"]) + @token_auth.verify_token def verify_token(token: str): - if token is None or token == "": - return False - try: - client = KeycloakClient() - return client.verify_jwt(access_token=token) - except AssertionError: - return False + return auth_client.is_valid_token(token) @basic_auth.verify_password def verify_password(username: str, password: str) -> Any: - if username is None or username == "" or password is None or password == "": - return False - client = KeycloakClient() - try: - return client.verify_jwt(access_token=client.obtain_user_token(username=username, password=password)) - except AssertionError as error: - logging.error(error) - return False - except requests.exceptions.ConnectionError as error: - logging.error(f"Failed to connect to Authentication Service {error}") - return False + return auth_client.is_valid_password(username, password) @token_auth.get_user_roles def get_user_roles(user: User) -> List[str]: - return user.roles + return auth_client.get_user_roles(user) @basic_auth.get_user_roles def get_user_roles(user: User) -> List[str]: - return user.roles + return auth_client.get_user_roles(user) @app.route("/health", methods=["GET"], endpoint="analyse_health") @@ -300,7 +284,8 @@ def analyse_datatypes(): return ApiError(status='BAD_REQUEST', message=str(e), code='error.analyse.invalid').model_dump_json(), 400 except ClientError as e: logging.error(f"Failed to determine separator: {e}") - return ApiError(status='NOT_FOUND', message='Failed to find csv', code='error.analyse.missing').model_dump_json(), 404 + return ApiError(status='NOT_FOUND', message='Failed to find csv', + code='error.analyse.missing').model_dump_json(), 404 @app.route("/api/analyse/keys", methods=["GET"], endpoint="analyse_analyse_keys") diff --git a/dbrepo-analyse-service/clients/keycloak_client.py b/dbrepo-analyse-service/clients/keycloak_client.py deleted file mode 100644 index afa36a1112..0000000000 --- a/dbrepo-analyse-service/clients/keycloak_client.py +++ /dev/null @@ -1,37 +0,0 @@ -import logging -from dataclasses import dataclass -import requests -from flask import current_app -from typing import List - -from jwt import jwk_from_pem, JWT - - -@dataclass(init=True, eq=True) -class User: - username: str - roles: List[str] - - -class KeycloakClient: - - def obtain_user_token(self, username: str, password: str) -> str: - response = requests.post( - f"{current_app.config['AUTH_SERVICE_ENDPOINT']}/realms/dbrepo/protocol/openid-connect/token", - data={ - "username": username, - "password": password, - "grant_type": "password", - "client_id": current_app.config["AUTH_SERVICE_CLIENT"], - "client_secret": current_app.config["AUTH_SERVICE_CLIENT_SECRET"] - }) - body = response.json() - if "access_token" not in body: - raise AssertionError("Failed to obtain user token(s)") - return response.json()["access_token"] - - def verify_jwt(self, access_token: str) -> User: - public_key = jwk_from_pem(str(current_app.config["JWT_PUBKEY"]).encode('utf-8')) - payload = JWT().decode(message=access_token, key=public_key, do_time_check=True) - logging.debug(f"JWT token client_id={payload.get('client_id')} and realm_access={payload.get('realm_access')}") - return User(username=payload.get('client_id'), roles=payload.get('realm_access')["roles"]) diff --git a/dbrepo-analyse-service/determine_dt.py b/dbrepo-analyse-service/determine_dt.py index 8df1b7363f..722131801e 100644 --- a/dbrepo-analyse-service/determine_dt.py +++ b/dbrepo-analyse-service/determine_dt.py @@ -1,27 +1,24 @@ -# -*- coding: utf-8 -*- -""" -@author: Martin Weise -""" -import logging import io -import pandas +import logging -from numpy import dtype, max, min +import pandas +from dbrepo.core.client.storage import StorageServiceClient from flask import current_app -from pandas import DataFrame, NaT +from numpy import dtype, max, min +from pandas import DataFrame from pandas.errors import EmptyDataError, ParserError from api.dto import ColumnAnalysisDto, DataTypeDto, AnalysisDto -from clients.s3_client import S3Client def determine_datatypes(filename, enum=False, enum_tol=0.0001, separator=',') -> AnalysisDto: # Use option enum=True for searching Postgres ENUM Types in CSV file. Remark # Enum is not SQL standard, hence, it might not be supported by all db-engines. # However, it can be used in Postgres and MySQL. - s3_client = S3Client() - s3_client.file_exists(current_app.config['S3_BUCKET'], filename) - response = s3_client.get_file(current_app.config['S3_BUCKET'], filename) + storage_client = StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']) + storage_client.file_exists(current_app.config['S3_BUCKET'], filename) + response = storage_client.get_file(current_app.config['S3_BUCKET'], filename) stream = response['Body'] if response['ContentLength'] == 0: logging.warning(f'Failed to determine data types: file {filename} has empty body') @@ -44,8 +41,9 @@ def determine_datatypes(filename, enum=False, enum_tol=0.0001, separator=',') -> for encoding in ['utf-8', 'cp1252', 'latin1', 'iso-8859-1']: try: logging.debug(f"attempt parsing .csv using encoding {encoding}") - df = pandas.read_csv(fh, delimiter=separator, nrows=current_app.config['ANALYSE_NROWS'], - lineterminator=line_terminator, index_col=False, encoding=encoding) + df = pandas.read_csv(fh, delimiter=separator, lineterminator=line_terminator, index_col=False, + encoding=encoding) + df = df.sample(frac=1) logging.debug(f"parsing .csv using encoding {encoding} was successful") break except ParserError as error: @@ -98,7 +96,7 @@ def determine_datatypes(filename, enum=False, enum_tol=0.0001, separator=',') -> logging.debug(f"mapped column {name} from O to date") col.type = DataTypeDto.DATE continue - except ValueError: + except Exception: pass max_size = max(df[name].astype(str).map(len)) if max_size <= 1: diff --git a/dbrepo-analyse-service/determine_pk.py b/dbrepo-analyse-service/determine_pk.py index b0ad8cbf76..772c356fdd 100644 --- a/dbrepo-analyse-service/determine_pk.py +++ b/dbrepo-analyse-service/determine_pk.py @@ -1,11 +1,13 @@ -import json import logging -import pandas +import math import random + import numpy -import math +import pandas +from dbrepo.core.client.storage import StorageServiceClient +from flask import current_app + from determine_dt import determine_datatypes -from clients.s3_client import S3Client def determine_pk(filename: str, separator: str = ','): @@ -14,10 +16,10 @@ def determine_pk(filename: str, separator: str = ','): # {k.lower(): v for k, v in dt['columns'].items() if v != 'Numeric'} colnames = dt.keys() colindex = list(range(0, len(colnames))) - - s3_client = S3Client() - s3_client.file_exists('dbrepo', filename) - response = s3_client.get_file('dbrepo', filename) + storage_client = StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']) + storage_client.file_exists('dbrepo', filename) + response = storage_client.get_file('dbrepo', filename) stream = response['Body'] if response['ContentLength'] == 0: raise OSError(f'Failed to determine primary key: file {filename} has empty body') diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.3-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.7.3-py3-none-any.whl deleted file mode 100644 index c1a74fe8c7e3f602651db9b6c30a5f7dcf17d97b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32568 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 diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.3.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.7.3.tar.gz deleted file mode 100644 index 7c13793a4936d21d621548c512ca88cfbf914716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49697 zcmb2|=HQt5>UuiU|CFSn)Pj6nLp^gnW4)5ZB8E46Usm1rn4}T4|Eq|^*R_JBZHvlw zdR=~Fyh&yH)l^;GlTY83{a&mnH06RCqZxx&+V3mDci-<jP`OFkJ1>HBl7Q;%C*i3R z9rPwnoVYR7B`taH#((zW-=1IZyIa^KFZXow!TEdkOH1Fj{$*`<|IUqDcYYoG_2;mR z-C=`G%rE}6zyG}X>*TBbclKSrQ?qgN)~y@&?%sU+#?60~@0Z`5KdmmJX5UZ$=V}FP z|8Au{c1^DS+kQOyzkXTy$M?^=@A7_LAN6^*wf?uVhx^yQ^^N!+Z5=(^K4SOhnE!v- zkMqv`Q}p;={nGiziXZ%suFm|ofA53;#Si~S&-$OA^Y+c2A3vWTJJ$5Me*T~TXHP!- zc=PJV<Td~I&YdgsZ~xZqJNI_~sV~oGH#sP-pYS*Tea`#83AtyA|JE=6Q-4zGyQRd9 zx7Nq29&eM?FX=k<{~61|*VWg;k{9Rwz4@)J%wW?tGqbWH?YpiQ6Y6XKK76<^G1#2f zen;&4!tjT`gu?dN?X%gtiSJzBn!}$rFP{8*^5@Okudn`G`t{qZ9eJ^G@iFt{_u3vg zUaD1EQdC-7`RS9c-9k1q>1z`&m)e>$Jvel1QbSr~PsUBI_iy6Pzp~zz?rL!91m~}X zsnxQp-&V`6OD+9-K&s8}ZqrktA9E9><*&O2M{IlC7Wm*E&&Qpq?P2V@ORTP)J+Z6k z)}0e-TjYNnzHR+F{q*}o{Nks6zD>OUagj<)-2|pJZ~5ICtE<H$|202n5o=%(y_=D8 z^YDvv{CDbu>le*kBXx1EY~+QPxe3m$@27Eb+DI^1Y%e=+wQO0i1COnYg5&#$ve{7+ z0~n+htjRdm&cx(!opWclLx#wYy}MG``~F;1UhvvNs>bSz1Ak-r-+k{pr@1)3KG^$i zhwQrziF-dWHzgbJu-OIl99uQ3z|#HnqN%A;UKv;KgsyvKZ{aArOur%0Ng<|x|Mj&e zw%;=Iv6?2l_Jj5zhlH=W=l7KseA;lo;Kn}ThO2Aat=rr9H~as+b!A)UOm^{=oKY)x zGI09(S3Kw2uyoyR)*QY$3wnL8mzmeaEPYqwz^@!<X42D8&A7*a-N3g|_>|bflhVhT zRkp;=I2G}lZBEsx|IhfRua&xTH2>hIRhF+m$Uk~=?=8>9wFit|I-5MGVavEHz{t4c zcb<gMLE*U{l@?@rPP`@h<yxC6$LZDcmuzu-P%>Ac;nkOI-V*;?V!!<D<96Ph8G4el zY;Re<$BG8mjLN!{uXpx!?>%hOR%c%2@QG`s^NcBc3GwS}vph@=v%V_&TYmR;qQm>d zsH(n$cIWc{aW0v_cK4gxAD(5&Hx_@r$ot1`PtN_Dat^xU909H3NuJR{BDOC(=f|Gj zCSiLe#@5c^qFd684LNLjdK&W^gb(jw^=dFY@c2f9?>koIz3J~{ldSiY{q{S)b!~=; zLHplx{B}!c9AdUn>FDHFT>4V=K~<4N7NfzdBO87tR78B+`}W(L+4Exlv&FAcHg{#p zx!p7+=cu?!IkSmF;?a8&!2vf^x7-SB+0<&FvQX6bN&>^V^xgIi^A;*?C{rk2*P+VK z#>`&zkEeU(bNe+}Ix?1x)%+2A%5_{kcFbAA@J3mhJ?YCL)nkn;e~$4LezJ+`l6}Lx zQhr5yrD&P!<<{(n56|V^mpsFurp+YDplw|6E_RmJk|c-T2=!^q65p7Aa?cXDoU=~t zqJ)>FI*XU$o7)#=-e2s>c=b;7_2#%s#q*vWpX6Vfe0qPL>P7Vp?N@Z3_019wQZD$l zZS}R~#v7Oyi5%hPUHqQKFQ4W0f!{72yBV__tv<flw^>X5E~}eJ$y+nd&RvSiqCvq9 zie)nUSEv6Kh}=2h<4oguG0a&frT%KNbg`<Zu54nK?mo+TvA{h;X_M;wLg%dyYUMtZ zCI`Bl_*(m7m-@{zi#?3@6lb(wvF_N#QN-l0!}_Y@M}^ng37dT$tqX{n(ZyAi`bzHQ z-(!p^WsIUfPkCEr=IgFD)a~9DaZh_2&(t|`ItLE0r^OtP+_ACR#hst=+GmfS5>-sU z#nv$izwC1pd8EnpHA(SL`&XyHB^A?evj170$kg}Z+lC_k5U-500+C*#T<(cazBo^A zZ9XGwrQvi-McI{eUfq<MHET6uPrFpzO;9$}GT6{t!7RJomdEo{aDVNi=}x^h?lS(} zYR@;jIMu9~B$uf1@IWsA-$ah??fLBUCwyg%vYw<hU3k}axsP=Uu5*-~a@16nHb>bp z*W8}AGfevQOVv3S)?eN5luKsyrx_eB|8Dq~WZh*nFz34<yrPG%u!!N-8+ZLf7k*wB zc(J_w?zY+k=H1yL6}?Z7_hhV2{M(czT2{THP2W`eb=HYPp%=2287Au(Pu8|pP}OC2 z6x$@wFmsE=C2j}HmcXVq^8%#<Ju3DIwR_JsckgO@UY%|7S+Pf=eqG}=;X8{SKIwlG zXA<?Ajqgv9<Hp_JZ=X03d@1He{f&iNwk=>=vyt&qVb|r%GCPTT4zUN61YRvjXI{8k zox!;K)`WQ+M-Oee?PD7MF)3(Tux(mL@grRu$J@tPVsD%%+243`rK4%Oz(XeH$;y+o zgcu|?Ic~|~typvHP2(=U-n%!y^JP{FDQsH&H&6VljR2D${|){B+%iY`mF7ttWp7!e zv&AXNxG1HAX`b@U)wU8}F5LNIJEP=~(I-8|sNLzi8}jwCdH6PX^v<{uT64Mis&re~ zgG;a8upOvf;`(?;(6^b~`^DBZNxrG>o6vFKpM!E>lx?VY*aYSz?r@K2hWS(XSQISk zW}m~Q`C96lr}*>un@)-aT1zrbH78b|R=Ba<Y@eE%I?wl6Vi8{3`TiKhD7QQ`xb;uq ztNK4)<NRpb--<H31o^f;zq3hzp~v&VR=)`kx?FksQka<KxPqg%U%ockc+%lXpD(KW ziq1+5)$!{LN}Y6UMTF+13m39|I&4;kZY(*V+O=6d^C;iaL)RMHC;bp9TWGpP*!m1t znbftV$yIGqS4!{8WuBY%#OVNg?8@6megrm7a}RFHQZ6xLQFAY8k>dUHb*f9>?6W$D ziY+2zXFIhB_(s(pe;E1hm+gkmh<)Dow(ei@W>u)%O973yVh>$E+_=|}S(?~!VvEn! z@W}Qbp1fDoeook;@^AK$6>mNtdofwoJZh?&HP_qnvR5n~P6>89<SubW_b<F?yUD`! z(hap)@3yz_wBPRhe#fkeZw`l8MC_}xZJhqs7#*g_%(=MnRe-RIZ1{|6eWi|fOH;aK z*}pE^wa`bP)2(V}=f;iPO3d?AynD0r&e*0(v&0-%Zxvg@!zX<4q_$qimIsrhYKj&V zE-4M0n7Q(&c$>W6*H1Tpem(i{qmj<O^MVhhr_X)C9GbUSzPMCUM<IFX5(DqgsV1tv z{?gAbyqnOwvh&<Y7i}X|>A!p2jGI;prax%BAn+>nLzc<p-iJPWgf==#+aBk;ILB!3 zmqlH1YZpj3F8?j$6Mbk!;aWqH#j7?5wEZ`mS=n>qOsQ<SLu6j~XGxKn+oPD4-TvNO zC3Sk+m9ISd(>L%MZMfpQMkGk#0MnC`O>E8Qr1*-KJUiz6Uq<50iU<ociG|n8b6OSu zdo8{>BR@#)#*{EWyA6t4K6XiY$;fQn){)$sw69Xt?2RA$e)f#_Gek1CC^?EtXl)jH z)$><C?U0P{&EOaJUX;kJH-6*2)zr;!(#8#c)t4Keyv%X%QYT}^i5Q<JYnf(uer-sY zvBciZ=iWY7wXQ9pj#=84uOk^fEcW%RJm7Z3!e_!o)#r<@NnI{7HmP`f>+}tyM`=BK zmG;kO^o`Y@ttZ*NSSI+$mvbwZy1Y%i-e&I4JmJ>bF3-fJrHl1vhGZ^TJR{mIQj61D z!Ax;?%A1b44BJAtib<HQ*)HdCae~^}pFFZ#V@>K;x+XWf{4{s-)V)-YCYiS;=K9oY zUp5|JqTC+3SNigAo6bzND>_V<6(sVSLa+DTseSS*y{={Im3O=+r%TW8HHz7`J>}j) z3B?PC6g!$PytLRO*mC;7455pH+2U^$Saq}}zYxo@Qu;G7LNR5c<@~wZ4nFGqsMW%9 zZmsNxeL<JL2~;yyAK+TbB%~B=^5sRJ{~Y6_skd(kIvwfeH4Te@V%B!oegDi$85dqZ zW%>T%vba5?n&aV^2%)ttJJ#*>JLJPVr=B-<V|5FYZHuMjM89CJru*+7e=~7nj$qrn zn3q{3cwrCUmn+NuY%VfASt)!;!I{NiS)9olWpkCwoaVW^uUTKPXVh2T$|17CT-hw) z<R>>_@6C*}T#e$kh_6|v?z84^Ky#FH#Kp`BCV^)!z1Y{|`%dfE)`qA0@-dO>;is>i zZeBfEyYo)D`t|ka@5e>I=hM^YKex`mZ~dCj-o?@X{!A?`_-6k4`sB^Z0p&6G82|O$ zyBN@aM0MXK!#hi=SSQZEGOZ?y#Z7Nv7tbPvvq_9Iud83r?|a?wb@SHAo5QE8r|*}U zFE>B-`r6BnPanR{@buv6$>!?U>y?G7N{edCYK}f+W?$6X-RwPM!}feWy|vxjr;9%i zKdzHoxqU;sH8;b52CLG{>y2e;H?(>tbDxQMz|SOpwOFb^d<A#6z~9Wi>>u7YZ%ec- z5Pn#oy1UHz(VK<$%cjme;}iR4^Ca_YcQSmXH~UoEn?Bg?q8V28_?CHIzu9^JfKO2i z{#6JbJeYf6v7DtfquYipyy4w<PBJld`Alzoe&<`vg?+cqWyQWNyPmu*=IKvK@Asx* zA{Un5FV6Q^sQe)BqWr>dx+&8I-4t53SkK#QH>3L45q7K8CsV%0yo#t`$;f)UuU7i| z!{l5^p#{y%hZ>u!UmtsCtfLW-Q>o1;D)H^*qqaF2Aw?Nqb~4_1v5v3eyv))aldkT_ zo?}wNIotVYa@(IHUyr0n)m;4|afR#q5!DcjH}lT3RKNZ`mwkKsFFyOmfN$)~(tBH0 z2=fSjSoii@8>6@K?(4EuQ9BhCX9#jO?Pl=Uqh_}wS)JvOqm>J*?aL0~T#fWycXyU& zPTrz@$UK3SL*>K+wu?6F8|F)2bCgbHN^&fUd-KzQJ1aSG&u-_dw)<ix&u(qKog2iR zd;h0hwd2XllDBiz=WD;njcxzIxxuRG!na#|{7DD$0uKIlb1C<`fB1sXTY=;)-&EdA ztG_H9r*SFz+QhdDo}G@?HIR$ZKeVst@QpHl35oT8*|)UZm=eOFTqDK%`eUF=_jThk z=PBoOx4E9^)Rt3LzM3=TfvT_j`$ZXj>ug=wBsu0A-15nr{?k~mBJO?5>~)8HkH2i% zdC1hk_+845b8i>;&+*W@&edII$=~eoej4X_!w)GNPF;*hRnM}0YrapCGu4?tqebF^ zMd+zN&5pfow^k%1GTGT#JMEk$%I5x_Ur%qriIef)3%O24Gsu*x91=fs!M4VIfz67& zDm?48BNyr&(s*=_Wo6j!4OvVEhm~JmU6Jj*@3qxlzl_F)hNI_v{<D>9$}Twb^t=4D ztrMH(aVoxbn>3?iHP`C%8<t3iy*=?gEM!l^Mz_?*|2Jk$-0GK>#qo+YfN8}KF1|!r ziKN>%W*^-u)YmY-K1_OH$`xaV1L_Ns^pEgr>FNGiGO0T_a+&l3qbm_N-zb?DE3|IB z6ScRn<OJ8-30@vfYj*G)nD|(#@`KT-t{>-?bJRH+G=7NLDz9&#{ylbTwVSo&n+3J) z*4KP^s*FGW<*<`q^PR=~z|0$|e;tmpPAuV>t?6f1YOHW&RU)Hk@y=iOZ?tT2pCGv5 zhtRv?mB)6^GjQ%S)#?h;>P!6k+x&^{=43r<&l6=TCu?I)tmJ5nW1g_mOOn^t|GR); zy7#i_Ms50>a%~0@te;FiNM6lfSs{FDos2qLlS)xgc0*c1#=W-!9DE^60^D&%oBS)h zx9pQ!cKm8Y%XR%v^<qEgcmFwm^!e)(|9AfQDqgZ^&Uw@S>FL?|>E;vv@7&8>FZR>E z_{SWpiFY?DSNp!m`n_OHuI}8%N89rab9GjlyQp}FAGWLV`@VMZ^ywdN?UHaUw`04| zcu%%xTHNp2bY9b|wLx2*7H03fyFrjwKIVA#jkj&GYm;BJ_0G0=o58_#%Bp-DU+o%w z*?=i8_LXu)X=Q}G7x?_>q0}*^@88y@evZAnt1f$Q^S0@0?Z3UOY)*S!e@5>A7L_ZL zYO`xDU4C-X|FXK{RNuBqPtUZadG(#jGMK3|HFVjnCz@OLhkFWz8tySx51o0Dcd}~u zQ>HM_O;c}eTC4NYt4_;vU(n*UDxBW!bs-aaL=VS^dPc4~ICJvmPabL4QgmgX8%JIW zld}<3D?I94nCAB^=wr;|NxMF^nH5i(o+KfvQZ30SXRKa3Gp4-eQ@C8!Di5~F^SdS; zGPys?($c3+%~$C3;jmQC<WIq|pJpU+hN?|G>A&@4%Epe>U6W3U%wJ)&^UM`dFO`{3 z1J9oEOjnb+sxp72n6{@=@QL+Cl4m;-SL<l5b@(~k%F?%Pm3L6Lub=73tXa#$W^PIA zTF^D=`jh3GRJN6Pe91YP<5jv=Wo53;=^2(MeRUVFnsm44Xq?$g-Rvo$Y6oAY#(M6W z+NHZr>8;k<vp#cWmOnbR+H2C}`70+s-K4f{)03U+6T?>fteQOk)TGx*hMz=LZk{~< z=49EY;J{0BX9fnieww>2G2Qo2@ap}uQf!RZ?eAJ*vv}{!$)BGrpQU1}oW3AtQ=FLg zDy>TWW9sRCkAk_9MNig5{nqh$b^4-ln(wFCS~vCir@fl=U(J{4O!JCOOAdHVW?t<j zw8kW|pypD7+@#f>N;NGhhq@+nY5VD|u{gQmQ_5kl$$YE*?beuZZv2&U#A~w9YG1!K zHl7<Fr5x>=EOuO7|CzzIQ<Eg8cC1%hd9lDYeBzx9GxOw0i(lrhQ@LsQ?w$1PFEdOh zPE~Wvs*iL%Iibxp%rhuu+ezEXq9uPqrmJN7rHY=MWH@<a%B2*s+K^c;D<iT~Pfls; z3y%z1`s})~dU#smmRTv@Td$<~?(*5GwakBCNLq@j=L|2~wR)15FIc7dotiTL)Fk7p zJz-OqtUTgtdU96emYB#-%N8bvO*pdBrdL$8SZiNsV9@eEA=B?<-YB}NQkfOIbW+Os z8SR<hmiQmOZd?5+-Nq<)n@WJFrlqe@#x<_hdX^?zZ`ylL%FwY`-jot}*lm?crpdmu zR@I+YY&;#|DYR0tGtE!!s`WNw^{G-hOBOu|N?veTeP)_&&!Q!l*L=FHw(wcR{;4WU zwLULvdJ=MY#~fSFt4~CY)mP8jC~2&=Rx5eWtS6yQ-RG-zhOV8-IVo~;M^@95YinMK zs_Z`HFY3A8Q~%<QC)eksnt2-Kgb9nP9$&WS{brSuVJT`yC#61JzGzA0+67{&=k;P) z?D8J2-MhD@IcMwp4N_*MVZLkjF5aPEv&-%KHTEfgCTIL+Y2N8{_r+T2uWx1_dvLDI zy3tpKO)F)CTc!Iqf#+A^Uf)@hxLWbp{Jv|uWvhKHbPs*qTFS-G{djLo=Ztr&sv>_~ zm2C8R*<!SLWgUyD;fia!LPDqUO;mq0Es5c%!}FIvnUi*hH=In&c>6xu`r53ompb1> zT+FU#c(SoSp!-JYW+R*DUo;KYCSOfBu)Xo_du7GF6SuG~bv-9qb2~35@7St2{1?t0 z;tCgWX>UE3IFX??afZ<`&RIuQHG@|Q_oVXG^xSK@-*iy3BUR{%s{Z$a-i0@||GT21 z(YK{0!a8O9*;`*T9=w?x5bb_Hm_1^R&*7+QRvUhX1i8i0woR`4{B4eMF8<(ucI~lm zX`kL6_?xnPUa!@QIT`Bn4{zadTX|@M$lHRK87x5ua^H6g1pNK&m$p$?_phS*#oU*B zw2dro*-qd4{7ci0L)Gg(FEqP*=vHRV`ew_N<Qq&AA52;n)fcF`RDNnA`%}5&b^44Y z?^Pd_TyMU3VChqX2TwQabtj0wSG~n`>a^19)z^fynBEKib$$Bqt5w{zPwn;$cUu$m zl2cw>x^%o>{^AM--MW|mH_j-I$gZ7nhVkgB1%diOd<&mk5~_4=WV2Vi*e%#zBsSsE zzwX^XPG88aKcsUmBlD%Wy3oU%7OQ(7Hm>cMJ7wXF^4H3GZ^Jiin$!QAMcjF_%TdX; zW2y^YOh})myj<sRN~Y(T%F7iI%}-4~IG)bb^S<KpVUyx5<Mg^p(Gy&WTi0&zf9#gv zEV4&q@BdCk=8LkkR2u&a=#}oeAo%^pj?zV9yvtilvnDx2<t^X&Ca0wC)~#PJkKQ^j zZU2AIw#^?O9lhm$ckle`+iuUcFTZ`;{O#Gfcb`@TDk*L6$=!S7&A%&k8#ix%b|bnv z+q!!9>}>Pfch_#+wt4gS%ir9}FTZ;yvc2{6@|}!}?)}|<`A%G{67Pm<FCX3b_<85m zZ;kh7N$EtCb%cJ=-T7hp#f*sWW%(}(blTqUl;uh}x<(`;<?tr6?^3&?t7q%$yq@Z8 zVzOsrmiY47(hL0l-~a!<Z14a2|M7XpZrx(pduEfF*>}UgGpcK9fAP(_IcLSpw|mmI zsb!_<FPF@C@z?C^uCF(5-C<htrL9)~&jIg80&DDh4u;s3JI-XYeVjKz-_y?R&Z0FD zOgkj3J}dvQdbNx3)t$3X*S&upaE^gR_|$`EpL%5vC@CJ2FOkZsaCv`LU%RO+?3?Jh z*Vnp~6e{*in$tM7CMwo3>#$W)U)U=P&;8x+tna#UWb?@~&(D4zdR{(^)k`XOmPp)` zscYSjT@ii0=9=TrT*K(>ICkgux^{&*zsuefrg?J&iWgo#veZ4LMTNtu>xNJCge!AZ zwDYDPGMU>U(%HXJ&?$A>{KBAF>klj_3A1NXxBGbD5?l1r-1aTo9bd}1xSQn%w<{g% zG3ex<b6%m_@>);FoV9^7cm(|SUYumI%CO{EeZu~F>5{r@+uXzCh2OJ@_&Z-sKEfA} z<`>V=wD+iJ!mOX_Kii)i=4WzOh*%f#tikLH*Rg(~Tfh7R-X6+$%M`m?#BAG^w7Eff zOc%|48tyLp;IsPMzQ@}SXNorLEv<gA?ti1;{x;wBoo(Uaq0_ymUE)79^S5-{g-24e zbic3rykOTfS&6%={7&9wxpt|ZNnwVLT1;1HpUt(uoPm=iOoM_|Z4G<Zb(*bIKA2W$ zKGSxA_bo=o^Q&Hpmwt%$?=8rEP`2W8^1ZA!y+p|ct^vN~3AY{@XufZ9@BGysHYua9 z{k6r<hgQ?MGDT&&Y9a$#`3<fK@YLS>xZsBPY55f=nx)yV|FF6g@E}Qq&styR{XO2A zex1418wyt_Z@kI--!f_QQup7-?k4hYUzy=8zqozvQhWYH&*t2kXYS{E-`8_#?vYOK z_&eu-f5(po!I~V0czM?a!XC%x<zKezkT%SZ*k!YCSDtLloGpFl`}EHFpIf)}Nm5O& z*_^VNf|pkL>-+T2^ZE5hHoSZ;&K@5A{+xb)M8?bK;m6za^%t6KdiHc_^X2_97am`K z9-g`@^r`+i{e^$t-RstUoX8{=Yr)rD_3!q{r(bV3n=dMUS29y_Zpvy|^OWtq_0`&w zCN5!cSjXGHR_@lCBRi$H^S)M=6E$A?PiJ1ozG+9|L-Ot)2v=XRR_S_O^WUpayx-(a zm8hPk$8_HG`M#FU_qUm!oC{A;nE3bL5gEqUaZ$hGGos6-ul;6T->g^qS}257{X(}+ z(cvRp&Sej(U*EQWpZn*^j_zN3ui7_-eo`;|azg(4NA@k%B}{8)EuTCkL%5_xJUV)3 zZ{6$X^|^1Cp8tO<Zq9$x>7Vy+`|>k>w*C8@ckkYqn2D*^*Uo=lA1fy>Ggr?1*WAi^ z|F?cj%1-V+_y3UcfwB)jpMC4@eS7q0{O2D!duDULe|Bj1&JTHdc$hVNW^>D*dGxRS z=wJTxum82*-8;XmKCYs1zxn_57got7|J{G%?%B`(FU|75^MAwlr049}<q!Y=wfpfu z>Hqu4H~({U-oE*>W#iTx|9_wR`QPz>Jo7edspgB1-~WI6?%f;3|M&0SX8fC+%zf?u zy>ChX^X=plSN&R8v>-XF^@m*FmB;mMw~p(*y*0xzhyM<n`i4Ne$r@eLzb&wDz5K1O z`2hd4DYiAq?Rm3h4NUz4bJqQd*nHT`Xvx(Jzc#wHuUVg)_psdP{Lh1O|K2@zT(~_T zZ|S*Z)t60{Zr*z|k>y&!e$K~PErG}7-Bx?Q_<h{O-S<n)y@#KSp4TM>Evr*6QrcaY zAjcwWZPl|q_@a5DY|Na1d(w}Y_6G8D@Aav8<|E&~GC^IqdYXmlXZb5H_hzSCPkZ%d z&Vffo)lIwG^7{49O?~eEdvfdkQxli3+#t-`uXxd+V0jkDO+DRxj>Yp=MVdGMKgk(Y zZl`uxpzBG+$H2o@;&sNmd{4-ITX3c5eEx0Qn!R^UWN-ye$>5StHEVshsLD;6!ED~m z*{stlLK)^2NFPm@yxXet*puYNikqk1dG5*QZsT`t(iE}7nm&`SZaMeFu-Z^%=Mz~c zl^O3JHTz$=&g{A8!Uie*X)cF$U(I@W@$1?!-IA)iJ*ra~KXuJ|HuVqJ$-*bo&q!V6 z@(&IB9r^f-#x&Dcq1kW!zqrmX?^>KEk=!z=?uNi==DU?!r_OjRY%wvg%5<}A5-aQ5 z1<oPco0pba=b7)H_mVj_()GHrn#A$rlUt6u<O%wG+!k8wr>}Fr;@D-2x+hme8I@!Y zYgZjMZA`V?+^Qj#_hjlWrIt|N&s&~K+%r5G-RQr(W{aJrveGoGjUUsFA5BhjxOZ{l z2G2uh6jXPfcp0Glj<G-Z7%$hY3&$Q8+g@Gp?C75uheSq^Kc}|kCCsfAV*grI6SZU4 z<><mi5?@aA^t4HxJjB5>UCDE5&06+uSCJ)W*o$vu6g{cf;+?au(dYb;g?B%`6xM(A zMD#|*te`f(z}I^FH@)Ojaad+?G;Z01qN3&N7F@bI-SnlzrVXA_0gnR`zdG$*t$5LF zvd==lqE$0v9)JBbo#)f>7|FAHT1^U9A8QMn%$8=85%VSIy7d+Qtc@pU?pS})ZsX6m ztHldnMxHzB?f9z7FRSWMPnW}ld6y3-DD71_ayV+0MD~2$owrnN&7V%caVcNwexv#C zxq-r>kKEF4$hU}yPPA-blfB1StN+KI`~Uev|2O}rk^MLSa=q(CnZNed($)Gw|K_h1 z=l*|w@{jssKWai|Je_<01@l}Jmn}?k1-$nAb>~lr<H(#pp)UNEddaWpuV24EslMcx z^=^L;)2Xk8Z~b|>{B6~~_im;J6W_a)N3VU))>!+lPO|sH@~;~n$b>vh416n68F8#q zDMZ=0QprT)YK781-TK4V9~cA}R;e(%PKf)owP}}WMFwNF-;C>=+!m3M4|Y!bX1*kb z_u4(TRaNJ|v+JIc_ByP}shxIJOk&GMvA+j5n`Ma4Z~eP}!~f-*{)_*-&;48eZM|%{ z9sBS4>d!}yy~|VjU!7lFo%sL!<$wM&z897=%>1%$Q)GOflDds${3O?uL#ES(IcGeY z>y;~_@49YlP4Dq$xso@G5py!nJG#$4`G0jw^utN~ZRLD_`<$)fWG83!8FK53?7z9J z_9?shlmp81=H0Rl`9G&`4eNtrtNy0GU|Foap+9x^@%hSE9#+*H%3AZ0Cw6n6?YFla z3oLiAFBSHEzN_?Pgs|$mA0oGY=<mIM&~K6o->(YZ7=`2gKSLIWJ=t!tcjdZZ<&O(J zR)v*cv=8p@PP5JI@19r`eC=`5O|Ojo{iPdK=4u~$YIN=BB(I&9o+T`5Fp*fea>d+- zT@U5BWsD~8NK%=Q6X&V3;`q&d5`_{!*2-G)fAf&**)!*TaNt|NC&7VRKh<b03VX4o zo$<?;zE4kOyf(c}veSz_vvNnD)eNS5gM~BL53Ja;FhH{Ck(+?khX23LUj23Ts&wu> zi$;q`xy^!&TTLw7``@!VC1>*%OCAg}@m?pj;&+E<f&61RMO#+m)<+wx8x0E||K8gf z>*#3_cEm({S94myrxX$I1N|pX6|=6qI<;)pl4()}GLd`sFspBsTVC{F$tLAwzBx?= zb6tKtx#1w|7AwfIYN6U0-9=@oF*SWzllQM+np9XmXZFKf-LUn$ostf}+xfrjL!a51 zHR*mjMF~eeIpdQi|JYrqb4dIruiPi5+}1>XZ3UkF>m~BmUvqY7^8K;5;qTp_vJXE= zvDtp?o#C=0fA9K-=dbcl`t#r@hjH@kKd<}VL}|3wZK@Gs4ZKtqbwW>M=DwsjXK~x( ztAyWreY-p%>-av)x4SG)U0Iv@d&7s&Wy0B|esMYn)OuF#o-|{d{)a!`r^@VlvF-%t z&qMKb=1PYqxn}O#vGc~J2PaQ2|C?f6v}yl`>5KGKH~&n!P_?MsQTXZZaF;KxHNW>7 zaQSV!ud>SUPJU!=^*$|rC%sNJrKdFxsg2A2Tzk>{?RNG;>GLn9b6gbAXq|V}XVsZ^ zaSZ?Jem3--FaPg5Wm`}7#@&A|ZDhXSxBtkkU$r|0By(r>o)`D|mA8Cv-Ql+nB$6V| zOEs_*PjcjVGNt6)w1!zCS>2VL&+0cmtH1teQRHsr<dmxtF%Mi0AGmDeR<rVBQ}!qM zq&D9l`~7N7Kgyqsp3U~LpZ~Gb`TSsk36Ey@ehe?VrS@NtXQStTDWBgD&u#y$r#SJ4 zvKGt#<r)4={oa$V-`@Bs<BggDlT(<)*EtuaxIZoDDiY(Jd*w>3pU=snnn_1xj-1j_ zoo(@X>n{EYe~%Ys@jX5zC70hS>eRc!JRxIWJ@@%Iwsn{PPUzLO^5MP`y=r!+Moydl z<|USot-pNuGwIz1@zo8RRD7gQ|Gvf<@^Rvp6BCqf${o>jZQsXmq<ZBt^~5QMTKJwg z7=-b}6yz@{X0V&uBF?gxry?@!i%fFkrYz+p++k6<3=*Mp*Y@`QSd$bWw`Kh)<-qGk z%dZqzT@ktwpL^iL9X>hsBk6WmHbf=|c?vC`z;5GkI&s4WYa8C*RS!7KI{MdK{G+E? zn)=4+?YaXS*53NLesx-O#cnU3MkOugT3y%F4{JoGCdR&=+-^R*(|cj!qMTbcQ`mQj z2rHU>;OP+H-}fu4Bf!_M)TQI{hb1l&TDo%kx5b1#?o=wgC^|tg^g-rx-OOKa%ea;v zx#QtyCSI;OE#tJA=+ctv!gkfI>aI)n@z3EC(>~dJeLu&M|NmmdnJzV6h*G_&{$lTf z`*VBW>I7@r>E66kIlmzD@zjZa=}S}ctt0myRbRVe`#SqCXZEQHsrzr8(9WFXYMDKA zPT`@zknr#KJLkumb1a@B&*_zFbC%`$yQX<BFC}%FGk)7TyH7W$$!7M(JxeFHJe|>9 zR&gmnwYxFs*xoaY@~@V^f1Q$28njW5$@BWIS<df*`u$vD-#z?0dBd}5)@2_!|6gi0 z-Pdj%lK-VSgk9?MD*jSQ#ht%Y&Ii_7$(g=ha@%NGuhe5h&XClfmB|Gup>LaVFG%;U zmY$uvdDq877Aw~+P<50`lYTzEUESSsYr2r;$G6HyH!scnm++W%W<`-f`~=VMuA8#| zR-T$1>7uIq+c5QVLdJ<@yB=m}TPR;SRWQ?Jrli906&I6oF72PyYWh^Xx!3gS_LoJA zpFGMqrC&OE%j{$22OrM*@;=K`a*t^@kJ>)VW`%nvgnB=26`Y*yqvf<|>Cy9xIqDbt zC%;ePt8&QMaOLloR}O2Ix(9G<TXXB+!-pS_e*Ji{;;-D%iEpbi>yIt02|RY^%32Yr zsk?4mj-JLfZT+!5K4&~q&6drZy4=J>RK&?Sbbqqi@<Waj@2*@m>sMmmT}$4~XB{bb z-zJ}Ux-z5sZ+GXh^lXP!k#ij@d{3QEY^XZ6Z2McGvo?2s1+wR=|JbpIaW{{2c&><^ zXy~h#Gk35&UH$Ok$D1p9T32gUiizA<RQ$kHc9)Tej^*_B5`n)Jryduny;RkFudQHn zr)T!mPb`rS&rMyWZ1z)QS<27PQV;7Yzh<i|Eo7D09-5)*ptnd#)*;wy9p8fB86o^e zlRNeJH9mx#HoD)iPN99%zoQ3^Y`!Y;<jVQmcXbMl?WY&-Ill7lxm`1tM_zuEHtoo! zuyv1lZ13;zRujvg@qWGMJ=4j2!8*?*9+~k@&fF0<Pj;bvTA}b;^Q8?;57Vw$uj_pD z@nHOMiRRg5j?x_mHyxX*=H|}(h+ig0nvv-WH{bfbg-8A-@13Z+Zt000RWs(K#|kP1 zb9p;=EOF1XN@tp?VJur?T>N7Fg`d%JRVtt4yc}FCIX3Vu^xC!a&6+mDwNlF+I|En> z)f4oj&W3au_Wm~S;H+ftcwP95`K?jK(qC0=vmPDb*ZwrYIDPV+{!I?E-fS_m^uPQk zG4AQoeZKX55wGMnJZauE@8enZ5J|Pto^I{aTi(o_Tx@goz08!UA@gThrfTZ7*8ZP! zwY;fSwEUj$KBF6wMJ*8wA(k7;CeJqF2{Y5y;hrm;WHwz|ZD;bF=&7s)yBQ8-PIy-J zvti0bn_yd;rgu9tukz{l^B>DA;$Ss-8E0k^P<n)G!@hmBuQOar1a^EkSQfqfa@W$! zNA4Xl%HWb%T4})T?!a^RN~ZA_gUC%i&wpRqd35%JrWv=q#C@uAZC(kl&sqHX#HB2q zzMYQSrx$9tw0xhZd32HP)Z|d-{*P%Ak^9)YqB8DxYm4rE6XCq1OZwL5R}&;!i{{+F z?vb%K(Zw>M?=q*WEZc&`R=w|->MN?%*Zp|)<E?*yu0)m1guf^DZM|kC-yKri>>PNZ zXwd?@zaHX8(r31s9#z>=UNdj$;q*%(d)Db4lJ2$IW3_*6MN?c|v{thI)oE5MPOj+j zTxovd;L>N)EZDR}vmbBk+Rz@pgSYA%M}uI?p^p}F0(sZ-(zSop?AMziD!*}Ne`M{m zLw3IP^45QPqyBcte&#y4+2qTvANzcJUCx<qov>+P=XL?j8@3VG7aR`EPJF!j#{acZ zhT%4Mubg@LA;C`7!)W@lKSqZu_es_)pZRgkEV+<0pJT>_H$H{1>qx&`dnR+%qxF+! z`+od>@obmYH=X5Mw0r&@`za;X`S;S#2r;+ip|iy}r-knOZo)j<&$;f-+{c@=HgWKW z{i}a__VmqG&z%{sE$wayoeP(|nElIB_@9e&uZhe?%ikucWu?!agw=}eyZru=<Epgk zIhQsSWcZ1FnY}l9$GXfPnvWX%|MuOM{kv>u*fjRdR{l?}g+J*O*|<!yr}UoS?wJZ_ z^z+QO|K{A%anh#IJ9A<T->T;iRdv`GYMAyOF36O+<FiEdsPn>Z6S@D6)ohnf`DuMD z<mzp!n$d0)JmuXJOMadcPTCO}to`dn1y+VG7f^Zf*K%#-_RAt7`vvZEfBak9{hrI= zpW745*I!eUJiMPs9d}`uJ>;1#e0R5k@6^A4B_`SGFArUESTCitb<-@hLcK}5b}U~$ z;qs)8>zzBag>PJL+wq+HQ72pT>tfZ-FJ~S%emTSIm89gZW5P?nth#!<=gY|{yf^;} zYe=PCKks~Uf`G06e+Q{ul`n)gUFZDD!54F$Ls*G##%m4(rUtLP1_}3y_pc{kDXy6< ztDeLDPN6o0tLT^5{jHOGa`wA5sD~y!d)9M;uU%Zwc8zy!`ffwX8zNU4_trmI{N4W5 z^OsU;69xW#ZO&nN-u_ymWGVa6#;;#Z++x??l`bpM;jNlH$#zQL`Tidqe<e-BziWrZ zY<`@2W8Vyeu(XBD#wU+I%M8-BSomk#-+LS0x0V)8v+q$~^thorFJ;Bb?W_I8LtKOo z@@UM;GtW77L#A2UwD)~!=lL|TxY@_PALqXFaOqVOm$Z#Zx(*k7iZnm}E8e%;`4ZEV z)siV!P4-PcreV%Hb>?orfZ&Vq!Q284ox)pV)<3RUw>HhnY~^hC-iSqV&t%uCSj~-J zGU?*On54-r^*+~CG=esI^v}GmuuDF_Z^oT}fx%Ki0yEEt{yOes$-Agqz318?oysO9 zolp6fGKFVd?zQ}(Y^1+n=23gi^BkQ==2}1gvite6DYm}b{vPSuzTEc65rx%->N7%4 zUH`a7R&CABg3`^_t`3{$2&+g}@49T-byqs*{e_s8v|TS|@E(rw{K=Ow-DShQNLfxP zlT@3!RGp5*x^sWh|8^hwwAuDw^NYfJ>Gfy)`+dsHzpj+;U%qrof{B6Uxrp$rS=XP$ zn-sb5+Ue(g-nwh~sprMIbG&>`ZnmDfEP2hIp0xY%cTZV4y(wH%%T{^rTHT(@mIW_M z+WWWJ&$$2g^9`0W&7L;%zsfXLeD<#l*)$>ZDc?$2^^=F1jI)YAe^AwXBzb&B<9)&2 zPe(Te8VK<Oex0@NXL`=1+6Q0$Rxc0kPro_a^iN}HdV9Hi<hy&8vz9LLX0O$oEq3}b z-+^E2RNg6fui)}y{a2NG=}&RmW!dxoW}yWe3U@7CZntXQRE>nLiSj+CB*jX#Oa8w- zu{p%d+^oZXfBo595ewI?NA-R!E>>XJq7WrM<6~l?fI5f#$y**Gk0%D`9NkcV_@gu% zPh|B6g9rIdt<yfwwaJfuB)G@qb(7hD^GR->x&QtC9sby5T6TdN|EDE~94Zr^ZkjjS z<iv~0d3tXu)(hX%o*c;{Y1?NQn$fBuT59F2xcK_=;!Vj9KK|Id^ZtS>GuG~$P{ebn z@|oC|md|sn{-ybE_dC*NU+lM1GgU3la;ovH7YT0ZTQVMJil?mG*P)-hTKHn@mZz?j z_NmjBoD-ULQ*mv>6M?HClQ)|7yq|w|+x75+T-Ww<u-Hd`<?JlF_dBj*^3UArm-o_= zO#Ew(W@UyM-xT!nVyThs(X?M=Z+&Kt)}&wTmyKK>)H$wJGP2)%m-T;**S|=!+w+Yh z3Rtgb+0Lw4w|sj3*+W0leVOJMap&j#vA=qsXM2|2EFO)wt3+m|v`#wUp|Y6y)c2oL zJ}Xc4oFK;U{WRZBQ`zXsT=g?s_Nx1_I%@=lvSh8hx>m&MveUKmYqsxDTUsJDt@HnT zE9uuiid)zpd|T(1_~gsu-Y<a#oV}jUBssfU6s-fU75_=xVd0)(rR#il;sueU>j$1b zxs-8JfG@w`ph=~Zfp+)&D_=fJtO~Vqi`<)`ad*{0^&02RP4esQmYJ`7)uJEN+f$=2 z<v4j`z{6ZU|N6<^qPs3k;q+M(cE-FuGw)aUs{Njurf)NHpMKEq^KOwpSHEUBExj?H z>!z`~siDjHSBs{pcvReU3k~05Giz6j*=$diFyCj3bcGW_qt?$|KKtA4{zR?S?k9IF zZIv@UU+`q*T+{gc2iId%%h#O$*;;)zxajyUACJ6`ebc_oIka&8<UQvYR|-|iX8&HP z{IR3)LLmFoZB}d*hSNC?-S#;4WaVRtml;d`@bcB3dGuNE?Mdq`8FQ|ud}=!!*TNsu z|CEXSZR)QKGp?k+mv|rUo|CcvkS?#(z3nd^KRg(^WIBT*_cFuAq@d1Y6L=b{mRZ|` zczqUG6mBE&{4e|DrF<{GS<e%^axGI;>FF%~$7iNSXFZ6im>ZSLIy)lq-b9OSDv?6B zV-vS++GX{WtuA)Utta-Sug`6?_7gDMzeeUjmZXdJ?`vFF-tWwvwY9V)c+DTXx02Ie zO>j@D>dkxbJ-YGow`RWx?+Pb5Ly@43tvlNsrS_iFWHGw<_)Yufp5RGBbCsG8vYxU! zcx7GhNo7M`37>00PVrK!O-sVHI&PXgsNS=oHz<>}^_Gv)@&y5NPnNE8%afmYSN=kb z#gEO3`)7#n^;^QVa&qpemrnh2<o~|8vQXtt71x(#i*`thpOjmE#6oxDix-FT!)DK_ zUw3qKXid;hvH0#+%mErf`uA6_V&Yx({y<%`-oI74|9@=XD*rp%zHD86&EEfyU;gV4 zuaA$5eGxr*`Mfi+4~=%u&AxOpMC<w&N%iv)7Y!L}W-)|*Zg}0fMYb_?yKL{xYRiRR zJOq!wJa}OK&Z<MqlY1|61b%4tI$-%>&O6U{z8f0_tmj;J6t9S%lYJ{>`;^s1p;^pf zy`MhZpR>Q^U)x^3iEK?C>HSu7ueR<oSiI}N<i8oa4xMpS)Oz-~%Hl;K5BJf-K9VIL zXGrV!oLVkWCTV-#@!r!fQ5#Qa@6l3XZs9!opvOp$xj~&rE90P4<JKgP9Zz_9R8BeU zc^W&b;i_R*!}-V8zdi~3bamU+){X5?{+|>JKeqATtK}1Pc;-!>e~9&LeUY2z>!4}1 zC2i%#Z^~r%)IEBtQFLf>v9gT!d~MmEYs)I)rEgq}J<T5#u>9oLC3^Z2;&W~8)}(%S zQdeKochT@Vht({b4W=LTBc!&9+UiMM@rqr*u$awrQ*-2p-^uOU4X>Wud8Vf@yXCg7 zLJueN<Bd0$-!<`>Khdu7)6AV^+*bl#arZ}Xy<ch9*1qT<dw;>M^sByWn_s_vy!rLy z&&GG{bv53J3!Kn;C?zr7ui><Q$({?n3$FfuFe96J-9Lk#HP&|&)N=VFTPzgfStkW- zu`x@%nfNAR`3b%$nTGbgHxsg(ETzh)>X_VHAN_c4?9<rioK=$wGU9%2op)YuvD$a_ z62@9ncD5E}TlcyPF)P<69M~dnd3Ng4sXLy`vhdpVyec8V+A;pevf0}IKZJ$Nk58HM zAjE&+g5}lo+MDLxef@pug5`xDrf@aBy}38=#4ZODsUz=<Jnl|Qv%I%q{W`nH+7~|r zYJaLOdaS#xwoO+qfIrV->7)jwc!tcK9@>oDdiG0Vv|rh;xjd=;eS=oY=7`Rt=I8Z# z*X${sFloEZy9zG}{#d!+sjcNIvW`ag_zwCVP?oM`FsUebxuL3#YlG+=re%Sihwi_3 zd>l9XPV}m(J(p)yzy8Tsb!^ucr;P8a-_BX_eReOb)lJS=cRRx}Xs(*9{-Mx0j@wEU zRy<hc^)Q?J)tPPkznlxoxq9_P%t4j;q7$!75zAZs)kReG^#VSR-B+sT>=#vAb*9`y zQoCwz=DN>{(UAh(X|ZeHOwB6mcviT3_et|-Gm=$)_QVMWb3gHPO%A($_s2@9LurSU z<C*W=n&bB`rSyvoi$KKXhZgo1*PnYaap_5gg5NtnGF<Rc(mQ4x`QXX?3GAJ{oQvgG z^EwD->i>9u`NMrf9udvY+7IU*W2)5J)_J2!YTZfO=LToB51Opsr@8E;ntd6^kHXsz zmzZ<KuAFuAPl!&X-K9Aq{@ZiEYjB@Em~AmX@kMmvni<EggrCdO_BtZ{{zBEel@&)n zDTgcSJ$Ai(<kN}vi@9e@xF^RQ_CN4x^69L1bL@E=CVifwFJ$BPD|%tOru?Q?GQOg2 zxlfyCd&~)5pXRsl^!rbmsjDn33a0H?v+IJR*O82miCIQ&ue19vB;E0qUoiDW-^Px+ z3u{xpuzgxmtFG$vz<$NqogwV~TUgx=$G>T|J!K~$d{Nk~j#r)I&!exa5AUydY5sA3 z`i_e#=bltI^)Bm~_q=?<!{9uV)CPn5y~}tQ<{dm5JGuM%C8f|iem|#nTuE1ZEOzPj z&DcQ8m4BqFO?;eMK31)?P2ZV%&)On>=hTaz=j3ns6ZbTXjc?xZ)^rZ;64Nh>HZ5A6 zv&?XYZ*o!3%G>J|F7KFiByM6%j*RXZ-P-+``?`aJpUtuP!*jXJP^IYF+@o)5VjkFA z{S15ZKj}zq?$h<z?I$Y3<g_KH|GXu9;(N*Q&ldMhH(x$(&#HR&{T)6h%`2vt3eJXK z_4xjOOL_9tK*ON)4Sq{(Y)&7JFm~C`^z(K&gV^$Awhvck3Ul3EA9d>7{|OsI_7_jy zSZtr6bM<ZUqz#wn+l6&D%su@u>G6}*k2uXd`xj*=@~>ct`yW|wT6*ft#Q|q0PG{ol z@r;g{8WyHvaB1Fa(aG*iA!>);d`X`3{<!sW4?#KQth{#7)Nj^jWm9JM+P*Bbe|m%e zf`mcT;l>V|6A#>%-k7{6(5HZHze@a}dFkQbME^ttn9lqnbZLXoo7GZc-$n2DJZ10M zFsV9m^Rc>f`tLqR&SLcmeI3to@ZUcPcb1P{PrgPu|H^%2zxwlu1*`lTd@2KjyZ)a0 zes0-vfkf9>|1GWIkvds&E{{e3ALqA`<&U;jI}vk!)={C8FW*YK%sCfm`e22r-*bVC zqaqfwS<gF#My%lC4qX@(nz(59*8Rr5i7S#H%y$Yt@w%?=<I3|M!6%wuSY~iNP83$v zx+wCgs+#TK=F1ses_!#vj!7MKD$r;7euwq@_3HDFf;%todG}o0?03(ROgWeHj&u6j zeW$E&ne*)Hx0dBX+|&2$m}lqT(RF+M|EBuBIeG>5a~5gp%dUEHZeeoQlBL;G*Z=$E zcC6w^x!n6X4g7|={LKtMwK(TkOKZ7?o!@wvqkumt=uF<Wfcym<W;<2co<2yl%DsJf zjeFsHejmfD?dF1?3U?K`#%^X}b1B(=YeU@bij;}B#V&f>VLJ3~Q;XQv=|LxE1<n;P zUco%kI!kKxE~S@`j~&m_^Zd1A=EWeTSy9KA9P+Wdv-7RBZq><*V&$$Mj5TTBKDv7f zu3Bi{+kLoc*}hcwu8te}Yo`esA6T5SL~L;;x96RU%)L*#&lonnW0@d(hk5#ue>-KL zxi7NZ*xq-cBKu*%0ncMIw7)f!KdnhVH7Dw*ldLhbS=O;x`BL|{N(gmi8@-B}s2{m| zUfR`Fx7%CS#hHYxaB7Y-SrB>fXSn!v@6_Wfrw8tl{BNAIa;5i*X+MQlJ*~~QtmM4< z>HW#wt53}jIK$vqKB4CP{=G+=Z3-VYtU5fqM%J^{<x`%{18<&Ze?P@v_p>@J@55X3 z$a~|fPZ6Kgip4)>e+~TpsUqX^y+f1tp38rJ?oHvO2?x)LNB&i9aSd#rsg$zl_HFax zf;kgRTpfA@EsJ;QnlfIIXzmP?p6{vj<9x~QrcJxmw|E6u8A=>|`Eij?Y5A^rtL(mQ z+D5ruHOJ>`*sXqkUSi5ZuF&$SFCV{pX}o31;yP}Yn$_jAvyS$>On2J;V*BfjPb%a8 zFS_Pzl$dCBRCxD4{Wrhslb=2l|MUI(|07ms^?$s7e|diXFWVS#tv&3Y_vu}EQ|2eQ z<D{Pa&s_nVcORej<>bG4dZGs>d`h15_tB<(7I)VR8T#4RtT%sjr8nS%sYuqt#hpLi z-(lS<&^WpCz<cHN_ty$oo$UP;DqQv#PqlHIUo2?5X#epEw%(Q1%`5MzPjU%5mBKyM zQ-$-V`X}Q%5-x?6hc+9q7C&)0dFDg<x$B$DSY0L?#Rku}ma<@05W01$@%ujmDIW1f zNryQ4cRu@aF>3b1ns=T%E$-GDxU*-i+TUrk?)$QWxMNjU{!|P6_@38(n1^l8&gEj< zf?pncOp(cuJ3gti^jk?9&-(}BX+irLvnu_!{9hPx!NFS9)t9yMGKXkdUU%R8xi2Da zFa^I?J~wq`^1QQ-$K_lY8XRA)<~{i^x>>N{sjbyw@fI6<Kl#@m1Vz7Aq!&M2t(5U1 z^Tw(Z9J4*9uaDlq;50*L-;ClpS@o^umKs;L<g?Fz;+pY^C3<z*W6><z29*U2jaSq6 z$f~r@+cP`(=zWGQd*#^XJX96?#KO1ljc<V+pUL-xEwQ`b&bVIo%I)98S&1{MT;xn7 z56`t(UCANSWc%4eq1E<W){PqWhaV;%jaAhbin!r?b@{4`Jy(u=%I@0VKX1L+YDv@7 zwpkN6KcDp$o_kJT`s|Ajh0XDg{-)|B>wQ}BGG)>4<6&Bl_S&Wj&E%+Ne|@9-&N^;y z`|lFjUc2l9S=VdMw<=mZPx;L9?=oN0L=H}u?^61}=IpdixWkV_#{NY1hY9iZD~et3 z`R4V?STA@nZP7d{zZ-lpT{})>|Md|6sj%KiKVu{J>4PU(zl!b+eH+2Bmf2XLd;i1v zslQ&{y!Up3Qp~-M{8blsTv{$S`*`E3_KnFWyi2l^b|m+oS$*g6i}%0dO2n&UFJwJf zz;)A*L$B|EcisArKMtO0xzOM3Z^_iT#w%*>fp>0`U(Wk9;o>%q$5+;h&T(zHueMSn zjF0`}<L{hW(y!TGubwY#vT*vXt!o%!v|{Fpblp%2Iq)Hvd%oX=gqn$;a!<bUG|V~1 z_^H$Fs?}aK**SGSx2MG&y)om5X=!p+VsLU%q5tKOdAT81ZY=%0exY>2wsW!)xh4A! zT)jO#{P^`{TOU^~2@)-tTRQ1|%iVuvMSt=(`EAaZo3Y{c>*neCed@2xkBUrY;pbmI z>i|#NtejbL{#Ps1E<eraid!`G(v~^N^Ijdg@7N_EudE|>d(P$^$M4SmedqlP)mMk? zShl8mw#Ed9i<`aAN!XMb<r%7@AK6iQD=kH1lkdOa>q1*s?wfi-W#g2P+*A6Qp<8Fx z1oWTWyX@!Ukoiu_OpnH|%{F^Feb*#C-=D5IuF76hK4@H>{ouRr$8hawzCV}FOPPH3 z$ortbODvL%zb=_~^yVzd^I`H2W$Zte?<!gN=^n4|vEq`#4i=8ygO$sF&ageNe^veF z>&f%Zr!xf~lb=}qyXb4B#mxm5TQ6*mW1f5Qu<)|`9c!mgDR;5&xc?*OP;wAM{F&)Z z(MFp7r!49{_e}aUZOWEUTjf<xM+@awtHpcnS=qWg#mS#@QNEdd=Z=g!-y%F+WzQDO zxNy_=(J}kaLj2ZUZ@$T{4>mu%cv6IDVX?w{wvVmcX%CwscO;1E&44lYxrv|oHGRf| z|F)-97mEso#AW3zms~A;d7k&KjA^GT1%&M8yp%C{{QK1R2R<+7N#0Lw`@gKGI4x7@ zy!W*4%cf+f)tL7`*ez+-_B!qL>Y}?FMD6O2`>wigxg*!;ca79?U#=<7A8pcP@VQa3 zc~?%5txc*;_k%B~F=k73o^t2u3kD^y>`rUl+GpM(zUsD9X?5GG+q)v{rn+|2O;!q1 zc&WK0C+vE$z?RCpcD-xPHa*+faXaaT)}$Sgb8VJhIC{iB^YnxrS1ao-RnMRQ^15(m z`6fos)2)$Jw~D+vPHsHof8|fsrQ<40$5kgxwSDWh+kd{ErwEVB{^$31X=YhI7hgQR z@pXy!g`T_>6QW8so_y(gMYh(IMfiAPXv*TiA5&VGWn_(aOin32(SJIqH|OZDCqMbU zR6}mZypnmKG-*<<k6*x|XW`ENhEKv={e)`$J$>5xHPv4x&bs?JhQqjgs&O()$@Uhe z&tFAt4Y^*rF0eBD)^dD3D>LVUJ-cmv-itg-dhn$+@o~2<`)R(s_SzK&FE_?dem`sG z^5m}C#TR~MlzbBO<TSRJyW&dS4IkdL_oZjAExEPDEQYzHKap`0i>*r5$H#`&&iR|v zYUcDS9-r{M*yM<2{}wY@@$wIAo=Em@$au_OJ@@~i=f##U)0Wko-jXQmCp&#sWzZf+ zwWt1>?;B!w2t5w|_{MANtWUFj%IE4O7k#SdJ-8sqXO0Am5`X@SfVr%bew>{q`f|O< z{G|W-Qj@ZD>=ZUmdTuCl^Quqt&gBO?mI<|g;+8Y&-?(C5nv{=A^Tb?Lw`Qdkf8H_$ zRJFFoHYIeHPR;K)z24*Ej$Kw?1-E|mW|I4Q<d)<VedlTCOPWrYw7);<B+9hRY|kYH zsjpYAOlFJy+UeJNZoWuLVd53}rWwqy{5%)sIGP+S+{n4bX74wv+idJw&4rHbJWo2m zn-zWGGhSJI#?JBRq5X>*I-ZyGeVa4)&E~=dIpv?9cz>&06Y*KEeNL+Nv#Pe9Q15-+ zM=!<d#OC=u-W^%R$Zf%MXX32uIchQ@ygg!PFL=+4U6H-jgI6uceDUs{YsrmqMkOaJ z)-RgzqN%AjC^PxfFa15o5{jAaK0dVE8^pY1$CZ!DDR*~#5ePMy#@XOEYj(wi&3%)S zdyn&9-qX13jKx&L^l1|wW(D(_lrLG@$J%?Eq43K7EeS?_1(hz2W_L}wEO&igviH)2 z^c|XtS04y-1@GGA-x2UfF1+fa=e{Q);(rRS@_4R{Qu%m&`RP!uC&}}LvX+bXUinkA zM2WwAkHe871#VWUeRaIkj@hO^otjZ#ws-36ibtW-?&K<`_-(kJrnmJ`ZIqtT&uLOu zf8WY9dHeff#k#E9y@G$Hh+J*=JiB0Ja9vE(f)wV~78Pz^Kd(j4%-wy24u%F!I`TnS zzU%ZY<NM{a>Wk*?{H*of%e4M-TuHXXj#T5i#ta+t(B>0ACq(J{?B<=jkGCqsT1<y4 zB)faAD_g+rPbWW@gszkQC(xR17i*s0Z9H|;s)_EFt9N}5ab#W{Ges^UU*Df=n}uoI zM!tVuVJ9vgl$exnnDa}pELuG9O6Z$!&t!I-KKM5NNz<>|xt_&;yQ8c{=N*XtSC*Y- zcV=GJu~#`#_g`oIHGMkW-G1M6#aaJ<?zNHrY<FOK)!gTd``p_5#n#Tf|8~ZPoHKH> zoCC__e5THc5YDeTl)d|mK=zC8?MI(S|2DZM{rZ1#Vtt+Oqu+(UZanb6cfYrHt?ggg z`T2P{xq1H+YUi;twK@D`Ecrk8-2ZFSt{(qwG;6kgnc23ovbtM0vT}69ewBZId57iP zf%w}wdops?fA0SpcG~srs;d$`TG9Wjt*w8Qe?I!I?PvJfpJ(Ta@2+03ts$lT>;B(K z`JdUdljptO|NlXQ!C8ItcYmAy`=9^6z5LRj`s{=MpC9^P4`Oj&yMHb(IsNx@&@#^` zkH+^?{xAN#;MLdvN#*4-|L-%e+rNA3Ue4F`>FMd;*|W<J{ulrCzv;jJm;Xo8-~HL| zC7n?8w?4nTI(y-N{U86E{-2-xKmXsJ%{zB*-u&P{_rLx3I{&P?W1sxv|GjI^&WXMJ zpTYFz!RNDg_nw{0`hWiMcD)VxTYtQ}A9lLvH?w_*&h5{CI?Q$)UaI<$=ljG7p*n%G zcY^c2zY#Fs?%KHS^%tu@*FLt@{`?`a@AKshlLeda{Iq2IcO~?R%U!Dnc5}}OO_%Gj zQsQepy?=}IbCK<dudlhDFWalFUhsC_?|k)$s9kJ35|n;3uU>ikp)tG44c?!sp?j}w z{%tOMd)NK#@1zq&N;Zb%K0UsF?cW>mzc&{Def;{by#M$5Jz0Nl#75Tc-@one!C(5> zPv2{oZgju1$T`7qNBPUcmo5n<vL1WNQWCd|sd}n8t7`)P;b(2l^K7#!XLv52cklMz zg&#LR-u^O#c@|%tj`c!`J%{9kbRW;%zDZDUbqas=BdNSjz1eIk{hyDA$oE`7B>X3{ zEqhVW>g?@_4U5%|?fbZFi9Va|YcG|a)zZ@ZM@7QSHEx>4?=DesQVe=~{B}s;Lfy^r z<~bidH?i$|5P4%?@vpK!Q{PNIELB%LxBW|pT7K{G0*yv#;|^>2e97<wvlCx@NfFrb zJ@5R^QY&4XI|gw#D=Zt<$^SX9!m=d#&W@P9?;rN=dE_|lfNS=Yg1s7HiyoBL?8rad zGjSQ?vBwToY<~<FJia{fW)e$=`K-(C?@z18nsX?>GcLbz;p7gbvhA<G#cZ5W?ETYG zdb!r;y;3|p$$yeOle2glTw^~UJa@n>(X>1&S!&UT1BI=-%I?4I?efyhI-&Zz=AMK2 zHRondK5eDzop(c=E@(=qrzWYngly;dlkg%@XBH!OQK!U?^0EqZvH22-CYlRQ{<ymI z%0oxj37<C_-7)48jT77;bI9;OTr&UT#Ir4Wh77g8Di4-C7xcR!^yt{jBR9(;!~C@0 zFs|C3=f-)Dh5M^Q7t{AN3Co91{$$?SC40WY$3yLj<~F7pd&3Fp4<(at#6-!&D3^5? z%v)EasN%CKY}*UV1uNoJen}lIT^yyObwa?eriE)V$BwX%7tBI)kDQ8=lb1PIFwN1W zY}!+4F0W(7UAMQTKa}oyw75(vqQ7hJZkwHUd2{z$AHK!kC~c{`;P@N07pCi2=O41a z-ceAwwO!<1?2Y3GXPfWh*9f`8ZW?^2q^Hog>14zMtJFo4+oX@bc=)>6yJdTAI{Tj| z+nc?Aevoti@Z|G!^>p^>^@op}uS;iF4vpI1@afs^*ONEz-&<4sPbl7Xo%ybpKh1xg z{rWL}{Zr|lPa^qGg1@?KTaZ0pPJZql+o`I*{f^6iE3K^4&i)u3`~B?CoBEs5&VSD< zwXIRkekdLL{KuQOns%<g`{u{U#?O<vVAGxwaB}(eKORnXMQ2}heOcju?#hD3LoPc% z7iV!tF3or;a>7G|_qPN8DxH46J&z8qEPu2z@B0(+k1vkx4fT)TYiYlr{qDT{?sWI( z`SJTKkG0Fn|JbHHPfmW`oKFVUe$p*l8{WNmFzYmv{{{bb{(e`3x2Qgy;orZ09lxJ` z#g#(|SKmKLuKTn-S<Pn81Lw*6_E@abdFZV<QQ<4|tf*+8R|gsYZaTU?{L5<Xy1!og z?K)5X;PySd|A@5`YqS7Uv-b28j2p$HKTN&8MeW^@B#Rx3$`}6lD*bnt_<j!FZ4QSR zuWnA=yZ`d~`fkmo_wrrd>u2(qC-EH5@APPYB)hdz`BshRgu5Ik;`S|zFQ4Qy!{vy6 z(`UB>KPMe4SB^ZO|K)Yq1f_#F#S7$wbaEL_uV;C_d|!&unWQ87O>1-&tQUvbTs(Du z<&*uXo>GC)JufB{TobeS{Z;ns2ZeicFI&g|Nt&j%pw4&yyCdtJrQ)rpw47Gat_$Rs zy?9tMaG!eTyk`qP=bsdsq1X|BWw&xwx}L(!1BSiV1Q*x3s_tI&WVQX}_4QrxCj7C6 z{OdVht!wxtdNDox!gGBUmi$(ZKdle;h!*TyX!)ws^4HX3-#z>K#aA>u4S)51@{9K~ zq6%HK_g`A?|LD5D$*pL^Tk#oTc}LgmS$6SW=f!=?{=IXlU%zs{^~L+yhaSv5@F4ru zU%xN^W_>79|L|#6)ed3XITw0%CLQxzu|(Tz-i3@<!&}0Ky0t$PIc?a%G)=hasOW|{ z0sQOUG+x`SeeJh?$osHs$@8?1eNV6Y?*H-Kc^CcvQ$#!?eyMEuqJ8$hx?%nPOA>aS zhJU>N)(ZWN6;fqynpD5k%>JZVX3hL3IhStOcW(Ueb>*{X!1?tii~N&Z_Fr1{%Vg4` z-qu+^T$5jP8tz&6uWHeLbDe)nHY@@8w#xbO>&}mR69u(e)xX{o-aG%&k6%eO%T3z$ zJ&|hZ+;`xJ=EcbP3pX{rO)oyvXSuny;mwqUm)sG4oV#lq?*>1Tsy%3`m${`;;;p9R zUGaeV7jM`aelvb`aPsT9D~=0aDRv8}W_o43NbdZ^rg=~IRJi}GT(sZ#&;oUX3b(!0 zi@pm>HESO$sO#AOXWI|g%`dxe+ARP0GpXkJ5#QQ_zUMic_Z@h^y46x3H}1j@wxk;I zkRk=IeT&LtfA$&J3(VNBaE71d*?*_aKlKe~Prp*FP_=)FAZwD#^bjKnudS`3VjsH= zB)E9u0^cuu@we-kT-V0<iy6*_x3pg=irB_nT+@;iwk~7KLW#Gc7b7*EnrNp4wJwU} zJh~=kqn7HiayO7ulMhW&-caJI%=NS*BeyLnH!kpGz%-RtoUC7Cg5OVk@psm>coosa zLoO-?g}yU7Sk%@<%7?tt*WUj~{9>uf(=V3Vok5jJS3UnMDxX;6Uf{-bF8ffr%7;qd z<o+W!)^j#bJn+D@*Gy<}t#<%F>y`YKPXeaYc(3Jg)z0tS%+H$szxP;y{;?0z2P^d- z{ONtLN4#L4vX2dikBrc{TTJQeUxbJMsdE1+=dyRdP@En2o<F@+5}k7Y+*I8cJ-NTK zy}n!SpI`Cs_Y1>xm!{8odu5BJ&pheeBU<(c_I-0!li8jc-8K8#<ZE7coaV05D2=P~ zt~?X>=Flna;~NirQq1=+TK`n9i|ygRUsV<|3qJSv31&6#y!D~^cBzK+y3^{}pK89D zmi=0D_x+nSUk~;jecONWmcoIx6Hk;Lvd>w6k+-q1)#jPc;p>roa!*f92y-}d_aH}5 zYQ~PD`)Y?*+wtZ0^ST~meYDl*gwVU?U$#h>*NXpU^F4mQ=dsZ*oz}-n63;oq-|4>G z%G7cE97FuXxQ?2Au|^MlMfuNu=Kow<cXHF(BNrx%X2@F2Su_8=aP5X>Kkl4ovk#ry zIU_>osNYu>sp5dodlxAC<ugg%v^cfUsPLc<TVbY-=JqWXAC#&iSI({c%r+^>eEZFN z3I)5~rT?{-xp8oRRa?0Ii;~{>fbFIml&5Gv-e%U;%=7QG`i#;$Wg_|~oHnhn`1j{Y z&!IK9-2Kj<TroHBPfL?tkZN_^?Y`nw7Y;5qRJuQd-H!W^!?FEsbs;-)Usd^W2V5=R z8}wWFStO$;N3weLll<o^n{BwNo7(Qadtq)~l7DBObnmJgN1mIVm+vYwdi<uvZ2z&G zZ~i-2StFWeZF~JtRozX${nt*7c8_TvWi~ebSmYCM;s@{co{P_X@;dLj<llI`^~gik zv>5M|x%<63+Q0K#pL-s5{$t+a-AxJ{Hs+filrDcDyX(Q(*x*?TEXwy9g+;|r9of66 zvE)wc^GBYqe}DRAvUq1<3B!~d|5UQMYI;{2bKKb{+Y@zQf!gXDUzv~Z{Tg-VCeNeV zqxyBFZmG?a&NV#i(a!Ve^V{^Z#YB2He{0l<Ta8xxZBq8j)=t!u*`)ulzl3q##EI?o zt;H`UX+Mn5JtzC(?!CwcbF<#ly@^p3{6F`7cB<5Q=i<N0_jAwbgKo!GMujY!A~s#) z<eghNR{h_+wix+cy?j`gJ-e*c<b?25ZN(<m#GdQdHm!X8dhWHIX9DKkowQwM|9;ho zb%(ZZy7h={_L3%<S0@6a^ykX8#lL>kdfH6z?HS?OSxzg<8TTnNc~0FavR=r=R&I_v z3**O`YzpifoRk+Z{ChKFPtWS#XH;dvyMu~PZ*Saq_rQ~ui5$Nrc$VC6DPQ)}m#=Y8 z+R5qP6<2mWpK7+pU!JGl-D~REGSw+T?$-OFPpl34w|&b+t@W#V538&{qRZT3Q@U?~ zv~2XuXqQ-x2!YMqe|xI$fBF#O?9-`{b?WDvE$zt>B?qS5?TU4qVp_aXHGnI-QTS1J zlSKI9kW;g#a=Dmi>`CtTn)c>*+`821-zF$YdlX*WSa<cLb8Pjx<7#4mG@mg^oD#pi zTQPg%1Gn=he>#dSp4g*$O#4((=gFUkn~ZB}=RCaqjPucw*N2v#?Y<Us`RKmO{<=MP zbu^SepE0;@*p+*}Q{%{)OMTZhb!MkU1hc&mH`0{Vh_`LmI@ropdC*2|<&mN?zR0{; z%@NmIE7Ctyo?M~Rq_cCvd|t!O^OF8k3Kj~=<ew4E-8G|d#-Z(VZanuq9~{Xq$9>O- zB~9sVmmbHgYy1C8{bG{{inaXC@O@uRZO?v@t8R5E-%VDodhwvvTX(mFV#p-U&nq_1 zTCm?H$b0$08REO9-=8b}I8tLjdt;)(iGIEX2Q*49%YEqitLJ)fNAtINHmj?GA00Na zj@fUuIELX%nrwM%klIA)MjOEsXL8eL?$T{YyuWBd`QH=&a_nANZxjE2xA3w5p%s^3 zS$zLA@skyQj9rsOtLee*s;7>y@~ZJ!clt=*>JCumG&cKHv|-(=j4gXum1?!R9<A<I zFWlAL{myvL>-TZ;@j*T}nNJw1Ydd^uNH)*qxff!6&oSMIp=Qm5tN$6@wQm{4e0(uO zUcqddu<|+1hnHR$q!}Jtnj%)IecV^%{j(D<g}6_3tkHa7a5p+Jyyc(_SI$x6U(9wk zcNDl<|A}N?nBByvk~nuwsaSI6nkAD=9}7ujMpTpv7J7c2bMdF*M58;N;wlF&N%z(} zdIp$ea@_OT@bcJcr<tM78x<uFg_V7jxSg^jK5gA%^Xtc_r?X#I-!Hp;o&P$^hc6bm zf3hfgFZ(LQ?cu%<)dV-?zt4Vsdhq7e*@Is{PRx63wPEjsH|mQ!KW8UMZ&}|VUaX^T zD!R05itIz#>&d-p*%j*P;m4;dF>{M}&WtMk^DJVCcc8?nqJ76Jgfdz@B@b6iEm>TA ztF6V}C};YjDG&Sq)E?V^KE+Dd_2(h^pTF0u&siz*=jz_+FP-%H&s$D@a%`_7ry7He z#qB%CmVa@zvEKP8Bkz||u*<o=id%8a`=@O#{lqPPWPcI=)XCF6tgk7mJ>kEOKeeeT z<9~17|Ffd+w>*j$yi<3||HJwUC4s_)hJ}v4hvgNEx9vQ4c-w8w8AdOEtt-3bw=Sw( z-Q%IYCdV%oo05f>yk};zuGcsqJ-=<$v8%VcyUmX;Kc0SFw~x)9bA4O0<N1RZ?q%CA zo^!ELZ{=@CjdSPM`JcNtYeK`;_f^i!Qh_asLiwg48ru5)aZ<V)#9zB@SLhDl{*<fH z`E*rjRZVR{$$`Mn>)(C|IU=)K@5%3L+F@LNArr%c><^^XS?}9pWoa+G_RlfSx2ps{ zZY%xQHCy2Q`Q59I-2AvZWTo+Q#n=yzKK<A}`SbRdX8KIe?|p5T%#D|ciF=(?CUCNx z!(yLEz+>&$mv6lleqV36HQ6{YSmO6wVcQL-ABQinohvJ4T=25Qv7f2g*|$;4rFg+T z>B|*$Kg=AB+?BHK%<u^8P!HO}$D3re*P>E*@zQ?``EM>Pabaaqy=Wc#dwcWg$;=CK zXFLhE^)6%3s%i;8D|N$W|B)lto6SFNdd{eJ@YY_Jhm(~XemoKIIvsj=_3qs7J+95c zRe$u_oK61v@FX!d+SR1$HF{5|a9<lfea`V_Zv}?J>y@G>rpU!id!Db)-!Hl){GUOF zHQSu&$LlMrizJ&L#5-T;;o(@(z|eRvQ{r5F+}y=7m#&`AcancPag}~|0Q0BZj3r)2 z7Oz<zz{B%eG1#`ElJ(Hv2^oJMur+VIrS<aXudhD^8OyxF4O*>ue@iU;z@skpg)8oE z#j&Zv^Ip7Om2&IsY4eWwq^wC^C+}FjSGs>`OI2;nk6%3=Owr4d{C=Nvo^&9r`zrUP zFKUhgmYkbDG_oAsX?)K4jR@nqj|uIEe)4=`+1K1C_p!G$!cpG)!}RUP=gjrL>Sc1o z-1Ru0{0u*LO|hb#hmBY5T=>WIknxpC&X0F*vW$Q2w)F1wjAJs3PQ=?+R2HayzJ9Vj zWS3#2qq+N%W1ewZGxxbThgh+{zxB|X_1jJUiKd)hZ2`aLi^#JItTrl%X}$fPpLYf4 z)amT&GrX)C@9NGHbdZ_$fLl11zoDes_VuxibNI5X4Q(zg()yB=QdQ8qSMqJ(nGcsY zo?H|5E@fZx7nwy4{EH)A<mP0n#ofOX9<*F~>Yc@!pLjm+-J*K;@RsOV51+p-J*)9O zZhNWt*Xlz4?3E5*-)IWY@S69*?U~-C{F@7AwmjEA{6IeV<68#(2a~sVEd99Q?8WVA zqLpe77R%&mXml2_3AO9o<+&Tz{+IccVOzjv@686MX2s4q>U!m1<I$r`3-d(g?!PL@ z9F)#uGgs(9$tlMscB^|k<1YSFSodp@QK8i8e_IT!bUgFwp5%K!Y5C?~vm)YWO@rj4 z&o|rG#Z8`X6WB2K6|1X@Ra4-xJF=cnRV1EHIb2<Ht|85GsoAZ~MqDEAHLp6IywkCf zwPVxqX-%cqw8Di9E^z&6->{(LmYwDdldbcE0^D-vKbd0q{g+x?$;PWwb~343&egBK z+Z&y9|Hh-0O*zTc(VO4hPt&UEY|%|tx1INC>WR;@-t2J>xYy?QDZoqqi}(95ZSKo& zRG+)E`bzMH^zHp@aqQ@%{&eopVx`~z#CGRQU8GuBaCnJ&<t54EZ#6s}TtZWK98Er> zyM9;E%tXH9XTNkOe^k5u^Sq5z)g#dvo#D@mf1mr7H~I83sVA#Gulg?Rej#knnj6su z+1gjn&J9uzRuF90W#!$eG5KoXhiR+MrWY^!-7mj9Xw^!VR*~pwQ`#eCTu-!3va>V~ zxBIZ_^6yt#u0cEZcb_l2uyfjPx2Gxde?RLyeCX2jd*8#t1ovK5>GIvCt)Z2wrYRR6 z8$WMDy=lP$*YIEA{QT?q_$$2E=eFnWUVLunuDrQ>YnAzS^?0aGN{`#h$G7zG)z8so z(biELuU-7Ox_Nv4lfoI7)<mB>P-e*NKYe~fpk~gA&hs-K^RtE|p9v{ryr2Ei_c7bu zW6yN=3BTW3!CjH_vVtT2;Em!(ESDOV2Pk#whkoC9yyW1?vyam@Wyq%M&-lc7=Zu@( zlche=CokR9ykqHkt13latejK#-T$aN|F`b=U-<Fos(1gH7P2}iuXw_@q42x?yLU_9 z)!(^!EB4NR)BgS)(XZz#KGXSpG|q*ESE0#G{nOK@(JxI}J~uv&wXD$jXL#9*S32|0 z&sTqZY&<kx<SSb_oqY6aL2iUg%8rN9cP*`+A8d;AUw3Zp{BLGvx_vPXOdtBCqvky> znbTKlyy%_oyZG1NKK)X!WDVin{`S?h`p^E1+%LmoGfuMdo^(6RcJJ!f7d=U9lpp<# zi`f6L&F*kebgb7NzIJAbS}yt0TP88N9uWdv>Bl3*Kh-P#2NS`c{u{rWlJM^98?6Hp zKlktbnxwAyKc2x<@5z4~yGw_U9h7fZ*ltn(I^taYCy~?%R~j{ZEu%H2TIWswBQx>n z^_qJRJ5Mn$?+q;3H{IfuM8131U6a;%s~(@vlW2Xsdz!d^;FS>m^&C<UuR4B^C}q0+ z*^p_XmuN{<k2&kKw-+N1Uz&FJ<$(={Xa2ICov`47Wb582{=5=)3D>*q$KMA0UF7#C z<C9%Z#@+UtpWEY>FL)bXSMa#Zs?U61?zg5%r`UKe-zyZnvb>CctM+o^eW|<lao&1+ zT8s5;(37j7PuTsozCE>~s$@&zmf6?kdfzj2JieDJ?d>clxo&H;!&Qbf*07+DIt@}> zpKA*Er+7-AOx=}xdG5Xo`|95x+SEIP!NJhg=~?^>36}#7Tm~XfeD$L|AKm$~TJXy2 z>F$oV<-b{(+}U>jJ-^{Ri=ZWWGRNhDcC#|b@GP`xU6I_s^kmQx--A(oSM^`K=u&Lw z{BFU#{!hYgGq-PxLz~Umj`lpNo12kdGyn1z7B)_y!lbyjg|<Z+37lp=Petx?v~M|i zRrVX#t$is5r#7f+X>fjHJ3f7<g4nIwhyF$1sK0u%9(qcI&YS(Mf4AS;&feU0XMggW z{b%2bOF#L4xA}ir`G=p+?tMFU@6f;5i~nzbe*fOCdv7mI`eA!ucD7R)NA=-<2`YaN z$o4FI@I1zC-+_wh;fymhO1n3o<GOpY#>COKQo<pYHSucY{@v%yldd0C<SVr^TsY58 zb6?)y=Evqn{f6e}lRX=k#>xuq+F{Bh#j|UQWuoe*Xc^|v$&9mpvz>XSd#`k6)MSar ztG0eqH>}%u{r=Gz7p11=bp*78zV5%a?3?RhjRTi_Bs}j<4fndgc=0!x?(+{m)=2U; z%4KXa4GT+N7^Gx%Dl6*!&#ag)$3B~1zZ@C!$Sf{AX2I=_qpKp%s`XFkt~EG*NHl!y z{|rBSF1GfnplvHT=Sm34vn*_~h{|I>uI{w#-si(@w-*X_aW`DNr^s+Wzh(jl`-$Xv z|KIfI=(VwD=$Vxp`lK|tXLz3f@ny5`x2>~2CAqYAh_Wg=EA-74WYcI{kr5$~`)RMZ zw)}m~pUrkWs^8|EK9^d=wQR*rk%kU2`y;cueM5^DnSBqA^*6Jh#Po#Wc+eKNm4yO+ zVnKf$XB=2zKjFp~_8UeY7q{iKg&Bz~6wzT;|5Pg&<`N&e$c0zGkGILPk;`#6Z;00( zKi@g}EsIuY9&5P&dTF=;&(fK*@)UL$=}Jt#)T6vSg}J4U)BJBl?A7O&Q*;CD`ZUXH zyROfR+;!*Gl0~1R=Tv4-KA;gb%hO`DqVuuaOHNNp_nf38&$D!;7N_Q=7Q1bo@#a_F zhgOzpzE$r2JS(LtCV26!w^vl_^V2-0?21r$B>QJs-Hz=Ap&AAj^YR?ppZ}KO={&gN zlZ4vWviQ|SOIBSm%KN+W`HRTaUW)_Inrh@OQ=I#)@Rh7}d_r3UTgnx&-E-!6oavr; zjj3dIac^%&Rn9*Btxl>tgSI?QDLtcb>SUHw;FPmEZ(3JtU2Tawm{4k1a@|c=D<<0X zaiXdD!PGYs>*OZY>3PO{5w`rhAx%RuDbmDPFZEE^tcIvxo1(Hhj;z|scW;N?zt^QJ zyV71o2B%mSIL%si<2%Rk_N$@BhnkPyP$*`N<f&b`HelL~d*{5A&M|9kFumNc)UohM zp7qVTyG0Xh4nOm{UEXB2p_NTQ$#K)I4Il5D*bAkFE`EH6CqMgc>ZVmw)jqJ^{yX>k z8I}Z(&$7#Tr(B4Ri#_#lzKz=9C7Cj^^7H1%?K!!+p|c_&F<p7R1N*(aqxY@$URaso zP+{>=WwGO<h)V@e&a3IX{Sxync0Fs5=&Y7}O{Grpt@fuEeS7|B5yO$Tug8~V$?nU$ zRLT1%#AM05bvx#YJ_^?Jo)&4~x!A=fY1?^~ikiy0dG119bsx{Kar^mW)zZksW0Tt^ zZJy6>I4>+D@7?*ypXD0Y&XsD5yDD+Kzwg|aP0u#0d**fj?;4(`N3N*9GHLi}s$#rq z?Hgw84SNH{m}l^0Ki?9Sq7!v2L|lLN<jap&ziz(V-ISI5+_wDPatY2wHA;GA1+_7n zdpD&Y|HWIHb4hm-hYC-yjpK*YJj*U@IP9UKxYjJ;hv@~s@ZdR4TR$H6(Jgf{+4lZT zf{=;aKD!+<%A97KD`zu)yY}wgnTGqx22WBp{4XnrWU66U7Zh3gZ$%K-&9X_6Q`>p7 zpBwxy>e<g>a#G}S&=#A9UA#M=eGHEbC_JnDIO^1VZ_ZQAvK1f1-!KaXcK`jG%=-MT zy!NuGS__;lePrtvUi_E0;TzL3r5wY+MR~KtbKIV4EcD#W`P@6wS^NKw<2Sux9;zL- zzvF*QD4yN<c+24n7n~Pn7x_-JFn)i<w)^k>w{ySzdw(tIf4Sc8{q`^a-e0@6_wC)e zcaNR>cD~yF?Y}KISpV65ua`de_U)|KrGLM2UH{*G_wJoP^LaP^-_89$H#h&#ulslJ z-Tr;>R_vSqdXMVG{?zAvw4d}}AH<yh<Nwk1``0|&xxZiP|K`nGw{M>P;J*admX7~3 zkGs2VTHiVO#`m>rk6pVYDQV)v=lzOT@Z_bd8~T5XB)s3Vr{(&!qZ+$D+rI9t7C!KJ z>Git%k<tMYXJSQo5B>f6wY|N)?KZFU#SaHd_q5&3yK&J<AR?hT)ikGh?&B7tZ#=&u z;t#FJ+cV+m6+R_{S@#s59X)Kye%TPuS(WSJ?`%Jne@ceu&9}M9owHJ3apo{enZLR= zKR2JlW8=1lGsnZ+N;q?FUdcVopLhLf?4;ML_T9Yj_2bi*qIZ85SJai2G#$SX6It=& z|LxU}ca>Jw6js)KndY~AW$?<y!ZtsiJ&mrJbn`*l;Y$m>l#-Pr*&c6Tb(^;K17EZM zhdp-Z9+fuLonV*z9oHVMc)O<Ka!V&`UAjm0{F86x*IX|As54L6YK6r4`^)}%p8LM{ zk?iFQw_55zJ73fP_B{U+kkw=3S|+onZUWN|=*1Tw6XV2|s=Ciuo+Etl;mso#>KE-@ zGs~#^vDt=;;wK}|GWoMMSZ*&nZ?#M>_yDhM;jBQFBJl;GoU#kJPpQp%Y@?#p6kWq2 zWTnHjKYaU}0~775Of>GOFI!$>uJttO$GxCi8@WVNirBUsXD~6~Z+#%e)7;1}vMSyA z_-9pj?WpKwifv(MW1p)1VefhMxVDhx)Yl)?b7dBoJ&SbQ>5`o#Et~x%mwyJI5aS_1 zzT4$Y7j}IucrFmt(6yp|_OBC%?l2n)XRLk3lwz{>;auwn);o7Kd}Vz1$5DLi-Cp_d zmC^DSjtfu8DUe9)vV6Mz@D`^2$-2&$&HLCrvUVGM-5AHS<Fn_p{C@>ES2;%i(2a;Q zU3u&qNBQ@>^p0HiX`b<&ZF9~WNcptxKU(<puE7#kw=bu=`<4~!aDHaxJ-ub(q$Lj+ zWjD7x^#8KW+xRQz?l-?>w`&XKA5vMkBW}03$`wZA1-)D5-9Eng!bCZz{nEAyH@m)= z`Z%vS?mx-T<T&f=N&2OCZ!fgaT+?ly{e=JRpJ($Ol3p&nd9P!BA(tqV*SQP(n%#Fi z{L10k*7)6MWwt~?l2T#t<cNpcj%F-LdtJz)a?5MMV%>Lq2a~x9ei~TiH6CKxm7v}> zLuVbggkXD3+YPzT0#*rEZLD><ZQuWS5Zsk%d%#&r@T32doV_fLN!^Ld#1s}s@$Bcn zwj%ZPAG3q=dFrCvUpBPd+s3-`mgYXyoyH5eCofj1PCH{I@~HWZepkRXAvM)6oy)Qe z44!YkEB{5K#Wm$ZY0AAjjFuDcp5L&d`rqL!yKOJl3Gcdh+UZE^Y0s`h`!*M<ZrD79 z%ZxGRWMkqQp=Y;+vR{1ItK~BFO!7wWS$Q$d{N;JS^_nvuwlXVxZb*J0*y|#+Ba5Lm zX>JtXnGX3A@e;Mio+Pb%=CW98?u4|nZRh^V>AI~rCw?*If=|>wm7m$>$L75X6WYtP zdk?pNvEN;el@be-W<C-w*{;s&!hA2IqE@}2N_ki6Oo3|VkoGTb8}%n;Xe?Trz1@@J znsEth>mQK`9k$2cKMUra_gu4dkx!TBI@6<8Mh^lw#JS^MiE-KGn3zr9;%4PE*?Zdy zW4)DTQ%+0A+>NNI*vTW?cip>daX|&Mjjw^}%JqU<FLiLlY<#l9d6K`Tsg9>Aqk4w8 zhimXf=a)_i53F_-GTe-HxLEOY{Twrw>6<@DOc&1GWVhr9SIDvxe-E%H1|7e-Yh$%b zKR@HO?>$E%k8rPBx8`J_iIQM{pv397d)?<Q@wl?AV%1IcKg$!hT+lh}_Q4`J<Ep?} zuhu6y_YAyQ8s8a~1gLEDG#5~vnG<knbJ_Beu;QXuk~unVw#U{e#2q}A!S8&j>c>5? zN6(#N>)mB6bc^Pm7xFBW@z`}N_E6((xnG9`X0YB^Fn@w5d(>*5RqOm-+^eejKi9q3 zOL&6k#S<pe&l{Y&Z&c}+TxoOK<AybtZqd@|VWPe*%KzV~H*9>za6<a{!7Hz}IZt9| zOa3-J?v3KJpH+eU2Qz*f*soc)U}2)p=bU3Zu5PGvG!;E)8S-M%EG@T7lZ+IvIV=mD zwQ-Ga=A(wN1j&vq6Q&-V;bE<2%Q+?g08_>}W_2bWwUbg2#p^#mSfuyt=RK*w0FD_4 z=VwcZH)=XH+Hb19n6XycVul?{*QdSr-595=KFd+hz@)G?a|LI1Rl{qQqm7pzb)4^G zThskJ^3|`-6H@CRzxgs{QR=Oyk!dp~$)@aCqHrQ0x#M`M|C?=w8^z7Iy7Mc-vXvY- z^QF2~j1?N31?BU2CD@OxY5vL5dk=J<#Ys<wljk2juGCREGbe7n-oK|$%;p6go!*kD zv?V*K{-mICS4Ezx$hU+G&flBfGhV!qqmVDUU|aPz?$3u(joEl_EIW24GN9&O@dpJ) z>w-@066Ob8mxN01EXgsK4A70)`expHOQ%Q7v-b&xujQ6K&O1qT67$sK{sNANH$-^$ zF>CLtdT{z-#5D6Yll3n7o@(Q5ocw53;ADxN+j%C{b}Om~8YVuxurkwe&Zbl*d!FkY z8^v08@&w+0a^Jyl+ttnThZagJa#fwv<u<l5?Ps5StyAdE?heLc79L&|5xwap)w#Aa zl`Uf|>uWFl`8bDHDsRrB$y!TG>^i1u@Y?TfYxS5OrS5H>!fJ8bGitN*$_Gg?lT?yS zxi4tl`ad@(Y|G^hda{?5Zz@dq_06OBo=Q23-CM7_`jh>|GESOIT~X(}+&STpOaF?G z2jlIRPCRl~ea)#S1-EvYMRFEq2EDcB3--Q#JfQkov5NoQ^OudYzG)?=a7?M`e(d<+ zrW}h=A*1Mt5MN>C)UTIqD?M9osJx#fcCY^Ul@1jhb2gnf23MBx+&cK;d187}g9_KP zxvv#vH<c@#Vc?G36y<fpZ2r0Xi7tuNM+LU>b}+FgAA5DF&M?L{WiR6rPn8sgB@7o? z!o^q4cd}m5eKpj5+r7d7{<Y~E@moxk_Wohz`|>iD^T#I_=NRKOO@-S^3D$P=GoP?n z)VSCeGwhmYT-=f=x=iBa+|ZPLUHe)V_N#2EDXXh3s@UVxIM*cp+0_MkQ(6;?w@T}1 zCm&sw*7VGBvFFRG4Z1d_JvH33cFaAKIbnKbitp@%b4N~AG?;9unpt@wL$5l`=y_v@ z_^nr#psi`w@@A}9wUa|*M#=LAhTGE&URz$2IJ4x^27zV&&00fyGB*G4xg+T1X+KGS z(W`>hrVS<bbphw+^G3hA)OJ1eMv-L1n`di0g0{T-*mp_s=d(KtHn%m)uiW|MwvnUh zp&g;t85asYa|;vm|CLCTIC+Wf4w+&sm1FmIi$kxTw9Uq8os0XDs-wMhZq4PZ<G+w+ zs%gF0)KaDKppo{PbDKpDwWRh=eUnns{gAPAZesi_PQ$LrJbiC#EdN&SnWpAswV%Ov zW_Re^praEH9k#JbJ2LgI_!*a#+n7$qEI6wdHbsc<Mvvx^V^418ADeI?bd6trNSIq& z>eMpZ^qiMP#mD5<-9Ou~ZeHBH*dn2xA|H>-*=wfhZ0%M^shDl*url`P46{XR6z(`H zPG);)c=_&foii;<!z?E5PTA5m*YsOx##-x~i2S{Ba$22}-`21(+|t|Syn;R1+32ah zwCdLK!z;6P1Qy3G&+O(=^swTI+`7-OJbszs&emUE3DPaceK)?m;OQp);rW^V4V!Mc zs#aD$-n_9l=kc^N<s$7YT5}J}TFE~Dpa1^s_S<fgY!m;VU4CH2Grp5@Oh^2j?r(U$ zDrKkF_SkLFn|A+_+senix+Qy3g7A{ut^M<}&h0s1b8|X(n2^dw6$dY$Ia=O_CUK_x zQ!-LA65C_QeNs1BtGRFEl~&$=30st}eq(&`reniACN7s*Wf3Aa-l;uoIf?c!xcA)O zz0NrArgJbOH$SVX{HD(>^O7sg_<p!+1tztN`Gssy>^r*W>sv<&ojDU2{>DvFF!&+7 zC)+{!$Fm6<hxA|OM%gnPyG9g<C316^*v;_PxTN60z<8p0o#TtQ2^*NT?x(T@Z(nF~ zXl_UE-}VVrhkx>gZSPsCQ|-bo^ZC}-iCH{zEoGjSE4*+1Sl!j3`-|l<r?k<8RJK(Y zX6JA&WYk=|aq2d4|B3_Me|`vCeUM%-F?04xrJo`u$Co=?YAp-f&@wmnj?wk)>1WQ1 zZ@<3%_2iGgzaEdjU;pdGpSr^0;*akhf4!>v`JdX$f1m&H7JqzaKXZS~{%YPMPU6)q zHM19g*(x3XLTO*R>NdutF4x}-RVUo%&sblfF|ld)jeRB!j{htEeta9sf99I?3;T-V zzwf56zQ68X?Hj}Wu?K&wE0@==+gDfp_oKa_$o-i5n)1@_yVLZp-TGBf$gK9~^6hTv zXNQ;1=6|2Re#4f=^8e}u>3S#J-n3=*=txI1Z%SlOt9f`<TrXtug$4_TwI9M-o>wgO zc*CBMz4JZuO+miHzlt9J%4q#$d%5?FdPO1EAMFe4oG%?ry1Zgy?^8wgb?w0n(v`1Y zv8`Ho!0>tiQ)0soi^Hjp3uiyL!Xo+c;O^?~<vhW0J2vlWsaz+dwtVJagF^X)m8<gf zKTUeMben;hPH*+gmCdXgJJ`(%c~vA9Pp@tGwx;**{tu$lE?hq8e$Vvgm-d~tS&}Vo z`@gQ7x8sE?lebV)8(;D1CExZWXfIqH_@?B^`P>(?CqJCp<fX|LT^R7-aJ59iVVew_ zn8*dX5;g31_C+ShOKTj>IiaP&_<q(x=H6dgk1Dlmj?HDAJpaM}NU>$-{O-^Ep!=}E z$Hs?&e_ncRse0tLcjp}>K0Yg+a*pSehxQLggR^h48p9)NAFWB-_@Q0wr|i7Ug6}*+ zu0?x3bl<RJkUL_0>fVMlg}7|(TRE53>gyF%6)>3_IV2ubXgwF=Xns><Ss~Aw^A_%3 z<kpFN=+#SdRCO%bZ|@|kbyjU#?zi`M`1qGrf4=y6L#TY@8{@gf7v?cdsF#)gxLt0Q zg{AvZ?+@<hHb&Y%IOorC{96fI?0qxdtrb#g56und8FH>!=&|m#vl)je&z_~7MbY|? zWuDBuy~cs@&(+^trr|kC9c&`K^^2N+?4HPeFK5!m(-JSO4wfn3TEpSz+$O)d`pZ8L zp`LPe^YBGClx8*rZ(wICjlF*GHD`*+jPnaN7MmSAw@G$E*dz5uwWQP>)tB9xk2)3_ z3HN?dlaACC`<Pd@A(`o#Ky~9KlgDQp?>)2Y{3yZ^J6rx2i@S#0Z;zS3W;v8P{pq`> zJKJF0y}fNkF4L+DpZyh=w`*`;_rH#BVZ$2F1l0<zJBugjUHKqYb#;C8_p*i2#pl?n z8h?k~dbMTUy^4k`@z0zwwHvP8>(;ehp|+Y|TaZz$Mck0NO7TVm)46x=&YMm3&bY`G z_H((w8pp=iC3n?zv}G<=zCC+u;{QOl^&Hl}^JC}yk(#Ob$9;;t?25RH)vULoooY^g zINPx0m3`yam(fptH1yd0Xl3}%#OqVDqp;^a-#6xK;i_MFjxCj+BI}S<64NX0Y0~K3 zns{8V^n`NK-?KG04oFsHZrR9ueUkAGv1PWhOzO5FqF&$c^4iba&{FuITyW;!BxOk- zGX~qJO^%}0oOf&+AJ23ADf6IwO=a|*bUV3*^Ik6wWk!6P)c4<q{hq+j6XpN+rvxvI z<CGMSJJy`LBH(OMdZQ)N#vdFjr57a~@_Hh9qHFbXpVNv5U!2ZO*{1*Gf$oK^_wL4R z+@KN=CR}N<D%U9H!QtDdHtkz}%<>OUNV>|t#QDoY0)4qe7hfs3f2-`(R3|0pM@k3O zemuE(n2SNCBP79c&f4m*^^s4L{+_!3CvM%>#D@oUZN6PT8+{^dxtZ8uFZZiUZdK3S z);c{q<n8&u59gz9U%xQ(biZ_M!F1uf51#e!%GNDmF;sBUix4Savi`xGS8Gx?YzUSA zHQ(;5tam!|;@11=zfahn@&8^V{i9^^tEFGXe{-(UG~iU~%X!sWSvzy~i;34%pLDLc zWVwU)gpF{1-;H;=5+|pgpEKXs=&+IfZExGs*Y5dz4+{D2TYZT2x2vg>Yw<t0<>blZ z2iWa(zPuD+dYRjyTTm`g%vv|u!qLO_libqfE&LA_$$VJ$y}^TF--6jjUxa<`$vH{h zE#<A9DK7Wr9#cI#k6zVd1CCc}8uJc5+HR5l&&DbLqg9;z4ey+7iHUvv#amW<UHJAS zla3kB;iUUJHmoT;ko+hto>|GBzuVzQy<F!Ul{N8mchCRYTkJ1p;y2^<^MhN?%s0zB z_H%8#ePieW)AP*Y7k<1yZqT*%>aR@i1<|kf3cD1{5EhR<f06Zw=(`Wb-{%&!s1^sw zuW+uK(!5D@vDohwN(<$=4zGBm@a=D2<M!R$?0WC2{+W~uTAnfd`Q>nQf_VAE4R3eY z?^$|3H7Y=0NAuzRuj>kS-hX=F!e5qx=gg&*O-0@RKOUD4SjiAn^LoGWjADZ~B0kS# zex7nzYR6&8Qob$fgcO&-56LFGA4&FeSUYz7@7(?4^(j;P!y4yOSAXr^%X8;ufvx<O zhl|;FF1eVdbSm<n`;^sB`-{KC{m2bkc`*NgK<uNLyqB7erziLdm!wXyxXJj$^n1e; zV=M0VG)}!D$Lf<a?O!uR94x;oS>Lr!dfys;@wgpT|HVrrBkY`}raY|u8a<8K>X2;_ z|2HF_dz|w+H%&NPvoPH(pVzg}BEdB7a>Pt|o*N4nXRS%$nw9L;rg`Gj&2wA21K(ZT z-1va!Y~z|u+w@kgS);|2?a_B)*0wc#s`ms--0$5LQ<*QwKdtI}{5OwR+a|Ew*eLVk z?S~&`X0`|NCkyFZc=KSzBCV$n*pC-lMC*M!`XOyyt4w4d->>-+^AcI62D^kx7@U!o zPRvL(n9IMP(?($V|NH-IU-<vO|Nr1wgGCHajM^Ty7E9FiRR8(9{l25I)55eRxo10C zX9aFIVV2r8`NA6G`x1^Ri{?D)P$|$mCvfgYwWN}9WBLy1C#@6w8?C3_k{4{gD)XQ^ z@a49PGapw*Phj4>@t|o%N!o%vi5x$QySwf9AJ%@^E1R&qR<5_QKhvFoY5DEf#ux7O zT{Ux&u2Gw@xQyTLQvZVL(+?lrSydi*{`=ho4~sd$62hv6RY#OdyOYDJ9e&6rZ!>G+ zTy){SUBsN_Rj*3YyaU-*3aZ$$D04V&@K7`pPH}OY?a2|gBlgL%O#O)pAKhPZA3PjU z-!|E(idn>K_iy$GN3I($$YhQ^dZl*D_QpfD0(~WWeBZL$rCD_9>$J1JzLFSkJZH67 z=3<M`_fJ-eYF)ihdhB=C+ka{kes0|I_lQs8gS#?6FE2PAoWPzx)3Vks;zskClL@mv z&Oc!%GH(z6F%BJ_?G<MkFI|xS@VB5f?H{|q+drzm8E2JEydBY<TIalxljD8@Q;G1- zbfdY}r;Yz^VruB>+VH1^eO{~YX2-*K^RA?JcRpd>UsSIxzvYC}R#vs+eY^OqJxZiY zyUzGJME{b1;F_=@A|XiS=hKz%)(g&RTHltTbV>M_hV+(BE3O+lcYKeDT?or*Xpp?s z`Gq_6Lwn?x);D*y20Rb1SS?w?d3on<vxV;(vbgPq#q}L!9e*l|O)A**(QZ!7{{Hu$ z1Vv-mK5lXl+1IeI&Eev4Yq=BOTR%RV_?&Uom2GdFd2|D2dgScckRE@h)!cd3Iq?OL z7xXoq&HFH4HfNj9g?$@0&pME+wPh*)-u9W->en!MGT;3%cl#FJ^S|FHf6udUzHyH8 z2Pcz!0!w|tg7x-H?&=$?4k?wMP}zQD&%)B;(%*$OA0JlLe0}$|{rmOzcE_~E<@6gj zpZ#)3)c*6!Z?B%+J(?e0!PtGie#efzfB*hHo4qIF==1#bdiHl4b}MGvWyk*ccAfvl zm-X-SKbJ_~{r~VU?~eFD_M}HoZtXr|zWlzb)&K3UXZO$7yT>;7vEO-v#oRYnJ^ghf zr}?t3nmEIWtp_vHm`cNr?A*!T_mg>9o2I7y`l+&9!8S|}zv=$C8dtJwLiYaFzomz| zH|*9+dK0;c!$Q9JowUKn;99<&#(F3FzVP!rQ%$(L_S*afd2b8O+&y}xNv-r5TL;%S zCACdUU#}08NMXOXMn6-_{)yc5%bwrs8P`5J@Azus|Eulw4Q281&0&*odKPWrOlfJ< z$jhDb?Ej*l`!oLOSDDQH|N7hC<+D$(j?Vj;8yWvkKaQd6V${F&jVmtvdfzKE@#oi9 zkG|%I-?@@?c0QA}-1aZaCW}S1g%{`jyTZkCs{5t=^NN$cbN;-YfBNaMlNE)2b7cAx z4gOTf%)jMhe*ISC;oj_pk+*B44$JV?J@ZZ6`}|C|cfOt5B;Q9`lV+OV7oEFp+Pzzn z7j~yF%$m7!b71Vjt=xgRXRis(OnkUM`NFFGWn8mV8=|b5&*toGdE_D%DZW^#PV#zE ztlDQSEvadRiZ{g1>@sN$oPFV}+GD8-Z~hYn{*l)Uj;`wA=Ke8Ta$)*kqjl~x3K{=R zuDo~tU&M;{6IK>^ecm7Rv;S26mkP&E@z-v7#r<opU-r~KaDuAVf77CXAp5t?>;9Mg zUH;lW_P_D<|4VMg%>Uc|T(t1+KjQ$^UH{Ar*ZjPxczoB1$$Y!dvF<CH687Sk|MmJ^ z|1LjHx%Pib>Yig?>udkJKVfxT_`1IMvp?rNsA>A0QvTQf2gm-u9R1(rW&QDA`doXY z*8Sh4)w$x|@-vse?(cl8H{;`Pv95MG!->Ti5sFN6oL*RDt1=%rc=ODL9h<K`SLhMC zQ*`}MssDvu#|4KY-9ny5zTPJqvY}(%uX8Q>Q(|APJ-)!J;6vM5)%)jW$S+8pQ7*h) z#B%4Ht%qvjl`jZ>5@(yv953->ie#&Y+WzG9J?TGce>&S9R{!K$*;f9Z{{zo^9l6__ z^I9H@ws^5ARwbkqw5Yo{Y*6I5dueeYXRgPY`R+Vhlv@8fCkK70P6+1u@3w5|3#Cm4 zjv`y$^-Q(i7!kvuR5yKx@ss{7U-odm@)Na?vumGkl%Ur-ll8vEzFz0+$AT?f7yO-Y zc&(W5|9zrup@-d1v4zdw8g%f=)7f2zR-TWtXtBB}vQpvI=CBFsQxk5dm&h*tRL}Y| zev<jq`iZCh_n!EF*!TB*oy=DOl0mu;t~{xK^E%s#|H;ex<$wLdu7CTV5-7Iv&;5=+ z`SvzF3pak>xAltrF^@2&MU20gubz=Gtm!Ud+VwB^_kGVB|63kTxb@$!`meei@5cPU z?PmKg{8L|T6!V{T=CA)IMSs5B|D|1j(fm&2{du*Vn~Xdi6}G?D5BDyARIIk9NbX3E z@`Nn~F%j&`H939S68}v+P-MaNrtRU&mY)SBWfQ%oPt{l@IW5ssl2<Zq>x`aL(HV!r zHcTv>Vx;LN&OBM6!aPN$Ig<anoQ(41#~JMh4foi4L_h6+7i1ZE&0VW>+U4hYGxERe zyDh-K?3ex3|11CbU$5Wt@9~2ZQ7`HjXjuQL|6%$!K4`)J^-kC8SN#wCcYnq|^^8pm zP8ePN?>GCu`ei|rh5vb7Je~f?>oFSH=&xWp`~Tt@L5<RPJZXuyPn;HARpVdxL)&K- z17nlv5d+idokd4lr4~J%<vqug@4o5PMmzDCVzqhOGai2S|5YNCIdxZZf8xGvVOpIM z0iBD&rpIY}i7bm2^Wyu)_l(6=@6_TCmv(=b&tGr%tzeT;MeUV;6~%>>SKqn$OYeF= z>j&?3xw_h~pO?q)GI&`$gY7KOrTYu_{tf$+IrqIsXg2#Py)!OdTX&hQ+qQw_`N5O# zCoa3bEyq3HciPIyo$Lurmv+~`ezA}9XW{kz>Hm25%Us#G+wRP~|M_!Qrmt0du)g?* z^|_rFzY4GPtv|AVTkVWP_w;VwoyXTC|JJ=W&9_NEm;L12%kjN7nF;9+1@7yKZ?pR= zYJbCTpZ+d}{H^<S8>jIH9RKNkI$C#fx$9!?d>*@riFHX$7mwzP@4I*C^QFgk-R5)1 zyBg2UvG}N2esTGOECKr{dj_=)!2+MFUe+?Xd=M0HRA0iz_pg-mbI7Bln-=X_U+!0k zi=ARMPWL~s;a=&k?-ypXZtq$3ZP6o!2V4>iB`a%9qkR*feOXX_Jo@aK;u$x@-yU1Q zXSe(F&RkWwUHMy^j7%>$ea^i1@onej-t6+nS&xdVuVofHykP!+aLJ@vzIjcanFs#M zsGKMhU&dA@cRqMQV{hTdaMvrh3gvc}7e0#JUt52jFE9K4_G{WTP8nY%&i~Noc-HXr zz?}Nv>a2!|?+-{G=lK3UVcOh}5_X1i_sh?l2i;y|?xcM9&v`-RoS1UikVNG-tXEmS z{N;OLv)FJ>UDdXdbZzU^s>}b%?mNkE@cr$An_nid$WPxjZN}|0e9lc9a+1GZD7;nR zXXqnwN80O|{q7$Hvd^BdPUbcia#UaZqBdZ9h73dV=~ry~)sJzr8}pw%uts&?^5`6s zfMSU=iP>{A;&$JaXl=YLx<@#1W4qgnIgAai-{&2ca@~8xe4%h`+h5}-hew9azC8~u zXPguN^Ww<*HxH`1HuQWI*0Yq{R(755+-|dmq$;)pJxp?olkaVOymI%3m%l&jglzf$ z`%syZ&6G@)zm*^7esKP7RxVz9xOSr^Oa9!=%wHP6mkXaTt$TGm<sN^*{rvLtk(rx+ z&rj%FC>kNL|3=TwNbbDX?#czKjm*E^Kiq8azP4oDZSRTqWe*rzbU&!s-}(GZW5eg? zdT&?WS7CbBr1$>(>scEY{C&3kUEhg2cc0I<vH7C<{9TAgLZW_ncjTh=GwhGAO?<~Q z&+UxmMw`4fH#wi}KNz@i_cxBMlMU~^uyrtgy}pfQ$%~~*cZ=Vw_qn`Hw?4LyGu-#Z zW~OT!%{`cY$ayo{&v>wS*N4{q>PI`|-{y7tN5?O_c*o%^!`&LWHAfOJ?z8d!c571i z^gn_%6VJ{6x5e=P#ppc0iYpIlx9>J|h%XIk;M((Xd1M5K=pJqfosOqVLN5H>_;>9= zi+SvarSHs@IlA@aj+T}C8;>!}bEt}2u56&Q`J(J)e~<jwXZ}40KHru9KP^N2TH^vY zjjaDmzr|<$UwT~e&Hn72>94o^@7kla?q)svtA=C$O*8-Zp4qi<u6fT(CZ~>{JE!j7 zaCp|oX`2)7`qx}nb-R3?`+Aw#yY9)V>Qb$(^WJ(Zu*T|&UC5G&c%XN9&vEOw1(`F2 zymm9r*?xN33Abs#ir$%j;MZ|y>`nUM5@oh!|JjAFCjZ&Qr}Jlt)~SH2x$UJQ&FQI; zr4i0sSi?5^1Wxz4H$^13{Nt7bFHauz^Is9bAuu;aW)7?JwO`YJU8?&a=Koy2VbQ~L z&0dQvqmJ4|zg&JzWc~aL+t+!nOfWg1QFcqCz0_dZTe;8i`^=^9Hcs5}`29|YixIxh z=f0bz_D^_LM_82hf#5moo?Lu7Y4X*Vc~VM+OW&-nU-!k6z2r`})T?*1zFvLv`OI%C z>BFDCUR}QLguqXYh!UR3E&VQWcdYfi4OUBEo>AV?q;*L8$>y6%lQuCPwf0$|==k?- zj?Fx#S5p1wKL`uv9^5=vZz}JKKmJeawf<jztn%dliUTgWpY|_Vv1rb;{|BWsIYa){ zSAMd03+~@JZ&A><i;^mq?8}?)C(aVs!G4chYZmj*{VnG%G^aAJPna8M|KoSk)|!^9 z{yr){*wpJUt6x}uU|ZAv|BWj1&F>v@DCIf4tf6O0#_CCSLQ_I|HF~!A3GEfW<eqX< zimS;kB{l9sM5JlSwGC4kvtKi<@7{KBcC+o#Im~Mxnn&#a`1O3xf#RkK9dA$A-MJ}r z?a$nvkB5VQY)I{4t<&LnT+44?^{=R;Ehr%3*u3h8Px@H`Cr!20XJIsRGH`yJ#Ia}1 zDd*<U6z`POY=up?0w&#Dc=q-x)oy3!Q;U}${dI=f;rJuYJ!Z3%&VA*wnJcw~>HN`$ zW;@kXL!~9G&-PsW;VHCUtm4X5^=+JK92!gREY3dA8FwqDU>0}7C#nCDPo|2!6OZT> z4-(6>kq~^hU+3_XxW%VgZ#DZLe4^h!FEp*7S@2e1yyfc;Ow+c?{onkaBT|-0eLW|$ zv&4-xNh=$QbWbOm-VBU%m*AP(xaRY;Jn<isw%+{wT==i1!kPX1_iNr3&^jNtl2v=A zje6fluJpTKmi;~Nc7NX2{gvJSBERoDaEI}pVcXV6-G0tHzAeZUaLrx7Q_1^*!<Y5) z0=|f|8&kqU+h;K!5x*zdm9p&Nw^z@8J<2^g^Fyvd-sD^AhYREx%HL0ad;IJ1|1p)` zw-2!%IlaB9%<JJdwM7^5ij+&HPfg<!n|{NmIsDXxX{=%wrpRXBty7+|CHtUIO2wkY zv-j>*ZLH3VRXK2Q>f5cV+hdE?l*wmo%w_Lh8{sdX@lp2rhBsms&k}wXsDEqD?Opux zK-{9za`Cfe(%u_POC|K4gsxd8y=kT0=QRId{s|7t-j?(-nXQ?A`^=t7Mt_dEXCLIV zA9~f`e5{3??E#Ogx~=YwKf9}+rOsP_Gj3n2uzI9kMQ4%P=jX@UXFoc6{7^stfyw-b zrk8(s)(~@9ts{4~>F*VxR%}^QHMRz2)!w`^%Zzv0(y*TrD?*oD@ml#cH8{J9e}T@{ ztm6)ArIv<yt<|3sb@_JA(-T`I)7Q(WXa_x=I_ZtK`prA%+B6sO&XF(-_`A_|uKxTJ zZ=0VNUGRzi_g-uF8n*kJ&S!poSGWFrmW9@m+NtJhYHwQ{PsKK9J~uoNQX<u0yk*wG z9ouWHw{f;N{P>*xNF(+8_r<*XKK=f4@mpMy`R?7{Kf2$oXL)@l;EGQ63jX#@1|qum zF12rZ<*_R1<~D_{rew}lTm_0Jo&^}R^*!sD^~j=0i!bGD*pJO7x_83WE?LE#Exwd1 zm;QM|fpm%SeWeP4t8c#Zi0*7%5a+M)>Z!}#IV+}LURT;!WtrO0Uu7Anzg)=cRpZ_{ zMlCIMayRQ{tBXi#t`^q+x^pUTQc)!HZaq=Ay~pNCKAIeGZ`-_i6PR04!)A&+wDj?^ zG?Wq873=SFXj|k#+etHK*d%U^OuMq}apl_<$*s9By33|V%Xj&u#jQFNyfuB#>+jo? z%pWYByQ$-x)61C(j~gc&HeWKH<@mDoYy#){o*v05^Dpw8($8V@_7IjfzR~00SoE?g zbIz0rKLRhlwNXva<#AY=ulp>i_Kc)i#y|F1{~MpxFZd~M^x59w@}h;m%Z{=XSbw(X zn8fg+*7pDHgasG=@ayaRKm3}(ckhes+?Ti1?mzxuzQt|l3SAH8k0<*#IX_s!bGz7W z!b$#(^S&rro4TZlb?#sH=IG_Om!ey8@89ayU&mQB`)rPJVRC`pTvw$(ADTShI!W0! z{P($Gs`!283-47`=Z`pV$~D+jlNfa1_LTm>DEq^cOgt|}Ft3@sX3Yw*?2Kh6X6;(X zu}V*ySu=Yw3-_}RUyc53Zdlfodf{8Z)HXGJ?=?y%xU{9eO}MHm{Uw>l#8;RnPW(y_ z+XRJdJ$J#SC7;ZX9jRh|mj9M#{e&<7%zpK4%$pH*Z1;|T75j|T*6mDH7mPVBxoq<G zrSH0y|JxV%La1EpWbd=R)#8S8W}8h_ckApBwE3<O`c19#_?a(Zn^XVBd=z})KYQ`F zjxAdCU-tej|0cALV~vf<hnnB)k~t68-)=X!kQmqU@M0EQ`c3CB;|oUaJrZ}m=~z4z znj9DFwN58GTy)E#E1PAm?7G$vS#c$uzih*~lq!?wG2LZroo8kT97}hSEZ*`=X11p2 zlrPhKt)Km0<o~Ai90$|%xAXRYd)T<z>00k=xwSK=?d!@*{2izCa>G@&`zl4Zofw1U zRz|Bd<_TxV*z<E<dn6&a&r$u6(oRbz&5Mf~Ygd0#_NzMI^<hQ&JKKXBH+JjG`&umz zna%doW4YqmbJORvIiI|lx~wV2uJBUuMn%7;^LrJ#db>hH)+|c8YAm!`=;MahV$)tl ze)Y*Iz9+=DdU<o=^@vOR5^nV_-)Sm#<!0uQ)n!v|bgBL2$~<*XIjpVu<ikrP6#=`d zBPtfpJhJVUFh^CC42N+$%W1tSDOMM!#($LdP2DQ0C)Db_w?K2XY3?CcJEk2cMD)HM zTDqoeJE!<tjt7eZcU<9~zLodqr;5Oej}IyWIW&HW=v#lB^mct9tJx*N18rP}XAdk> zijX=Vv6a<8>8WukbK8Q{lK%cb#=`ZUix$`MJel#5$Nu1-;=Qw?SML1x=-0Z3es^T! z>aHmG@jkkuQ0Kz-F?6NvzB->*(QlvM+_UP1SKJ+geRH*QofiD?Q&OCNX^+^O6(8lA z<xih&l-`g&`GDW#XYZ9xD75z3aGdO%^eORyb)u53{fsLi2Ocg}TIO=&r{9qi=lKnd zTzv$OOyMZL-#CM9&EzG5!P^Z#ryfwbEf*=Pcj<F;x68wz6MT`PD!h@(p3JUGl=Ao% zOyMrM*(f$?rd1h_;mV6TX*XWKmA=WvDt_Hw%)MD|b*aC(&SA+c=4)Xly;E~t(@Rf2 zyxFLfb$DUU>pcnqujRJB3w(X=-Ba$1VR6SJKAw<CHjWIlU1tA7>hYZ(_4Q}@_ZmEp zvQ^99U0Lz%<1J?AEwYzHcCf0bxGvF3P)z^DeNe$x+rUGFr!?ZLlfjAeTs%gs&a!OQ zJZ+D+UQKOWm}z|XGXt~Z<`@pHmywN4dg7)M_YFk)Zoiwx%097c($<+b4Ai7Pf3!9- zOuBu?JcUiAp=qz$!8sNjKE6NSG)c0}j_PSnoqX+T*1y%Kx0Ls!Em^tu%0uD5sye(= z^v!u^^6lU8E&R~Vf^Vq?=hZlc%9d++mTVJv^--$X%;0i~Z~vap9!Yv9XO=cqw(h9+ zo7~Ou<#)d=lXT!bhmRo){>QV`?;KWNGTmZ5i%wmponoNf#L4~vHg6vafBO7H_>=dX zaHeAqOy*C}oPXk^y2iY+M=vYN#mhc%F1pQg+;~09cg{(F9!dIsYW&H1G&FCYqOJcv z#k~)Hsvgx{AvS4xbb!fQhs%ZUecnA0esns9{lptXwV6kaXFp~(=HXiXcf%@UBNd5m zt@*KvCCXC`<J?8x6y;rbR8&6q>E%0eN0+|eF?)6Q^=h+KiczbMrBpl!X57@be1)4l zf85%wrcInm@kz>WY$A^coJ}!jkLla?%FRagtJr-7Q{AV$>uz3FvR|J$vA;UX>&Es? z%bu=SU6kU_`}2`Z%kpJ+qV`X0>04JfQ}R=n!t(j=gSYhrOcV*^ebRA?&BN9)>1RWT zw?-tt)9hyb3uoOG*)^Lk$Z+vTWG8AL@%Y91{CQ+Mr`zqOUChroYWLl^-L+xaB!MXr z3jOCNR%**n@ni26dfLo;JTcF8ZjIH7$(paE_<r1J+SPoe&w}TblwRP+PXXbH>Gj&b zmRxp}kIkITn|QZrXLIN#3!Zl_t6s`EuhB7e3cK-4%|ZD1+@=4X=uC({@wlS-I)}rD z36kqp{4HdEwj}uA92dj#2Xms&-mL0lEjBuOr!lzNH2tL|-x<@nVm-GiixT{;MBiLA z{kEa=)U2(aWY}N1tn!ta*!%p3@FLlT9ot2duFPF{;8FHX;oS{qCrStu?w|c;L1ls2 z%-MG8@6XJe^7w?ud~Un1x1aP0+n3IM@rkMV$)YNW!?(i{Jk_~$I+?mVN^`Y0JP~G{ z=F{kUq-7gx#Mjvu`h+7&qp!@<+@N*i<TfTBtH6efsuNobbGX;cGHjDwE#+~vB1vq$ z?vJcfkG>WiUANXE>lDMaH8)p1wK^lAdQiT9=EV+6>Hg)rtffJ{fz>m2w<Mo9xOr~g zYf)RjPY-^@{J(Gi;(p!M($jHQF0=Rd=h|1sg*?9hu(DB{^`+?NwVjL+jBcA5?#_Sl zr(4N5c2~kfQMOGBPBy$gDdWHM;7OSsc1GF-%zm#9vmSi^c&_;dyN0V=>&*JH^>_RX zHvJWzD)~=@jcfiN&brB}^QOmfesW;_uW4kX|7p^x{YgL6Udm6Oe6#NUzSrl!6f7^! z-`I16QNjFyux8?>t3_h>rW}lTn6$8qGq3Obk~|hA<#gS>AJ)C*@ZEdleSz_Y<9A-g zzd2%AZpo;wpZK78`abFSpX`$oA6;Ibdp~AJv4-f{?NfJs37c=b=1Y4o-~BadVl}!I z-;T|D;eFd{pYFT7$4pj@x9;v}*`Kw!x#!s8h^DjWcexrF<Z<)5J({}sVC4P@GJAUb zkJLU`Et$Xh-;KVBz4sohwf_Ak|BTJF$b-do91UNNx#gdgyBlq+{B6^byC42;=5^jX z#qR#?kb?p9gKIgfcKu)y(VXEfaIbAc-#dm$n=KiIN|MCv7;pXHSXZtzQ}SOaX9(MZ z##A<!qcxN7Tr=p4@4V0DHgAsQDgyx#&*aidhLFyMD>lwrD7j{x)F+2+ti=hQzpscs z`o(`rg;RR7Xy6r{z_h6g*KFRD!ta>ecPeVqnwdiDJ^Iq#W#=$$G<D)|cDAr`o|R#9 zs8%R>gIu;@U5ualg4H{-1@q<m%0Gx6{gP?1?ypU9*Dc%E?<&<}?(j^!_T%I=@dE4k zbDw+uXXv}V?Vms6KI8HH_mxaLYnS{~`o8`3>ige)s}HPjS3Le~-MzPm3(u_lb1_zp z-Pt6Wm-qA)mCjJnqbaEdU)C)9D3l$&ZAqtd?4#7hOS<;Itv!&zXp}CLf9c)5_tF+8 zjs?p%Nm#2@yO*2HHjfOJig+L_(rT(xdV;U=@+FglB`!C0esiw4|DZLn|9AXVM{n;} zu^+RVkI&wIMo~Xv%}WX9FtZ<w3*;xJyJj!2o|Kl=lrl{||4w<p+xKVR=YQM(mPx;g zQ;qjtP5pQ2Y}H>DqCI<aUoc;LP|BcocuM5iho)guMUHMfyU<i*N|F3`*ZFG>sB_w= zcT8IIrSx#l^sEd)56#7EKXI2={{8rBTgc;%J;qDr-+lf4dT()Jk|2|hgM!ZjM_C55 zWs!Y{XLa#dtXrx1CLn|%$7g|Qgjqwmq;kxKaE7VgwTU;nj|TVu<Ue2j_4wZ%2iZ;r zPAfT9`{T>!+pllOum4uLW#O)wOSt08y4yUDcif+rU20psFkp3kxY8<N^TW9({9X3! z;L>qYyna?>mG#ex<ZDVZ%eS80{?3)hJo?1@CrMp1YYMvKE+`)Bm3rhIY7r7O;l@IN z(k}gv**y8dvtPYQ4GujuHSd*rZ<>map@P!9hR_@Se`@6R1>3(@JX)`nRFOS9^hcEL zjrDUh3|-kT1zu=$dD(Eu(b7s|zJ|Ul`=`JQjXp4eUHXpfy=iZ6d$BLQ>!c|gV6|eN zkAW-yrN9f!Q~Nb+Ll(Ddg<PmeJG^#^LQwC_Ag4&L6(L_$9r;wcckku6te+_m$|w-{ zA!N<u=^G3mJ56r6tMo4GL$|_v3CC;3i>|QMb;|zP6#XOh+Xwy!?*e!4KYr1oMrLli zOQ?9~T|1#A%Qr5Xe8h3Diq{U$DPJeAc%tEW?)AcFZ;y7>@%LKUg?y_~c=XHR#`lN& z5)6;~-fy>7u)6c{yXOD)-*TTjm=gb7{BAsBO~yVO>-2M9e%i!j{{C=tv;5SqOKKXc zHoh?4w1_>@aUs)-RXJ_zxtIMr_2HoArA3;IOZLS?uqE?VKWv|rV6lMt>?VfK!LqYu zXD#BaP<#<1lp8C-bI#+O`6?y<<-1S5Jm$=2ZKx9XsCVHhrbM5l)Lf1fpSXaClNWVU zPn@2$s?#N1+VH^6eHWG&vJ{lAKKjc+EP1o^uTmqSg&UG&F9f~4A2Bb@vqrTo;H`Y5 z)Jm0o8&5JldGh^1d7t)4riU*TgZmRtTv^tZW8Am$$_CTe;M(JLZ8xr52=#LHcHZ5Q zDX6c@(Al=?YU)m#r5Dyoot<W~rMs={;)QkMBDc2Q5?Niema+2i{v&ON_nW1x@pHPf zYNEAS;y;CS8Q$srJ#!?#zOR{hn_v08o^zFP)$yVkQ|*>?*4iZPu72|Ew^{!g9WB%K zD@*mavfoTylm5PNeobuEx&8x-8<vzG)SKCMKtlDXlBik>%aa3qvaDQOT}Sy;FDJ6* zW^~M2;j!qHu<ZP(#Xjb~s=i@!b@jMKdtKHleR=cYWNzG_mG`Z`zhIrwHOX67$=fyZ z>5Y~tS(i8&H$IVgGVvD6L^oA|rbX_eGat`r;cW_X(}|PmUveSBqi)&-1zYKbj*Fa_ zMWt3;aA;-IG6`7N$i?gXRR5%q)RS~&lM^8s3s7Viu1xWt?c~gSavldKuh&^SNmK=U zViqoRO53CJ(6P$w5cAz-3l1@h%B}d|(8{i56Yy~1LX$<am7JY3T{t^=l}bC8Br%Ih zuejlGlugSlU}IyZ(eqEs-Z&UN|HSx6mw(GXx#%k?Pa96oN>bHs_mqooNxAyKL#c4$ zaY3QTWRsM`jT2mw6;`*}%Y{EtzPR9ca!f7v+Wn%JuCen>Q>$6TIe(j-ld#>z7XPy< zHC7?-mOY=?^74w2*4y`cD$c3Sa#^Wx{~f#c<!dQkYh@3Ytl;sU9ptMyb-!0x2hYK- zm?{pf$iS0bUST1d7EKbJx@JX6>8?prW4763*=cHf_noR)`RY*U&mO6nP19Uhb+s}A z9lN=rLM|+75)<9BVnJx+g-LPK7KAEsdoEj`8jK?63Q`^_w&lrm)r_ep?o3k5nCN}i z2_%SYhF|!FAdV0vJ1xi6PTOYtG<N4H1~qnb#e_Uq#3U}dW5oei)^)F#rhidlUFVe~ zc2mSL<jSH&Vxn7DtZ;SJ)yfJCd|l$I`*G>cqtj2XnxdFL(Py=b&52DBQr**D8zj4g zJ~lL#GE9H`F{C{G@khyh)uzSMKV(}}Y`dJhchT{eaxwE?|NqVY_xAd2eADh${d(|m z<6HIf-C2LEZS+4ZQrMfc&(x4X`+&Uog5Sb(>jP7kd5aemCn|8y;!(+)`B>B2V&-8Z zv2S;hS@RBf*6z^yQ9GwXKu0LKoa^ePpTdlg#!Lgtj6WwA-)H?dRe?X`!+fQ~pAR_* zT?yy8uktrpG4FTn?{)T<56?Zf_o&e%&V~;S{!7+)ubsB}!!n*@T;iv#d<u$d)Jl~n z6k2A#Y%Py<Hc>Q`KB4i9<%HIcE9w`_LyWB_CNTZqb){CCBO&wP+k<=#FZ<uVtoiAp zr+VEiQ}&C5*Xs@U1HSFseP7#MeNz6CC5L}VTUB4mxN|rE{Gy2xoQE<`zI#;ZbZgGC zS%(T1yn5px=dnh|TFhF6rB&1<I9&GhG#BrC*`E$@9S(`#v1{vnhfl04J_M-S3A6Y; z_$EE&z={{EPZoV~o8K^T*LstU2?Fna{GO6@^+?S6<vy8S9m_w-PyN5*kNea8K0osx z%`!`H4^=&2`)U4)F6mG6SMjX)^Zn41{o5scrMD-%7Q0jFxn=scSFTLS7u*~t8Xow_ z*m7(^x>Hi}57|)G;~6#{-F*kYsGOO*_}f#}-=FI@C4@GbeQveRve%nl{D04V_iy#z zyK}29YgPoGi?(Tb{PcV8a=VHp`>TUh_j-TJcpS@dL8Z9!c8cD#)2-QS9?1G!Fk9@e zb}wAMMlO42T}|Zt$Pah8?mV>Yk-L{?7{B*uI@_HMEV481ohiEb_OyF#r~kuTo?~An zYwhAIiWMH~y*(+shvD5;-F2}MDzWXng$qseCzYjr@^)M~bCz4AbBM{}NBemD<|>Dj z+<$nZ_hZPv<)7@Q{$KfLzUF`b-23gvy1Tdz*!^Cwq>=eE{z>J`TlMj?{`{AA3s!xc z-*Dm?>(2$rPE9o)5$;)xd}&-W>q}oWm={!pZBCguwf)xwQ<<X)sR{->qJ;}??vcHg zVO5;oR~{B|D^@=G(WSh55ACK1ersTd1iii1|I}0U_i|qP?rC3M_0&Ev<Z0<o|AsIA zPxp(f{@=@gVM-Yz$9XXk7Uqmy?FO&fQXD-bdhD03vX~(ua!DyM>(hjUjM=MlKRZt} z4PoYJo3?60n;Peu7aYu<g)XTJGAf-E7x@0*xz%$1_uuvL`->jF*fj63lg^J1(^szj zy}GqG=STv}o~wtp{Ju9u^mpa18TvWL|C(8SURL?;+w)(K<_o{^neg~q>(d@Py|A)< z{<7yw8{QpVb4tCqUP~`IKVjOA33KI-scWPK|D1p7f5^Y($3IW{-#BGM#j2bC#XWva z_;>w}eM;QIPxZ~8?AI{!-*nLU=PbE!s=v8|(EphEkyTIje~gNMl`ocHtG?LckLaNd z?ezy<?2{8_eZ!g_&-^p5?c3ApGt%XoS{ir1PX91@eY3`6xzGG6(J@RLSv^Dpi#LAG z{!rcjbA`0<2j)93^~E3DTY5j)PUp_beHFjD|BA%$%kBK4w)&;cSN3=2Z+PduG<^U3 z8<Q39lMk();&m_AE<O8Z?Ne?3V~@qQ<Q_No`Kns+=27=MzYp6VZ1;So`64$j^ZO>I zb4q)8zitlB^nS+9z?5w9sn8{%a}J}$1EFtIKJc96dUS=CTWp!!hHZ;7*W_qht@h?S z&nFTn&6gU@-lJ~ZVVrlZ<$}TVC5xP^PZsQRul<(5K5>1;FX8*l3T*Q8dLFNrechI+ zn*Xs-VDZjnRSlo_{mk(H`sTE^#ovD~_#DMD3-_#uY;JtAq0h`DVy1azn7PY>E4;jp zQ$@VXdfsM=Z3zFq)_kj>V9s8{mn(|foKKbC_t#nLQl)dg=EJ(jPtWb^Y-7o<)vcGY z*m?V!-&?_gTT^Y%wfvnW^=j?3cW)B^+^pkLJgWG_C7DzC>dv{jInGy)#qKuPCgv<x zd^WJD*{O|DeB#BswHHs69pKIVp2%ju<;>#;XV0Ebm79}1t)K0O-n0K5T`UYPo)2WN znejI8hfZJ=y{V)vIZKOUlkN%UnJ!TsGdkQquDYyvCGW%}?Tsx#C-pqkCu)`?+^XUa z+vPetWp{SW9p!tDlUD9y?rC{(`uS6TRq68wExoqQnQuDP^1-8o-rnVNyq%_p+*cEl zap(Lv$>gec(>jky3pY8RE{cfU6cT10Dl0I5srIb{CR-Z4ro0o7mY%P3xKMY|8Hf2h zcKOfaT~aCWu-wf~dE=xbe{24p{<^#W?z`IZ-6o9rY^%-dRyoV;i16A|H}^N=j9)G1 ztBY%QtnQp~ZAtp|Q~#Z27SG-tUvCrbtCsv^6@Qq5%#EGjU$SVmb){xcvP)^7l(T8m z%M)wTJdIxSRNmgOrE%>i*T9dO6W(zrI$Mb5tm*1IXXW&-tg!g!>!ZG=9dD|C*v$+* z#gl8lc#9|pqsO$h3l$g`PVQN7&?moPam1;Ht)-3EU2i`)>!>$TuK3*jgeRY0&z~9p zrE~8ENtx?&+GnmSe4x-|b$#-MD$^+LXJ#yMVW|c`yK)Zt-fldR)!=jkHa~XBOSh~w zK0o_HxinATiO!|BIG7JEym6iPQ{lqGhMW4!7kVeZbiDC@Vx^tZ&q*_{Gpb8Czq+w( zX;tG_ff#<?PK)xn>llwMWL%f%E%rl?bxr3o6BZvAGo9ntbVE<AZ;e`KKmUb4V`=>U z(|;BGdc&V^o;D5-mJU$Z#^3re@t{TVGV{0fX1~6zd4KL#dckz7w?7-0HoV!m->9bA z^UlYI)>Ep^NiICT#aWE~Uyk*>>;En$H?4kjE7UoDOZ}4VFLc#6G%6joVCUWcxHY%Q z^iaF>qq}#0|MXMJcKmOBE9Q7*RLpDl9lPgSM4LL_soEbn%kNI<kLPahFS07>8+`v` zlYim3f=9}U+ieHkx7>f*zi<2hb8&|?bNEFMi?}2n=$geR=05p)1n-*34J`+l6ug{c zjoS-OUDnrr^L3`d$G+nl>3n;0|B3C8)MNeT$GMR43)?hSxtjLh`qe5Qj^5C@qs+u? zFt`7Ztg_yprOlIGJ2^4_|JeC|k@Z9S|4dR`+oNW&nkH`%wv4*{`elN5gxuo1!dPj8 zaFzE)8&it?7nQQ-y7j)hwtc0Qhg{e8RXgt2@7=XiX=Prnv6hJ7>(i3HO|GjhEDCtV zacy4T1>xNVOK-gDV7Y$J?@Vv*i|J3wb<`hD-%>quV&%TZfbdhVKY#dDGV{nJNx#(_ zUjF#`>d($nn?D=W+$wlvHk4hv&T#(r**8rNU$^{rSodbf>mI*FJ?}Im=ekJBrj|^( z$l9a#mOZrV;>jr&WmOkX)?B=}r_X5Dr_#&UCFU9|=y@k038MOptWLdPa@+pwWL(o_ z%{>m5cLj^ARF7}td|EQ)^4tmUc8M(t?z$Q1e7DfZI%~z^Gkr$8FI}B@IcMEYo5NGC zil&w--K|-=rf<`(uB)Dx|LE!Yc-cy89=6?){y6UXG3D}vC4DXDCoVKUe!Y0(_pH7a z{uADN`O-^Svgge4-yn0*pl!_q4khjEP3M@_E!eO~^YymOmu=gO&n=!P!|`EluCQqQ z%8Rolglm3(d-e9}Q}<(AADO4zyR+wiZ)fH_#}=l%#C7)#GoIb9o+W#J!NWAB9}`^n zvAY}#JSY8b{rq)#|B8R#RcVd=liR=RzeQH`u16NDxDpogTv@2X!xCL0bJ@&whR4xu zR~N3~tMuMb={Z&9vQYb~#UEcC2r>=4w)SBkKMTvISvt*iDWP&F_AFf8q|w!-=D}7` z?i?cPIEk&9(f&fp*#ME~&?65o$Ym{i!ozzrBsG+|!R(3b-vb5364M^*A2!&y_q|E9 zFRuf`?!%dnmE7yxxGvOkN-o}NcRq!6b-g`*WWID~K%PgZ?o=bYYirY0CG^s!@3f4* zy2`Ehmz^93zsnp>{>IL%1daE4)0o<7v<^)0=aEpolO1#*z@Js()yu*jquC{#1scmY z&CyWbK1bx<6^{dpUY_b?Z)Mxb)O(&)>S@n`58Mmo!kinM5B#Z)zoIw$zE$K#1*Z>p zRhMn+y0d>)^w*_=3#LhC&0IKb=G<vB@2>py%IwUU@Z+g76t_%C+kA6|@PV`Yjy$uv zb?<eNX4sCI85_<l^S!vV<nwRlB@gb{9r;o7x9|_Ui`c{i6-7G~Px5j<&SbAU)$X-E z+0#l?$5X`HdSl3;Jv;hTe}-&O3D$XgB#5*7iPW?#{vXz2I#YWWSWD_m?Of^A>}fgG z)o)?<9XSJ0v#Mniuk_sg>~TS5-i{x0Z=Q;4nYwxIvP3cK3u#QbxpHRD6jJB<^cVCl zOE-EvyZS`)!*eUXPm$}fZOgi(mX#ECdD)p|y*GSc8_h9Gu++`4Qk^ZbSMhOX^0muO zeYveXD_)CTvD)6%ab3~w%)7uzyk@hE*6%!0xV5*$bo!c#D^C~8mHxDF-@9agu*IuW zfyuF!VQZ#;66ZX==cB+4p~eM|3j3-n(|a70+>c7mOIDGK$+g_E@6m!if8M>4W)9hG z)*E$BpnAfN4bQc`cC244`PL*<uxEyH_0}EAElEH6nddL7SXN<YGH+u?uH~HnD-KuP zeAxbI|7(@zG^3yL+^;-#v&b-1x$H6W&iR(l<Zc!Dz(bvTPFABcW5JWjtbH|`4y+W5 zXlYnHN9TB;-;Bp0ow|-2GS9^o^juJsE&McRf%CCDiB+p5KXz~!imym8n!VUD)M)cL zRT<$0+kTy9y>zE;LeSk08RfHd1M3$2_{Fm8)%8PtTwYsOC!Rg@A|hmyfcK@BNuG-$ zlol^-jhN&w?rn5bNb)FevZrP2z9j+sT->G~_Q-NuY#n8Cb<rhTXOpL4@1xco?m1qt zJl7`8P5D`l&AeCda%}7l`>#oRC)B6Fe!gti+VC$H6PsTb|E>SOp#Hb$%WYr39DJO7 z+kc+;)gR>*aSvP_tB%%WCozOIY}9f1u5R^z(Fvc0_dj|_oM=*GHd8OQS^9snrA~6< zdE2lDY;&%(dpF!aZYYxADxn`>RWxUN<-d^5f1#0W_N|SF)ayUJD37aBJ;5ycXZeW_ zdroL~edu~PdrAG9JNy6ctGzz|<wL*c_mWOl)M@|F6=98f*f~YzW|pJ64BO(i?xUJ& zJ1p&(Tlk8ZTKbQy^k49@|G|1cmAnJ{^%^&@F1fx{=7+<YNWHLUm!fk_ZPs(v&O3i| zv;Mn7v+r)rUzca!r*9Y24_-AMv-SN<!OLy?l-^#GE6&NDJ=yckgrwQ4kG6#x|2*XV zezUD|y8iw77rA!@ik{dzW$LzC-Dx_H>s0g)&--&u?z4W@B5^yhZF}sJ;^l2?Up-rq zzu_C}?KdxW?0qA-=Ud_d=k(d0Ruxmd^aZAC7uxXi9Ju+;{E)Kfz1f?lnQN^H1}$$6 z`M3B}{IWmoOn+8+)LA~UcMKKj^gmsH$YD~5)_+rt|E-2A7G7X??VKZ|D8%vn*BPcm z-UZH2CPX{L_}t@2kvbPu^)Oamk*E5M>MA3qdZ$3{HMQRMHk{3#7g;mJoCWvUvU$xu zxc<MxYqhLrWh?b#>tD{gxcTBtxzC9Y{k|T(9RFtdholP(RVF#+JWB5j_cuM?b2RwN z>8s)&R6oR;?PHUE6Z7HOL-(cS*45e8VSBg6vVSm_ICq8fPoSjYZQEzBZVPcKPrj{Q zpXuK`+4FMo7jcPAGjrAC?iy&i71>BND=FFNeQB;Z5q6R5chix>-A#Kd12?lVpG=g^ z&Dda+|7lHLhf+2VqzTRQdCkfdi8_}LuD^40>D$@d;%5!^N!DLp=gv@fQKh$#|Fo^` z0gkfl9Gj=T(f1|I{;;<3GIv(QUvm{n+GC`)ZsudR`!!pZSAF`ISGiQ3%kQQf<0Kwq z&z2bvEGEfG#Gn3WwyXL3le3JR-i1?d-gA)fpYrU~<dcTsTi4b`Mc<R^j6Pkk&|E*X zRa-t*WWkh*Q|=e@ZCPZt*lspIP^(|@J#otp?clDXihFvOuY13HGrN;@ap=kgVF7Pf zJgH=;Fl}5d)S&hL_7o;@%kMkVPeyd^I322MRPExk#o|HtwmOd$-XgC|pG4kusYv}J zwDLeiD;uAKM9a#hEsGyXZ9Oq1O6!;QrPhUlE2e)~9MinZZK0e~?BW3Xv=z&HOOI|` z_d)4s)e9?~pf&P_*EZ{(OjYoI`ft^}Pa>auo%X3*IBE6XzIsFVm3hTi67<EL=Q;hE zCvqpG?tJgh+;jQtu6f02(?4n4n|-Us{g0?r=%Z8%Pw_0@T&J)#2Rir9sNs6L`}f^S z#-@pCbNeT3sCNw9oXYu};Zq$?Y7Jl4PKKQC%s0LZSl(~TVQ**RJhM7j?qkcdQo+af zbYvM#Pq{~L+q2GAc+ulHU1diT_D`E<G5^$fz92=V-hlmh>~h=atwQ}pa;KIrz4g{N zBFN5RwISz8h3P&4F;WVe>>`sHq_k!SA5a!N^Y+v+{rheD`&V~u-5%u>zUI7{fDTi9 z49k)X8`i){J8joK5v}LqvP*k&#Kz0Q#Cd-dN4&xT@$iW<`H8#vjei_`D#h?VzfSM_ z3z^-1ix2MW{<}gjl#^k`qyyG#a-|pyS1B;B+T<E$WD+Wn5<Q{aXyM-aBNr7cdxebb zH%_}~GdW0sE9*M@r*j?~w|%Q#;G%ykCEBle$+mE3anEVHmwyVhT<nrp|LT<)|D{~< z>({zuSxa~8?Y!qJa?sF=rD(!)mPre=C#9@-b77NA*fgD~SA9d-pJcr3GBe=KT_CjV z$bs7uCI6Hnd$I-9>S`aos*_Eb|1A2*ed(#Ex)0CZF@Jsi&bsd#Z|{BoZj#o6w+XDr z&zEL3XiSq{A1_|P^6tQgpZV*B+YLVo#2vo=B<s4?r=Xd}u?zAc9idvIkNet|GVK0- z_t)36`xHBc@_9nT<QR_WWjl9Yt#C|Kb>BWkQ9pZ?THfOBGZ`~qP20pK6PYaX^k<z> z*^XrM!=X(~g3R{}6&4#=aYS(U-;MAP&@^)O5}p05*dSBL**i1&g}0Np<!SARd2jbF zymRD1Q?<1~l2^mBF8QDb6;os$L|q7xu(oChs9*Ij+3CQ+L%g$_*fg&NDZR_*4ZGxd z&}-3#Rh~j|%~NZFHcZl7lO;4ec!QGog3mGur5hyXJZD?Yb<iOD!z4ehxDrDhruCB+ zWVzk8*ZbPb_1^a;s|S1Ko{U26RF5nc)h8Q*ET<&>>A0*a^!+pcC4;h@8SRBz=1rNn zyRN*tbaQol?n~XTCq3@e_FJ>QU+VvSu|c+)_`genm4WXLE>Qj;KmUjRF5!Ql_4Ct; zS1-M(`(V1?5+47$Ki``*f8E~)?oiaQIbM1BPR?n`!8IoAH?MGOF07k<Yhu%ic}_EW zlV3QnZP8Ki6!B<Dc9<tUK`U48xWgpP2^{R3Y|IrxZ$<MpE(z#!+4S$}W|p9po2F+< zm_A=s@FYM<=E~PQ3qnlGc&7eRSzDnt$+snJk-|fl-|qdK>$<YT3-!86lDN~W-MCle z6$Tvqw6N&nTRGi%+eHdoUp<=Fudz_$(7joggt#AVkC8vRmfPj-xsA+a(>5l}KGc0` z@zDia7yf%)uA{#2e_8qD<SAk;LTajK*f@&&-ySQn_#fCVn)+x_{fGBbnh#QM)fY|q zq?h~IQjbBdl~==IQpqZhNg9(lBpaDjPA>0KnW@w{L6k$$(=v44l7M+GCwN*4z7*v; zSZ)Z3|8r{d5g|eA2`|^Cd0+BcK7%{8e_Ng`_ZhjskLl0_QGA>in*Kgz%51XdSlLvu zX7*a6%Po7Ct+~3)`&gp_<KthYCz224G<!W!Tu^PpmCB*_GUcFZV8PX;$!!lN`HRIE zv4+QHsk2Ql+BC;|;hfcaz9P=6C2PM#JPh6J^lQ#T*8t18mEM1(cNMH!y~J(ewB9YN z^DW-rcsqIjmgTCiH&6K5c{9@Ssm9M47hL-Kdj;3?7ks^88?g1u`#{sV|3B1(*XMkn zvF#s&{|T-iUk}cU{KgbF@0IZGzl(Q^mwk=a?Gr6;Kc{m^LE*LOv8l{zlF6Q83zkl1 z-QvPn8`7{YDt3>eeZyncEj|#g^B%?WmSol~PL^LLGVY4fyvep#sV}^GanP4S$5{>s zBU)ZB6YAPyk+yfMQBHE7U8!}Pz~QW$F>0%KUfuCC=WEX0OB@mB&Dj2ktVy?=?e=xw zA&=#}lW(hqNE_^2yW;5E4GMO4kqaF@ziv=VUUgcD<z)z`<D!-iMjQ)UI`z8+o&>A1 z%oI9wTA@W~*+E~Y0KZb#fEQgKf;bj#@GP9nBW0wyZiVZ_NltT@I4G<wG(I+0Vdck{ zx5~|q{i%3kUHwLTc1GqJ2O-mqGD7Yy8(fZUnb_+1vc*s%kSFYL!qrvYypf`PlFdd( z6HIx+bT3|+;8edyB1A)eP1nIJ)^e#UOZy`m7YHS~icAVhme#xYdD66}Ygwz~di;I) zWQ0CWGu(SJ%Sw4}$#bEtw;B&CTM5~R99SUn=|DnioNUuW!S*%DAG$Q6r!Ag!Y~8~~ zp49N5*faI(;@@XAYsj5AyT|(Q#iryxyz91ZzP)^>?V-nAr_}#~$A@B{PWH)XOJtho zXkQ<<V_S1ti@0gF!33FW7uyQleCA!{4NU1>sJLQM(#gI=F}62Z5Btu^O+Wp!a(}*L z@$I70bI~?mp8smTyPu_^`U8VveZ-Ar*5%VVHn#pgaCl1I;@yiUUOf}rXV+Mt_50hC z@cO^Mrv83aSEhL5!gA+ZF?L`7YjNBP2sEt>SdjQ<rLZ`|k@RQZnm+#Dc}d*Nm~~Fx z#?Omm5e4zBYcG23KE8c-@f}0LzsvFrd<#D>I$-4-mz<hyk??ils!g+0SFc+0c~aWU z+mlq8r%l$XD2?FGQaWLo&CXb#?|ktrZ^|96Yy3Cd=UM7pWnc2RFn7tegNDabD<Y@< zNsQ$FbovX|8n?IZuWfGd1YY+%yLD3G+b`aI1)M*P-CT46mFo2R`locnO9+O4J=)U| zvCQR9%p5aK!TknG>t4A_@hm^oJ*A^O&#!Yzho<0lmm>%F-Cb%v`(|2c@>Zv#ubw}) z_3QkZDpYJLRJT*_?UNG`OVsqdj%}S-XsO?(6P2f9d?ItzNzM57=C`U>_fNfYz%R&I z+Ve=})-}u9?JleP*Kvq<xGnJ9z0CjC-N(u~|IM=MCVPFn^K0?@3nw4i6!3S-y{NgU z{&=OeG^fn{<O}k@wohdHKjYS~oFxzLANat!|F?H`&dqo?CG!bp-b$kDl*M?0YhzU8 ze%`6R(fWPOcGc_m+8WcRCG5V@_bTjx{FY7c6ARr^zJIx~pmf0^AL|dQ!8H?w%HlZo zdCl0c{n6?=>u;M6gl86i^*$2L`uY{$98Zz-C6ny->C6#yxPDNZU7r7ti&p2<4W3(L z+9j2@|NJ;ZvUkR2!vM*<H!Et|<~MZN$++>&ds`B{e%{H0Uw8i7Uw>i$-!3nP>$n#2 zywP*`zTWS%fNL7pYLWhyMx6{Jh2WWwqu0MERBBJvd9(94*PVvRza}*Ptj#HNZ}a}Z zZ(gtD_<xno;rWLg9!|Cw{Q7y-7q1EIT0i_JKCDbs;5wz<mOts=^7!2A+qd7}{{EM- z?VXo*qIDKO<z7?#!^KM`YwMg=^HhVd9T9v9O|u^xuas`Qb2!ple~)%o_pKeA`o|pl zKM3nCyPmp%X}0hNA>;Wq)r`@<IDWlxS*`cywUCFb!>ZeBR&u;o%4^)`-Ch~#eA|rm zZUTFoNkZ!F2@!{j*w!eX{&itO+oqG!zg1*2_U5a9<J@!e((DR;|25AyypVpN9~}KX zoLhS4SMhD{*NQE>`+eD(8~eAY@7w*!{?_H4dl^36JCyhSr9kfaZOzYTJZZlB`wo-- zwETy^w^rZSQp4`{qHn+d%<1pFXHQ-%`6guJ`C}Ftexe?|JQGi?+{xC~we8CS$P|!& zf7d7bh?wl@|5;rhh-&?x-|&b3LdnJ$y_jUyU9T4IpUBW#|28yOpelQJob5Atk1EgO zDPK3)L|17#7w6|zZ(H;1<JXIqm*;JpA^FQ~-RWIFX13T&7bsf)xBT9jzB^jGZ{E$l zTy&}`L+zeP!KFK2`yvF~&*oP9t88t`{wJ|Q`t<T&!LQX+3NPd?SsW7L@j(1du*bW1 z-(M(aNOZhjsu=0GcZ+Sv(uF5a3$5nZbm&x@ZA$6MX$SL}eJ`^#UuWGad;Z#r-k&j? ztOk}lo`@c>dAv8C(S`Zm4yF$GwvO#i7Y%PM<35zXu{d{StM24unk|{CEqPmWUtE+j z_R_bMJ@7M;dD^}oJW+FAY;K?WkHPQ8=CbY4NnyW#-n0GfYP|P@mM~}1tH*a9do?YR zDst4ad2==(W+~(OFV|1{&u+{wi+vJVEBexq|DAYs+vVP^^_RuH%defAFSY8{l<qwq zQ@&)KycojdWP7Yo{GXBOGS_bxf@{_vXYna~WM`x2`LS6org9F8l}zD+&L-8(Z0jx7 z<a9Hw=3aE-)GVc!tL!8)cI`MQpb}&jVbS_FX1#+}w#(r)+dl=Ib~n1BDx<u3VV+;k z8k;+}Ci0Xo?a()Q;p<ivDqU(+Z8dYX)4A<8RqtM#aMtvJ{hy2Hc{(pNM{FvzSwA=8 z<?Xh88R4_GXDRA+`fFJHeQMliy5+>=8I_&qY)+bl@}87YNsC)%>~FL^uvtl<bL)(v znpc8O{IC8y{<UB6pWXJ<ulkz8x9dxP*K;VXU&ZwGzr~vW>{~jvfBM;^aKC4#-R3VR zBp+|xcjdlL!w!dIflu-o%51;r``x~n{76ehbGu-L_lMW<;oly;-1>IMgQv0lHlL2o z)p_gs$>#xo)49jX;@CH4+0OB2`DXliI=8|Voxe!E=m%97MC)c=k$-VgwL-6I>uXJc zqfPe<kH7Hguk5c`v)7eRetPNksio}Gx3KL$x|Owj-b20Oue{frcGiBH{>|jFpqlkL z^P-N%!}~8QvS|t(lrUbLvE#ACNg>0g2(@-wRhG;JQ*LwzR-N~PFAL^9@u=(Et4W79 zGrL}CbG~`4((%NXnvU6~50}h3EvPuXYe%BN^?rw#?ajT0JxxcxFM0iCOJUCH#Hf?e ze?Hcv`ot7}Dcraz_<60c23ys)R1uSx{qF=8tQKE!usVMGy(`C5HhpzF{q1aP_Xk_6 zW`UdK_8Sc@ZJp(AR}n6=b=TKU9TUMBU$$QVbUgk|EB~>>+pay+sAagfd(-im8{%)T z{1)b2{>|WDj(zKdM+J&I3UoldIK-6J#MxR;RxW0#Z{=au(_Xy$_aZLCgsN@74Wt)$ zr5=@M&(EvV`}{ygpChB;{iCalffE@TG&uJhzO{_;!$K~j1xnE=s?Nczj@wu(HReye z^hdD9{o|}Fim8Dd5k<ORca_QZrnjBqXs+THJC8i4<@7vYk^cPY_EU3g*q>|MEULQ} z@~ok|+0<;_r(eG(ypmSmBCXoue<?(tbC;55+bKTX(}}4kgCg&SlseQ*TbIFn`2w3( z;I3|Ai#aM7Gg{~L3~#=@SH9g_*kb+T*hLT210OtF`EF(!NA;;zvzFbnI#vc8y&zLO zd-we_izZdi_gj#(B4V4`OXo6;lWN+t`_5!dQ#s7Dep_NDbM({hMUR3N?us93E6}<T zAu2n!wB^s+N6$W8@1C6{aP#|z+V6F~2iwDD2i~e{W>7hOEkJ;wAtmlYgGW9?Uy>&C zwQH<#;<?S{>^oh4od~>qHU9sZKZ_t63e*dN<kEH>Yh1oT_VkIbDqAdile|TKX*oYg z4P~3W{=~Esr>;4qm^vuFx$rFa>ZGF!6*HHL?LM@Adm+oGXDfKw+@GAvof5Te@p?6H zm2aiY^W#kT&TvFOSjBtjU;mlUf+we+*~8bp6*_q(C>X>4w)4gAkXYs(XXcp0({w(> zazzOHW^&Bv$cgA%8@*~uJona^db^ABnO^OyoBsQt{;!nKH{jW;>New`$2`~mRqmJX zF;1_#{4afR{`p_;*3`2(cbe6jJdAT)Y?yj3O6kY@6VX<GCKs=jul?cI!gTJ!^Qj)| z!VFz_`?X#QY(0_J@2lRXa$0J^VaAA=jPqr^)-1EOv6k@=idfRVYt8HQN~4)`9GO4w zv%W5-t9@Mgh<Mr-RmM2RKE1eY-)uhk@7Qf<wR>+>b?Hw*jqEeCXMf*scv*eR2IKwz zt4fPmpS^ATX?%G8)6A?tD}MJcHuh!nzQIsnz2VGCseJ9GrKgx3rB@wZsKKvt^kMs< z12<+*+PA=OPku?41iR7Kzf1?aU02SiNJ;i>*=rue99*{eBeNyj&TkWRjSk1^&SBuM zef*JywSE5<=j!Cc@p^j{YIrZLmWsK;u_nDTY?D*A#KEhp5A1SHIjXcf%yiS*>E&Ow z(w6tFiQ5>=Vt8?7lc_f24W_n*U1dwv-fX{`6K=gm`1W_1SngeU7VCJY?)tsx;)|n~ zyqtf%eSXldc;o92Q(v8z?fp@gcSun&$y9`=T0lgAbE~C|#ww=8Q4;wKLO)F$l;&G_ zXl3y9K3{985Ri4*b{=nlR;%CjrS}B3-h66yQ*`@{iSwQ;`es%1Y?suUQkUM+joT(C zN0^n&>yh34*Re76Mo`AS+Zt6KZKA2gbLR-Qbm(s7aIi?Smb5<i`ty`*y)Mr^p7$=N z6jXTH$Y}W4RBu~-zQWGyjPdKK%}1msWpFAxEaO<Aw^~i`LdgaTMiCPU^M5%30kHzP zcJ1dU>Tte1nU@qdvukp!nd*d{8|F9P`?%<P*rNl>91b&xue)z3yHLGs_MIffh0!55 zU0#aa6?c7?cyO7<FWGk;ZBovUauSaw<{D~lke~g^c9+8w)@SqLZ@f;7Ut6*8;hmYB zWx-u*pM4j*)q3jHMzt9et~*V)w%DcZzaZ(K@-2rJ>)h{GZx;uMe0`B;dums6*||p& z*?b$7CMhz{ln<+6-grasSF~7BmQEqdyvZ}t%ir$~{qph2teE;)cBlMLTUbmDF<(`1 z`Nz*=H#IE(-DG&Ia?FtbyjJ$JiCc}2-;LQ=V|Ci3eTqiAjT4_{AfKnD%F_ud7Ac(F zb+epLO>ve}Y@edpzC>nHk%y4XrXzjfUCv!0Z6LKll9P%&PAPU4oak9HvGwMXL)}w+ z<z#1voZ59K$jtMmO6ufHvzc=(wzDi>!t~Uz$V)3A$j{SK)zdGs&)#gFQ{$%-cTOt5 zxMucr;uLqGhZCR1Y?$1$NmD%Ml$P|JgPxVM<d3ON+Txy)%r~*+ucEV?N0YP6rKOw7 z@=vkJXclk0vZ;};A@s%(X4!3p!FO&ZF8Vn0QQ(G9m+cNY-aPrT6Mwlr{<Qsk?O(pF z?j}FmzXh+A6iuBl@nDdbg~BpH)wx28RJvAJ8F4KYRGlxhD5YzK)g}I=0;=<b`h_(6 zZ}qR(#K-6varM1Gfy)M~FLu8_H-xtGUNPCUB-lwTHDc$)P(J^&ITo^0@A-%B-!<v0 zYU9-@jsH|%G-&QFXJ$}jo4m>GxCXPvDsGou5~s@}uDqWkSmk4_67WI&RNR-v$63OU zZe49K{bGN~RNm8^UNwuoKFH|g+r`~bTTrl{d3&tIj-!tb&-j}6PefMwaIkh!;BLte zuDji;_bn{gmTfZo>=R|xso$mEJu7*nxh+wMX@9b1rwYs6xi?z>TYQM@dX(Pw=yOFt zALE558+(njBKV%$zbdwNGx@jMZc>Jt>G48^2`82vGW>Y;aIWl{W)G`C0Z$PZmRI~N z3X}XrT#Q%+8-KAdc5D%5o#^HmQs}SHtMb(4x=HK0%%{CuGdWDf<qK*IR;_J0W!w^Y z)M+Az_p<G?bUkP5wr#SRz_v5sTgK~a6A$q0<I)NK4&KPd=lxs8A-|D_%l^cTqaO;) zvwSQZa(A$7cxBEkBiJx&GqVhX`|%`UjzZPBTI*E0R$HB6QC#;V_~=xh!qE1o3P+}v zt=e%(V_lZ9T0(*5@?8>IC5CGb?`sIW+B5Z`$HdU}Gavp`(%yb@A!xURsI(N8-4e>D hpt~hrIPzCrXqNl3fZZ0#Jlg+XUN7{E7J~-|0|5AFOd|jQ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.8.0-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.8.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..86bf040fdef558afb682d4aa0d41e2cbf4958787 GIT binary patch literal 88162 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≀rW;DlsxaORk-=Roq6-IYrZGs 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 MU}*JWWME(b0It$gO#lD@ literal 0 HcmV?d00001 diff --git a/dbrepo-analyse-service/lib/dbrepo-1.8.0.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b0c21d94d641cdddaede16449367638abc78d5e8 GIT binary patch literal 97755 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±N%zn*Czgikg|`$Cvti@^D&j$nhspf5Y#( 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 A+W-In literal 0 HcmV?d00001 diff --git a/dbrepo-analyse-service/tests/conftest.py b/dbrepo-analyse-service/tests/conftest.py index 3418998a94..6c3745526b 100644 --- a/dbrepo-analyse-service/tests/conftest.py +++ b/dbrepo-analyse-service/tests/conftest.py @@ -73,7 +73,7 @@ def opensearch_container(): with os_container: client = os_container.get_client() index_mapping_path = os.path.join( - "..", "dbrepo-search-db", "init", "indices", "database.json" + "..", "dbrepo-search-service", "init", "database.json" ) with open(index_mapping_path, "r") as file: mapping = json.load(file) diff --git a/dbrepo-analyse-service/tests/s3_config.json b/dbrepo-analyse-service/tests/s3_config.json deleted file mode 100644 index f270753cdc..0000000000 --- a/dbrepo-analyse-service/tests/s3_config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "identities": [ - { - "name": "admin", - "credentials": [ - { - "accessKey": "seaweedfsadmin", - "secretKey": "seaweedfsadmin" - } - ], - "actions": [ - "Read", - "Write", - "List", - "Tagging", - "Admin" - ] - } - ] -} \ No newline at end of file diff --git a/dbrepo-analyse-service/tests/test_determine_dt.py b/dbrepo-analyse-service/tests/test_determine_dt.py index 824fbfcf47..72cf915e52 100644 --- a/dbrepo-analyse-service/tests/test_determine_dt.py +++ b/dbrepo-analyse-service/tests/test_determine_dt.py @@ -1,8 +1,10 @@ import unittest -from api.dto import AnalysisDto -from clients.s3_client import S3Client from botocore.exceptions import ClientError +from dbrepo.core.client.storage import StorageServiceClient +from flask import current_app + +from api.dto import AnalysisDto from determine_dt import determine_datatypes @@ -47,9 +49,11 @@ class DetermineDatatypesTest(unittest.TestCase): }, }) - # mock - S3Client().upload_file("datetime.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("datetime.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="datetime.csv", separator=",") @@ -95,7 +99,10 @@ class DetermineDatatypesTest(unittest.TestCase): }) # mock - S3Client().upload_file("datetime_tz.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("datetime_tz.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="datetime_tz.csv", separator=",") @@ -141,7 +148,10 @@ class DetermineDatatypesTest(unittest.TestCase): }) # mock - S3Client().upload_file("datetime_t.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("datetime_t.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="datetime_t.csv", separator=",") @@ -188,7 +198,10 @@ class DetermineDatatypesTest(unittest.TestCase): }) # mock - S3Client().upload_file("datatypes.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("datatypes.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="datatypes.csv", separator=",") @@ -209,7 +222,10 @@ class DetermineDatatypesTest(unittest.TestCase): def test_determine_datatypes_fileEmpty_succeeds(self): # mock - S3Client().upload_file("empty.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("empty.csv", './data/test_dt/', + 'dbrepo') # test response = determine_datatypes("empty.csv") @@ -219,7 +235,10 @@ class DetermineDatatypesTest(unittest.TestCase): def test_determine_datatypes_separatorSemicolon_succeeds(self): # mock - S3Client().upload_file("separator.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("separator.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="separator.csv", separator=";") @@ -228,7 +247,10 @@ class DetermineDatatypesTest(unittest.TestCase): def test_determine_datatypes_separatorGuess_succeeds(self): # mock - S3Client().upload_file("separator.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("separator.csv", + './data/test_dt/', 'dbrepo') # test response = determine_datatypes(filename="separator.csv") @@ -252,7 +274,10 @@ class DetermineDatatypesTest(unittest.TestCase): }) # mock - S3Client().upload_file("novel.csv", './data/test_dt/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("novel.csv", './data/test_dt/', + 'dbrepo') # test response = determine_datatypes(filename="novel.csv", separator=";") diff --git a/dbrepo-analyse-service/tests/test_determine_pk.py b/dbrepo-analyse-service/tests/test_determine_pk.py index 4e960d39c0..b2e730edc6 100644 --- a/dbrepo-analyse-service/tests/test_determine_pk.py +++ b/dbrepo-analyse-service/tests/test_determine_pk.py @@ -1,22 +1,29 @@ import unittest -from clients.s3_client import S3Client + +from dbrepo.core.client.storage import StorageServiceClient +from flask import current_app + from determine_pk import determine_pk class DeterminePrimaryKeyTest(unittest.TestCase): - # @Test def test_determine_pk_largeFileIdFirst_succeeds(self): # mock - S3Client().upload_file("largefile_idfirst.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("largefile_idfirst.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('largefile_idfirst.csv') self.assertEqual(1, int(response['id'])) - # @Test def test_determine_pk_largeFileIdInBetween_succeeds(self): # mock - S3Client().upload_file("largefile_idinbtw.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("largefile_idinbtw.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('largefile_idinbtw.csv') @@ -25,52 +32,65 @@ class DeterminePrimaryKeyTest(unittest.TestCase): # @Test def test_determine_pk_largeFileNoPrimaryKey_fails(self): # mock - S3Client().upload_file("largefile_no_pk.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("largefile_no_pk.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('largefile_no_pk.csv') self.assertEqual({}, response) - # @Test def test_determine_pk_largeFileNullInUnique_fails(self): # mock - S3Client().upload_file("largefile_nullinunique.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("largefile_nullinunique.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('largefile_nullinunique.csv') self.assertFalse('uniquestr' in response) - # @Test def test_determine_pk_smallFileIdFirst_fails(self): # mock - S3Client().upload_file("smallfile_idfirst.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("smallfile_idfirst.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('smallfile_idfirst.csv') self.assertEqual(1, int(response['id'])) - # @Test def test_determine_pk_smallFileIdIntBetween_fails(self): # mock - S3Client().upload_file("smallfile_idinbtw.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("smallfile_idinbtw.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('smallfile_idinbtw.csv') self.assertEqual(1, int(response['id'])) - # @Test def test_determine_pk_smallFileNoPrimaryKey_fails(self): # mock - S3Client().upload_file("smallfile_no_pk.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("smallfile_no_pk.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('smallfile_no_pk.csv') self.assertEqual({}, response) - # @Test def test_determine_pk_smallFileNullInUnique_fails(self): # mock - S3Client().upload_file("smallfile_nullinunique.csv", './data/test_pk/', 'dbrepo') + with current_app.app_context(): + StorageServiceClient(current_app.config['S3_ENDPOINT'], current_app.config['S3_ACCESS_KEY_ID'], + current_app.config['S3_SECRET_ACCESS_KEY']).upload_file("smallfile_nullinunique.csv", + './data/test_pk/', 'dbrepo') # test response = determine_pk('smallfile_nullinunique.csv') diff --git a/dbrepo-auth-service/init/.coveragerc b/dbrepo-auth-service/init/.coveragerc index a387be8425..75f7db52f9 100644 --- a/dbrepo-auth-service/init/.coveragerc +++ b/dbrepo-auth-service/init/.coveragerc @@ -2,8 +2,6 @@ omit = # omit tests ./tests/* - # omit ext lib - ./omlib/* [html] directory = htmlcov diff --git a/dbrepo-auth-service/init/app.py b/dbrepo-auth-service/init/app.py index 65252a5ccd..55fa08cdae 100644 --- a/dbrepo-auth-service/init/app.py +++ b/dbrepo-auth-service/init/app.py @@ -5,22 +5,30 @@ from requests import post, get endpoint = os.getenv('AUTH_SERVICE_ENDPOINT', 'http://localhost:8080') system_username = os.getenv('SYSTEM_USERNAME', 'admin') +readonly_username = os.getenv('READONLY_USERNAME', 'user') -def fetch() -> (str, str): - print(f'Fetching user id of internal user with username: {system_username}') +def fetch_keycloak_master_access_token() -> str: + """ + Fetch admin access token from the master realm. + :return: The access token. + """ response = post(url=f'{endpoint}/realms/master/protocol/openid-connect/token', data=dict({ 'username': os.getenv('AUTH_SERVICE_ADMIN', 'admin'), 'password': os.getenv('AUTH_SERVICE_ADMIN_PASSWORD', 'admin'), 'grant_type': 'password', 'client_id': 'admin-cli' })) - if response.status_code != 200: raise IOError(f'Failed to obtain admin token: {response.status_code}') + return response.json()["access_token"] + + +def fetch(username) -> (str, str): + print(f'Fetching user id of internal user with username: {username}') - response = get(url=f'{endpoint}/admin/realms/dbrepo/users/?username={system_username}', headers=dict({ - 'Authorization': f'Bearer {response.json()["access_token"]}' + response = get(url=f'{endpoint}/admin/realms/dbrepo/users/?username={username}', headers=dict({ + 'Authorization': f'Bearer {fetch_keycloak_master_access_token()}' })) if response.status_code != 200 or len(response.json()) != 1: raise FileNotFoundError(f'Failed to obtain user') @@ -39,7 +47,7 @@ def fetch() -> (str, str): return (ldap_user_id, user_id) -def save(user_id: str, keycloak_id: str) -> None: +def save(user_id: str, keycloak_id: str, username: str) -> None: conn = mariadb.connect(user=os.getenv('METADATA_USERNAME', 'root'), password=os.getenv('METADATA_DB_PASSWORD', 'dbrepo'), host=os.getenv('METADATA_HOST', 'metadata-db'), @@ -48,12 +56,14 @@ def save(user_id: str, keycloak_id: str) -> None: cursor = conn.cursor() cursor.execute( "INSERT IGNORE INTO `mdb_users` (`id`, `keycloak_id`, `username`, `mariadb_password`, `is_internal`) VALUES (?, ?, ?, PASSWORD(LEFT(UUID(), 20)), true)", - (user_id, keycloak_id, system_username)) + (user_id, keycloak_id, username)) conn.commit() conn.close() + print(f'Successfully inserted user: {username}') if __name__ == '__main__': - user_id, keycloak_id = fetch() - save(user_id, keycloak_id) - print(f'Successfully inserted user') + user_id, keycloak_id = fetch(system_username) + save(user_id, keycloak_id, system_username) + user_id, keycloak_id = fetch(readonly_username) + save(user_id, keycloak_id, readonly_username) diff --git a/dbrepo-auth-service/init/tests/test_unit_app.py b/dbrepo-auth-service/init/tests/test_unit_app.py index 4fb38ac2f4..fc454cfa3e 100644 --- a/dbrepo-auth-service/init/tests/test_unit_app.py +++ b/dbrepo-auth-service/init/tests/test_unit_app.py @@ -23,7 +23,7 @@ class AppUnitTest(unittest.TestCase): mock.post(f'{endpoint}/realms/master/protocol/openid-connect/token', json=self.token_res, status_code=400) # test try: - fetch() + fetch('admin') except IOError: pass @@ -33,7 +33,7 @@ class AppUnitTest(unittest.TestCase): mock.post(f'{endpoint}/realms/master/protocol/openid-connect/token', json=self.token_res, status_code=401) # test try: - fetch() + fetch('admin') except IOError: pass @@ -45,7 +45,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except FileNotFoundError: pass @@ -57,7 +57,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except FileNotFoundError: pass @@ -69,7 +69,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except FileNotFoundError: pass @@ -83,7 +83,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except ModuleNotFoundError: pass @@ -98,7 +98,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except ImportError: pass @@ -115,7 +115,7 @@ class AppUnitTest(unittest.TestCase): # test try: - fetch() + fetch('admin') except EnvironmentError: pass @@ -131,6 +131,6 @@ class AppUnitTest(unittest.TestCase): }], status_code=200) # test - ldap_user_id, user_id = fetch() + ldap_user_id, user_id = fetch('admin') self.assertEqual("7a0b4b7f-77cd-4f28-a665-2da443024621", ldap_user_id) self.assertEqual("5b516520-67cb-4aa0-86a6-d12f8b8f1a20", user_id) diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index 9fb1271c4361841c3d4061e536d23bc16b590d0e..5632a876e9fcc5546b307f7a795c6fbf2087d302 100644 GIT binary patch delta 647 zcmbR1Ki6L<z?+#xgn@yBgW+9LebkW-7T$?MO7*Ax4jTyUaX)4MgFQ#x#Me7dgfHOZ zgj0|AZ8X1<^(f?<+S2;|*-iqYOnlp}-}`v3;#zrvZ|l4t+*bKf(HlZk3QJxJaG1uw z;VxshjVgP1<<^%MH(XNKk1R6Y`pkRp!~W=yhqrY4_$IFGVd9$lWAZ{N?q%NXx2HL~ zXTQ7n)$O5XebEy;X|MTeYx80cPV2r_9ro@fm+5Y{uEn#{qLZ7a{d;EJSf?y<S^m@i zCpB?*#d3VNd~Kbw`>x-NQ{1o0*w!+rHZ0jVmDzt?@D<B1pEUfB1sYiKpBAc;__=O_ zNy72N=lfW)<!$Us79?DFVI%$R`-PV0_oQy`<^3%<zx#r-o#)Sb_HTive>QCu6XmU3 zKkL!e3kFMgKJU_Q&63`EaPO+<8$FF2o-5n-AK1u0>+s>qT$_ci<vM!~-IK{&ZngGV zr=I%r;<>2>)6OsVoTuuwG}3hSvk9RueN-3pf1elo_vxK{DHThXn=JenYcnNVSRCb} znkE*0;R8hk7Xt$a1H-!{#`?*d7*&|xCe=^A$*2paIho|Zv=);p^Sh+_$w5q7V7i{k z1Wa#Z@&d~<GoJ<1mzldk^yWmCIZPnNCU$O45WSgCphgg^qgQbjnATF7%mIu0$w!r} zz=BN5CLq<5EtPG-bfvN$m|mr93YLGQ3{fYq;sWNUsYHS0532-&X-U;wFx{yd3#MPH UI)Z6kwOwHKuhcTYbf~%q0G@my1poj5 delta 647 zcmbR1Ki6L<z?+#xgn@yBgCVG(AgXd{`Ll^aO7*w%9xDjcZhun$fSqA^>D?pwzTXqg zU%7hezki&#$8lpJOLF?>@2Y;US6y7SoBzN8nP)QR3i!`m6N%V2iGN%1(itmteDiD> zCr>=>tobfcK|RkV?~OxT%&I>f5#P2M7Nu_cl<6+9K6d#@!%bUVA4GWCMdz&$S@vnm zYn3m1CN};_sGoRlqVV^l5x;C+`aJjE7*(d&@k-%Z$`StuCO@yflgc{zasSVA3*tGh zUXB0s|K!h2`?Qa?Rf>D9{r-FJrqX~r?{zI%S2S!b-P(R&pZhyo*4jzSFRMt!9!X_o z_NlR7vFX9G!~K0O+49XcWeY?u%u<s7&VS+9^Lvrk|4V)s-WRa3z5Y{?+Wn3GH%{F? zXXzyOneq0g?N19cWS{%SYrcuvyOh~XHfOoR(Iv+|>U&5ndiJB>=8XeSPR!?8pSeLj z>I8R0%H}&y0z$$w#6I_Ih;oprG;@zhvAi~Q=KObie>}Uq^Sw#NH<w+#a+CgFG2-fM zy0_Iu`SKH9P(*MsFmNz11QjqAOy0z(!W>voF!?5<E|}(Il4A}kD449pqza~kn6$uj zJ(CHT-p1qwR>#bI7EE7e?goi(PGp(G1QOW9&dmuH;1j431TiM}D$WAaT1t~SU~xbB zsFD>}kV)ADq-(OJvMrddRMrEFuTnMz(~p!P>f}{i!2C3oD6qQ2D#2h{QZ*MW-l-Z3 X=D$>R1oL&(c7f?vY8hZURNVsr#}yvA diff --git a/dbrepo-dashboard-service/.coveragerc b/dbrepo-dashboard-service/.coveragerc new file mode 100644 index 0000000000..9fd61fc166 --- /dev/null +++ b/dbrepo-dashboard-service/.coveragerc @@ -0,0 +1,7 @@ +[report] +omit = + # omit tests + ./tests/* + +[html] +directory = htmlcov \ No newline at end of file diff --git a/dbrepo-dashboard-service/.gitignore b/dbrepo-dashboard-service/.gitignore new file mode 100644 index 0000000000..cadb5f2657 --- /dev/null +++ b/dbrepo-dashboard-service/.gitignore @@ -0,0 +1,135 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Generated +coverage.txt +report.xml +clients/ +api/ +dashboard.py +access.py +panel.py + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# SQLite db +*.db + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/dbrepo-dashboard-service/Dockerfile b/dbrepo-dashboard-service/Dockerfile index d5f64a82fb..fcc698ed27 100644 --- a/dbrepo-dashboard-service/Dockerfile +++ b/dbrepo-dashboard-service/Dockerfile @@ -1,8 +1,29 @@ -FROM docker.io/bitnami/grafana:11.5.1 AS runtime +FROM python:3.11-alpine3.21 LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" +RUN apk add --no-cache \ + curl \ + bash \ + jq + +COPY Pipfile Pipfile.lock ./ + +COPY ./lib ./lib + +RUN pip install pipenv && \ + pipenv install gunicorn && \ + pipenv install --system --deploy + +RUN adduser -D dbrepo --uid 1001 + WORKDIR /app -COPY --chown=grafana:grafana ./dashboards /app/dashboards -COPY --chown=grafana:grafana ./grafana.ini /etc/grafana/grafana.ini -COPY --chown=grafana:grafana ./ldap.toml /etc/grafana/ldap.toml +USER 1001 + +COPY --chown=1001 ./ds-yml ./ds-yml +COPY --chown=1001 ./app.py ./app.py + +# non-root port +EXPOSE 8080 + +ENTRYPOINT [ "gunicorn", "--log-level", "debug", "--workers", "4", "--bind", ":8080", "app:app" ] diff --git a/dbrepo-dashboard-service/Pipfile b/dbrepo-dashboard-service/Pipfile new file mode 100644 index 0000000000..6c446aaefa --- /dev/null +++ b/dbrepo-dashboard-service/Pipfile @@ -0,0 +1,28 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +flasgger = "*" +flask = "~=2.0" +flask-cors = "~=4.0" +flask-jwt-extended = "~=4.5" +prometheus-flask-exporter = "*" +python-dotenv = "~=1.0" +jwt = "~=1.3" +pytest = "*" +dbrepo = {path = "./lib/dbrepo-1.8.0.tar.gz"} +gunicorn = "*" +pydantic = "*" +flask_httpauth = "*" +grafana-client = "*" + +[dev-packages] +coverage = "*" +pytest = "*" +testcontainers = "*" +requests-mock = "*" + +[requires] +python_version = "3.11" diff --git a/dbrepo-dashboard-service/Pipfile.lock b/dbrepo-dashboard-service/Pipfile.lock new file mode 100644 index 0000000000..8ef3ff818b --- /dev/null +++ b/dbrepo-dashboard-service/Pipfile.lock @@ -0,0 +1,2224 @@ +{ + "_meta": { + "hash": { + "sha256": "911a375e6d52635530a1278e4186660b395093e16a092a223fd7050c6241bedc" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "aiohappyeyeballs": { + "hashes": [ + "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", + "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" + ], + "markers": "python_version >= '3.9'", + "version": "==2.6.1" + }, + "aiohttp": { + "hashes": [ + "sha256:04eb541ce1e03edc1e3be1917a0f45ac703e913c21a940111df73a2c2db11d73", + "sha256:05582cb2d156ac7506e68b5eac83179faedad74522ed88f88e5861b78740dc0e", + "sha256:0a29be28e60e5610d2437b5b2fed61d6f3dcde898b57fb048aa5079271e7f6f3", + "sha256:0b2501f1b981e70932b4a552fc9b3c942991c7ae429ea117e8fba57718cdeed0", + "sha256:0df3788187559c262922846087e36228b75987f3ae31dd0a1e5ee1034090d42f", + "sha256:12c5869e7ddf6b4b1f2109702b3cd7515667b437da90a5a4a50ba1354fe41881", + "sha256:14fc03508359334edc76d35b2821832f092c8f092e4b356e74e38419dfe7b6de", + "sha256:1a7169ded15505f55a87f8f0812c94c9412623c744227b9e51083a72a48b68a5", + "sha256:1c68e41c4d576cd6aa6c6d2eddfb32b2acfb07ebfbb4f9da991da26633a3db1a", + "sha256:20412c7cc3720e47a47e63c0005f78c0c2370020f9f4770d7fc0075f397a9fb0", + "sha256:22a8107896877212130c58f74e64b77f7007cb03cea8698be317272643602d45", + "sha256:28a3d083819741592685762d51d789e6155411277050d08066537c5edc4066e6", + "sha256:2b86efe23684b58a88e530c4ab5b20145f102916bbb2d82942cafec7bd36a647", + "sha256:2d0b46abee5b5737cb479cc9139b29f010a37b1875ee56d142aefc10686a390b", + "sha256:321238a42ed463848f06e291c4bbfb3d15ba5a79221a82c502da3e23d7525d06", + "sha256:3a8a0d127c10b8d89e69bbd3430da0f73946d839e65fec00ae48ca7916a31948", + "sha256:3a8b0321e40a833e381d127be993b7349d1564b756910b28b5f6588a159afef3", + "sha256:3b420d076a46f41ea48e5fcccb996f517af0d406267e31e6716f480a3d50d65c", + "sha256:3b512f1de1c688f88dbe1b8bb1283f7fbeb7a2b2b26e743bb2193cbadfa6f307", + "sha256:413fe39fd929329f697f41ad67936f379cba06fcd4c462b62e5b0f8061ee4a77", + "sha256:41cf0cefd9e7b5c646c2ef529c8335e7eafd326f444cc1cdb0c47b6bc836f9be", + "sha256:4848ae31ad44330b30f16c71e4f586cd5402a846b11264c412de99fa768f00f3", + "sha256:4b0a200e85da5c966277a402736a96457b882360aa15416bf104ca81e6f5807b", + "sha256:4e2e8ef37d4bc110917d038807ee3af82700a93ab2ba5687afae5271b8bc50ff", + "sha256:4edcbe34e6dba0136e4cabf7568f5a434d89cc9de5d5155371acda275353d228", + "sha256:51ba80d473eb780a329d73ac8afa44aa71dfb521693ccea1dea8b9b5c4df45ce", + "sha256:5409a59d5057f2386bb8b8f8bbcfb6e15505cedd8b2445db510563b5d7ea1186", + "sha256:572def4aad0a4775af66d5a2b5923c7de0820ecaeeb7987dcbccda2a735a993f", + "sha256:599b66582f7276ebefbaa38adf37585e636b6a7a73382eb412f7bc0fc55fb73d", + "sha256:59a05cdc636431f7ce843c7c2f04772437dd816a5289f16440b19441be6511f1", + "sha256:602d4db80daf4497de93cb1ce00b8fc79969c0a7cf5b67bec96fa939268d806a", + "sha256:65c75b14ee74e8eeff2886321e76188cbe938d18c85cff349d948430179ad02c", + "sha256:69bb252bfdca385ccabfd55f4cd740d421dd8c8ad438ded9637d81c228d0da49", + "sha256:6d3986112e34eaa36e280dc8286b9dd4cc1a5bcf328a7f147453e188f6fe148f", + "sha256:6dd9766da617855f7e85f27d2bf9a565ace04ba7c387323cd3e651ac4329db91", + "sha256:70ab0f61c1a73d3e0342cedd9a7321425c27a7067bebeeacd509f96695b875fc", + "sha256:749f1eb10e51dbbcdba9df2ef457ec060554842eea4d23874a3e26495f9e87b1", + "sha256:781c8bd423dcc4641298c8c5a2a125c8b1c31e11f828e8d35c1d3a722af4c15a", + "sha256:7e7abe865504f41b10777ac162c727af14e9f4db9262e3ed8254179053f63e6d", + "sha256:7f2dadece8b85596ac3ab1ec04b00694bdd62abc31e5618f524648d18d9dd7fa", + "sha256:86135c32d06927339c8c5e64f96e4eee8825d928374b9b71a3c42379d7437058", + "sha256:8778620396e554b758b59773ab29c03b55047841d8894c5e335f12bfc45ebd28", + "sha256:87f0e003fb4dd5810c7fbf47a1239eaa34cd929ef160e0a54c570883125c4831", + "sha256:8aa5c68e1e68fff7cd3142288101deb4316b51f03d50c92de6ea5ce646e6c71f", + "sha256:8d14e274828561db91e4178f0057a915f3af1757b94c2ca283cb34cbb6e00b50", + "sha256:8d1dd75aa4d855c7debaf1ef830ff2dfcc33f893c7db0af2423ee761ebffd22b", + "sha256:92007c89a8cb7be35befa2732b0b32bf3a394c1b22ef2dff0ef12537d98a7bda", + "sha256:92868f6512714efd4a6d6cb2bfc4903b997b36b97baea85f744229f18d12755e", + "sha256:948abc8952aff63de7b2c83bfe3f211c727da3a33c3a5866a0e2cf1ee1aa950f", + "sha256:95d7787f2bcbf7cb46823036a8d64ccfbc2ffc7d52016b4044d901abceeba3db", + "sha256:997b57e38aa7dc6caab843c5e042ab557bc83a2f91b7bd302e3c3aebbb9042a1", + "sha256:99b8bbfc8111826aa8363442c0fc1f5751456b008737ff053570f06a151650b3", + "sha256:9e73fa341d8b308bb799cf0ab6f55fc0461d27a9fa3e4582755a3d81a6af8c09", + "sha256:a0d2c04a623ab83963576548ce098baf711a18e2c32c542b62322a0b4584b990", + "sha256:a40087b82f83bd671cbeb5f582c233d196e9653220404a798798bfc0ee189fff", + "sha256:ad1f2fb9fe9b585ea4b436d6e998e71b50d2b087b694ab277b30e060c434e5db", + "sha256:b05774864c87210c531b48dfeb2f7659407c2dda8643104fb4ae5e2c311d12d9", + "sha256:b41693b7388324b80f9acfabd479bd1c84f0bc7e8f17bab4ecd9675e9ff9c734", + "sha256:b42dbd097abb44b3f1156b4bf978ec5853840802d6eee2784857be11ee82c6a0", + "sha256:b4e7c7ec4146a94a307ca4f112802a8e26d969018fabed526efc340d21d3e7d0", + "sha256:b59d096b5537ec7c85954cb97d821aae35cfccce3357a2cafe85660cc6295628", + "sha256:b9c60d1de973ca94af02053d9b5111c4fbf97158e139b14f1be68337be267be6", + "sha256:bccd2cb7aa5a3bfada72681bdb91637094d81639e116eac368f8b3874620a654", + "sha256:c32593ead1a8c6aabd58f9d7ee706e48beac796bb0cb71d6b60f2c1056f0a65f", + "sha256:c7571f99525c76a6280f5fe8e194eeb8cb4da55586c3c61c59c33a33f10cfce7", + "sha256:c8b2df9feac55043759aa89f722a967d977d80f8b5865a4153fc41c93b957efc", + "sha256:ca9f835cdfedcb3f5947304e85b8ca3ace31eef6346d8027a97f4de5fb687534", + "sha256:cc9253069158d57e27d47a8453d8a2c5a370dc461374111b5184cf2f147a3cc3", + "sha256:ced66c5c6ad5bcaf9be54560398654779ec1c3695f1a9cf0ae5e3606694a000a", + "sha256:d173c0ac508a2175f7c9a115a50db5fd3e35190d96fdd1a17f9cb10a6ab09aa1", + "sha256:d6edc538c7480fa0a3b2bdd705f8010062d74700198da55d16498e1b49549b9c", + "sha256:daf20d9c3b12ae0fdf15ed92235e190f8284945563c4b8ad95b2d7a31f331cd3", + "sha256:dc311634f6f28661a76cbc1c28ecf3b3a70a8edd67b69288ab7ca91058eb5a33", + "sha256:e2bc827c01f75803de77b134afdbf74fa74b62970eafdf190f3244931d7a5c0d", + "sha256:e365034c5cf6cf74f57420b57682ea79e19eb29033399dd3f40de4d0171998fa", + "sha256:e906da0f2bcbf9b26cc2b144929e88cb3bf943dd1942b4e5af066056875c7618", + "sha256:e9faafa74dbb906b2b6f3eb9942352e9e9db8d583ffed4be618a89bd71a4e914", + "sha256:ec6cd1954ca2bbf0970f531a628da1b1338f594bf5da7e361e19ba163ecc4f3b", + "sha256:f296d637a50bb15fb6a229fbb0eb053080e703b53dbfe55b1e4bb1c5ed25d325", + "sha256:f30fc72daf85486cdcdfc3f5e0aea9255493ef499e31582b34abadbfaafb0965", + "sha256:fe846f0a98aa9913c2852b630cd39b4098f296e0907dd05f6c7b30d911afa4c3" + ], + "markers": "python_version >= '3.9'", + "version": "==3.11.14" + }, + "aiosignal": { + "hashes": [ + "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", + "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54" + ], + "markers": "python_version >= '3.9'", + "version": "==1.3.2" + }, + "annotated-types": { + "hashes": [ + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" + ], + "markers": "python_version >= '3.8'", + "version": "==0.7.0" + }, + "attrs": { + "hashes": [ + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" + ], + "markers": "python_version >= '3.8'", + "version": "==25.3.0" + }, + "blinker": { + "hashes": [ + "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", + "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "certifi": { + "hashes": [ + "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", + "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe" + ], + "markers": "python_version >= '3.6'", + "version": "==2025.1.31" + }, + "cffi": { + "hashes": [ + "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", + "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", + "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", + "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", + "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", + "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", + "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", + "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", + "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", + "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", + "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", + "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", + "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", + "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", + "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", + "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", + "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", + "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", + "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", + "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", + "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", + "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", + "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", + "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", + "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", + "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", + "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", + "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", + "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", + "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", + "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", + "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", + "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", + "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", + "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", + "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", + "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", + "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", + "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", + "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", + "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", + "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", + "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", + "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", + "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", + "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", + "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", + "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", + "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", + "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", + "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", + "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", + "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", + "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", + "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", + "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", + "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", + "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", + "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", + "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", + "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.1" + }, + "charset-normalizer": { + "hashes": [ + "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", + "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", + "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", + "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", + "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", + "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", + "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", + "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", + "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", + "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", + "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", + "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", + "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", + "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", + "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", + "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", + "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", + "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", + "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", + "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", + "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", + "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", + "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", + "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", + "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", + "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", + "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", + "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", + "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", + "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", + "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", + "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", + "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", + "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", + "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", + "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", + "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", + "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", + "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", + "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", + "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", + "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", + "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", + "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", + "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", + "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", + "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", + "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", + "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", + "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", + "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", + "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", + "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", + "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", + "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", + "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", + "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", + "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", + "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", + "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", + "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", + "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", + "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", + "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", + "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", + "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", + "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", + "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", + "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", + "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", + "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", + "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", + "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", + "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", + "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", + "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", + "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", + "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", + "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", + "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", + "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", + "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", + "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", + "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", + "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", + "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", + "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", + "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", + "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", + "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", + "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", + "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.1" + }, + "click": { + "hashes": [ + "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", + "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.8" + }, + "cryptography": { + "hashes": [ + "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.2" + }, + "dbrepo": { + "hashes": [ + "sha256:7b9a70cf1bd9d623e52ada74d5585df53716353d509f5d905f1b431dd91c28d6" + ], + "path": "./lib/dbrepo-1.8.0.tar.gz" + }, + "flasgger": { + "hashes": [ + "sha256:ca098e10bfbb12f047acc6299cc70a33851943a746e550d86e65e60d4df245fb" + ], + "index": "pypi", + "version": "==0.9.7.1" + }, + "flask": { + "hashes": [ + "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc", + "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2.3.3" + }, + "flask-cors": { + "hashes": [ + "sha256:38364faf1a7a5d0a55bd1d2e2f83ee9e359039182f5e6a029557e1f56d92c09a", + "sha256:493b98e2d1e2f1a4720a7af25693ef2fe32fbafec09a2f72c59f3e475eda61d2" + ], + "index": "pypi", + "version": "==4.0.2" + }, + "flask-httpauth": { + "hashes": [ + "sha256:66568a05bc73942c65f1e2201ae746295816dc009edd84b482c44c758d75097a", + "sha256:a58fedd09989b9975448eef04806b096a3964a7feeebc0a78831ff55685b62b0" + ], + "index": "pypi", + "version": "==4.8.0" + }, + "flask-jwt-extended": { + "hashes": [ + "sha256:52f35bf0985354d7fb7b876e2eb0e0b141aaff865a22ff6cc33d9a18aa987978", + "sha256:8085d6757505b6f3291a2638c84d207e8f0ad0de662d1f46aa2f77e658a0c976" + ], + "index": "pypi", + "markers": "python_version >= '3.9' and python_version < '4'", + "version": "==4.7.1" + }, + "frozenlist": { + "hashes": [ + "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", + "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", + "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6", + "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", + "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", + "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f", + "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", + "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", + "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", + "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", + "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec", + "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2", + "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c", + "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336", + "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4", + "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", + "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b", + "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c", + "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10", + "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08", + "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", + "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", + "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f", + "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10", + "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", + "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", + "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", + "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", + "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d", + "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923", + "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", + "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", + "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17", + "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0", + "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", + "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", + "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c", + "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a", + "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0", + "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", + "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab", + "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", + "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3", + "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", + "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", + "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604", + "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", + "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5", + "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", + "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", + "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", + "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", + "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d", + "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", + "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3", + "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", + "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", + "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", + "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf", + "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76", + "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba", + "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171", + "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb", + "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", + "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", + "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972", + "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", + "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", + "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9", + "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411", + "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723", + "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", + "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b", + "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99", + "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e", + "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", + "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", + "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb", + "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", + "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", + "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca", + "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", + "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", + "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f", + "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5", + "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307", + "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e", + "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2", + "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", + "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", + "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", + "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "grafana-client": { + "hashes": [ + "sha256:2477a47b923fd0637947e620b0b777c641af18a3025464fa4505783dbf05dfcc", + "sha256:8cb61bb2a87ec07bca10974df276b9a1a95bfdb63f3a696f065692ffc9b8c389" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==4.3.2" + }, + "gunicorn": { + "hashes": [ + "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", + "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==23.0.0" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, + "idna": { + "hashes": [ + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.10" + }, + "iniconfig": { + "hashes": [ + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "itsdangerous": { + "hashes": [ + "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", + "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.0" + }, + "jh2": { + "hashes": [ + "sha256:038091480cd1544e9389b0adbb1b1645a797689dcb68ceae7e45eec96ed24497", + "sha256:0c8e336df8ed1687590695f4469f480eeb4159bf13bb6193791c6530fe114b49", + "sha256:0c9bf2d5e4ef45c1686c6f76935e7ca263f5eae4de92bf5d1873a0e737e4eb7d", + "sha256:0faf6e96f74d27b8ca816b40217904891f91b664ed1c0388737949ceb50ac15d", + "sha256:10ea7f497e6226372e1d4fdbf42c8381f4887819a643ab930bff4072ad298d84", + "sha256:11650f7ed77ee1df30f25d6b3b74b2fa1c94124e074fd455abafea3cbc913d53", + "sha256:12ead3ee3e9c7caa00356b528a5cc7fe210fbe2060628af6e19ed76b8416572e", + "sha256:136b3c5b08883681fcb58f12393a5bbfa422d6e2d5ba887e263e776874276bc6", + "sha256:17d6e1691154ea9f726e43dcb717df48e56c66b5a01c90ad675c6494c36e5be1", + "sha256:19cb987915cc0d321746a12f2a693d087ffb721c37ac9a153cc088c57d4d90eb", + "sha256:1cdf15de698c4026e64fd914fead3180e52bf2a7bcbe44a3392404582dbf2d22", + "sha256:1e81e1c64e33506b8508ba5e3c7c139b2577e78b079c2c16a8e7a02a161f1080", + "sha256:2226c76e4ff2149c5d9f94bed22bf9c4f3411d38cc53d4a7ddfbe0899c8b558c", + "sha256:2837412fb7b684c6ce7392c8bc57440c6dbadaf1bde7a53144381f7df7083c1c", + "sha256:293f0f3da3c391e997e0d55fdb85540e98a8b0406622bb4ba57fb7617697f31e", + "sha256:2b9cc6c0239215a349d28c192fa4c4e7a7348eee7980531525c01bffe39eea80", + "sha256:2f3ad679f84ff236a0d7b71ddc4b3c09fe467abee2f1a86671f0cd417be5352b", + "sha256:358cad2f328c52c15756cf32b0ad17afb0d617e7cdfe93d59aa2616966d825b7", + "sha256:3663712305b509f79c002c8c0ca9994f716cadba576f5a59632dda1aec1ca8c6", + "sha256:41794820ccca039ca2ead6245f30b34601dd1456eee5b5dde620672bb989e79d", + "sha256:44b7e64aff542471c474c24f771eae5efd9152da02a12556f7cb7607020e1420", + "sha256:45770eb0990166026538d3c2fd7d92f17cfde13ca6567570c4baec3ce9162936", + "sha256:498060078a4d1b458e9381fefb027d85329397b50d65287712b3d48233e20836", + "sha256:4c2f18f337c2393f84e45e5011c8b02697b81638b1cec49da60a01b9ed067695", + "sha256:5162d6e475d2762035fb8ea25982bcbec6c58715e33bd0951499f743cd90b110", + "sha256:51e8c890bb59008c95b3a552cefd8bd9ce50a7466a6c920a78cf586e885d7449", + "sha256:56ad3839ac6ac5fd3d023cf59d4b04264b74bb4cb44c0780faf51d6b5ff38fbc", + "sha256:5821638ef0d7c973071810a6786f59b305172197f7e7e469a2ce169e7f4978e3", + "sha256:5ac1b2d379f4d40c13dcce537e69704452943cddbe991fd54a84fdb2da9026d5", + "sha256:5b465d4311b0429fe6fa85df8e2cfcb038c9fface95396dd14e838ecabaaadf2", + "sha256:5d8656b98057329bd03d968aac8d5198389cf51517511295cfc4cb827a507e39", + "sha256:5dcfb3e823ef4b91b70b92848570d1d8cfd584304bd2bd54272dc100c9494def", + "sha256:5e40d23ea43f683f3a7c032dde391104f609b05c21b6d284101120b51dbd50c1", + "sha256:63a01522bde161c713f7fa5ee5d850fee6386fc386073490ebcd438f14579cf2", + "sha256:6b2a3d7756035dde13571f4ad232629b78b7f35c2cd5fda7b464079fc697db3a", + "sha256:6b3be1a6bf6c965aea3b4e3a40df9d2c134c516d89c76cf2b6c81f67e6c5c6ed", + "sha256:6c7bea3357f2dc653756e6da55f66cd21c73d3875c8f3dc4e8d196a876252de0", + "sha256:6e6c8e229507cf29333a2f491cbaa7dff5b8a4a3e613af8090ccce9ce3e4f7a0", + "sha256:6fad27f2a63884ee45d491aebec4b1f38752cd6aaccc625038c21e7f43c02c49", + "sha256:71bfef52547c2b8b145897fa8d1b5142bc52313cfa38c0742e0ef755f0d09c60", + "sha256:72370d312323282b1bf74426e53fae861a310d7ae519b419da46673c38e7d147", + "sha256:76c7d36043a9c478b0c846fcec7da5cb095983722473e503e0122ccd170182b5", + "sha256:78d8a81ef51edb9a2f278a6fb278789b49e304b12bb21bccf2fe7e344f71a9fb", + "sha256:798a6b159ce32181a5e7ab7611c17d1080e74a5541fec47f961b728dab25a76f", + "sha256:7e370567f66a57e2c0e3ae2afcc6f126e1d6babd36831cfd0caad279b05c1c88", + "sha256:8004b845f606b95a8b17efa112aa10b327e46e95dcda604a257b4633d4ed45c8", + "sha256:80b20bf9ea4e709b3b9ae364ac298dfa872b084c186e5c1d60b0b79c79a7ee7e", + "sha256:87303f4bb1b493997f911a4f126123ccd2827d3a2e7dd2390cc6143fbc75805b", + "sha256:8d423f4631395b92dceda39f481a463498131ac02a58581124a44495491f715b", + "sha256:94ee262192db50fb9c069a0be7bb1a426fb1b43af26ce12bf4c6c30e13f46b56", + "sha256:960e4be2e7de340300ab4bcc2b45bed46be1d62330575b8265e6602dbcb9a14c", + "sha256:99397d5e1da6b345cec3e6125e2902b0e6864eb8eaa4be43a2013f059c502c93", + "sha256:9abbb8c1bad08817bad62ae1ea76c01bdbd0ee8c827d05f3ba038c9f6d6f14bb", + "sha256:9c0b8fadf80bc70d341032f92702bda1b0ed78c01e9c495f0df701938c99bcf5", + "sha256:9f977da9abae170eebdcf02bda33727c342fad5dcdbc08498bfdfb6cc6c65489", + "sha256:a6be712ca39d5e9c89b705bc9800be36739436fefb8d0b52b2d332f7d6d22a01", + "sha256:aa434418d6ee44b0ba3a5a407bc9e1543cf496328f43f149e9b58f74a63d5c21", + "sha256:ac4f778e32f7de0ba63346893a4af87c2280ffc1783f594a117be51d908a10da", + "sha256:ac85d65ee369c09b2904b55078ad589961e2e2e03c810963d35a26e6a3931425", + "sha256:ad5d78c664d39960435d4162db31117c8945ba74fb0c414e79ba85a8bdeafdec", + "sha256:ad91f57c3485d87a8edee558dafab0f08c716857d748731c0998dcefe9d3fd5f", + "sha256:afd255d42b340036883ca95bded553b29065b064e2fe5db64ad5988517db9694", + "sha256:b1c2c74f100a0c2110a8e30445554ae331860d32f145c60a2a1e1c27702022a2", + "sha256:b49a8c71378d40d43c6a56eaa536d7823baa43c27c93e082aeb60a9717be0c10", + "sha256:b5f52611323e8e35705e6750a760f32165b41c052d22da154ae343871e7cd50d", + "sha256:b6bf99ae529ac359263269710356d3ddb173c15d8f8dc8849ae794ab811e5cd0", + "sha256:ba361bf87c4701f11241be92c99ef5cf916865dd225955cccb2376bf76717b3c", + "sha256:bc351aa2158575e68943d8e1d5531719ad86bf6607776627ed5a1a60657664af", + "sha256:bd6eb7b1e12e4dd0b75cab1b023272f1333494add5ad61deedac738af1ffeede", + "sha256:bf8852595f5e2d2b072e24c29394b5aca7fba96ecc8656d56660535f9e9872c9", + "sha256:c1dd66541569a2bdbe92589cc96a89f470b20d168f2238fd463e1b59ee3e2d49", + "sha256:c36a7a004cba4e370d0675826eeefe4e42a256638b6b1432263ddb4af317bc02", + "sha256:c886cda61da4d39010be84802bed11bc75f03e8a6094cc18016957a2c80254d4", + "sha256:cc7aa83946f80c66a5d2dea7e165f15aa3eb21e7b74b24d8f850afc0d44bb00e", + "sha256:cea9c4bef70d1358bafec6019164abce362f4de15d79d1ecd64ae31c1749d77a", + "sha256:cfe1951e80869695857986be104a40a1e7fa8ec7de05f86bcbd7bd20854be764", + "sha256:d36cf6f139da3279644794fcfda18af425c8bb122ef9c2e7c762a937bbf7b0f4", + "sha256:d81308faaa9393b7e6ed20718d465c4c2b73c24d5e4826024961acf4b87b1524", + "sha256:db51ea1f9c5ac790848bc271fcdf4108ad1b77a77c6949a96320477962cf7ba5", + "sha256:dd05c18c920a15e00d7a52df37bffd3930fe2c004c690f9422b20e12077e6dbd", + "sha256:df05918a11e1db0198d00486e36673b4b4a89390e4458ff9479b4908dde357ac", + "sha256:e4c31dccf6be131709e545d0258eb5b75c5fac304857ad3976331c6740e8b9d6", + "sha256:e60954d673040430802b29fe5bba698e262182b5ba5f302ff4458e39f8101881", + "sha256:e60e2d2c88a0552e61c37172fe377f6a8abf479130a445314886de4a360ba940", + "sha256:e786f773ddc153846b2ebdb854011cfd1f7c874b8ee79cced3706801341c9f5d", + "sha256:e7cd91548fb95b69edd376f5204e27115ac7d093ec7d80066123a5bdb31c71d9", + "sha256:eaef2ea4f5602aefaaf3d6e8235f3b9ffde35aff15aac1c16cc802f6bbf0a3b5", + "sha256:ec8c5ea93a03775fbadd08462200cf34ce617ec75a032abfa44fd6d3a00e5424", + "sha256:eddeb8574bc9d9abb8491d4a46b60e553c2cea235b80373756acb06568101175", + "sha256:eeb300b0e4b428aab2f70d785cad4306529262af6de8c8c5fe6a4b41a674a434", + "sha256:f39d71ece8e97cf069e4154868eaac1256b133fe23e0459829432e4bb6406472", + "sha256:f4840ddad2b9d53710e92361391944da89e3576641a290066a1719520059247c", + "sha256:f70723a00bcbce0f9a216853139955be45da35741335eb3afead304e77662560", + "sha256:f829cf2ba5b553e6529d6238928c07096f1feb47f4ad536b7f06bca6cc77173f", + "sha256:f96386910467725895f7972939a6faabd6e96b1de0cc2c092e4bd2c40e956e25", + "sha256:fe259a9d6f555bc79aed9bb4b9a7fff73db443b4c483e4a81a428c8a2860428b" + ], + "markers": "python_version >= '3.7'", + "version": "==5.0.8" + }, + "jinja2": { + "hashes": [ + "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", + "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.6" + }, + "jsonschema": { + "hashes": [ + "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", + "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566" + ], + "markers": "python_version >= '3.8'", + "version": "==4.23.0" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", + "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf" + ], + "markers": "python_version >= '3.9'", + "version": "==2024.10.1" + }, + "jwt": { + "hashes": [ + "sha256:61c9170f92e736b530655e75374681d4fcca9cfa8763ab42be57353b2b203494" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==1.3.1" + }, + "markupsafe": { + "hashes": [ + "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", + "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", + "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", + "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", + "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", + "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", + "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", + "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", + "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", + "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", + "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", + "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", + "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", + "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", + "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", + "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", + "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", + "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", + "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", + "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", + "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", + "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", + "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", + "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", + "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", + "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", + "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", + "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", + "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", + "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", + "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", + "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", + "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", + "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", + "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", + "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", + "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", + "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", + "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", + "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", + "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", + "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", + "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", + "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", + "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", + "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", + "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", + "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", + "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", + "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", + "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", + "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", + "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", + "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", + "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", + "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", + "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", + "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", + "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", + "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", + "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50" + ], + "markers": "python_version >= '3.9'", + "version": "==3.0.2" + }, + "mistune": { + "hashes": [ + "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", + "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0" + ], + "markers": "python_version >= '3.8'", + "version": "==3.1.3" + }, + "multidict": { + "hashes": [ + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" + ], + "markers": "python_version >= '3.9'", + "version": "==6.2.0" + }, + "niquests": { + "hashes": [ + "sha256:a32183c98100723e7a308f6a13f4a1b857a9f38465bed7c6f06bfbaf307f0bf1", + "sha256:ec7d9424bb3481e6a72a4543a7c043bb829d534aa906380c2e9a1c5a0cc24e47" + ], + "markers": "python_version >= '3.7'", + "version": "==3.13.1" + }, + "numpy": { + "hashes": [ + "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", + "sha256:0d54974f9cf14acf49c60f0f7f4084b6579d24d439453d5fc5805d46a165b542", + "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f", + "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", + "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0", + "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7", + "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", + "sha256:218f061d2faa73621fa23d6359442b0fc658d5b9a70801373625d958259eaca3", + "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146", + "sha256:2fa8fa7697ad1646b5c93de1719965844e004fcad23c91228aca1cf0800044a1", + "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", + "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc", + "sha256:4ba5054787e89c59c593a4169830ab362ac2bee8a969249dc56e5d7d20ff8df9", + "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592", + "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00", + "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", + "sha256:7051ee569db5fbac144335e0f3b9c2337e0c8d5c9fee015f259a5bd70772b7e8", + "sha256:7716e4a9b7af82c06a2543c53ca476fa0b57e4d760481273e09da04b74ee6ee2", + "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392", + "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb", + "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8", + "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", + "sha256:8146f3550d627252269ac42ae660281d673eb6f8b32f113538e0cc2a9aed42b9", + "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0", + "sha256:892c10d6a73e0f14935c31229e03325a7b3093fafd6ce0af704be7f894d95687", + "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", + "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", + "sha256:9eeea959168ea555e556b8188da5fa7831e21d91ce031e95ce23747b7609f8a4", + "sha256:a0258ad1f44f138b791327961caedffbf9612bfa504ab9597157806faa95194a", + "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39", + "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4", + "sha256:a84eda42bd12edc36eb5b53bbcc9b406820d3353f1994b6cfe453a33ff101775", + "sha256:ab2939cd5bec30a7430cbdb2287b63151b77cf9624de0532d629c9a1c59b1d5c", + "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd", + "sha256:adf8c1d66f432ce577d0197dceaac2ac00c0759f573f28516246351c58a85020", + "sha256:b4adfbbc64014976d2f91084915ca4e626fbf2057fb81af209c1a6d776d23e3d", + "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24", + "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", + "sha256:bd3ad3b0a40e713fc68f99ecfd07124195333f1e689387c180813f0e94309d6f", + "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba", + "sha256:cf28633d64294969c019c6df4ff37f5698e8326db68cc2b66576a51fad634880", + "sha256:d0f35b19894a9e08639fd60a1ec1978cb7f5f7f1eace62f38dd36be8aecdef4d", + "sha256:db1f1c22173ac1c58db249ae48aa7ead29f534b9a948bc56828337aa84a32ed6", + "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854", + "sha256:df2f57871a96bbc1b69733cd4c51dc33bea66146b8c63cacbfed73eec0883017", + "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", + "sha256:e642d86b8f956098b564a45e6f6ce68a22c2c97a04f5acd3f221f57b8cb850ae", + "sha256:e9e0a277bb2eb5d8a7407e14688b85fd8ad628ee4e0c7930415687b6564207a4", + "sha256:ea2bb7e2ae9e37d96835b3576a4fa4b3a97592fbea8ef7c3587078b0068b8f09", + "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", + "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", + "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee", + "sha256:f4162988a360a29af158aeb4a2f4f09ffed6a969c9776f8f3bdee9b06a8ab7e5", + "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", + "sha256:f7de08cbe5551911886d1ab60de58448c6df0f67d9feb7d1fb21e9875ef95e91" + ], + "markers": "python_version >= '3.10'", + "version": "==2.2.4" + }, + "packaging": { + "hashes": [ + "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", + "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f" + ], + "markers": "python_version >= '3.8'", + "version": "==24.2" + }, + "pandas": { + "hashes": [ + "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", + "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", + "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", + "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", + "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", + "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", + "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea", + "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", + "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", + "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348", + "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", + "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", + "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", + "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", + "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", + "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", + "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", + "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30", + "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", + "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", + "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", + "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", + "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", + "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", + "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", + "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761", + "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", + "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", + "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c", + "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c", + "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", + "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", + "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", + "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42", + "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", + "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39", + "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", + "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", + "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed", + "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", + "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", + "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319" + ], + "markers": "python_version >= '3.9'", + "version": "==2.2.3" + }, + "pika": { + "hashes": [ + "sha256:0779a7c1fafd805672796085560d290213a465e4f6f76a6fb19e378d8041a14f", + "sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.2" + }, + "pluggy": { + "hashes": [ + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "prometheus-client": { + "hashes": [ + "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb", + "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301" + ], + "markers": "python_version >= '3.8'", + "version": "==0.21.1" + }, + "prometheus-flask-exporter": { + "hashes": [ + "sha256:41fc9bbd7d48cc958ed8384aacf60c3621d9e903768be61c4e7f0c63872eaf1a", + "sha256:94922a636d4c1d8b68e1ee605c30a23e9bbb0b21756df8222aa919634871784c" + ], + "index": "pypi", + "version": "==0.23.2" + }, + "propcache": { + "hashes": [ + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" + ], + "markers": "python_version >= '3.9'", + "version": "==0.3.1" + }, + "pycparser": { + "hashes": [ + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + ], + "markers": "python_version >= '3.8'", + "version": "==2.22" + }, + "pydantic": { + "hashes": [ + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==2.11.1" + }, + "pydantic-core": { + "hashes": [ + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" + ], + "markers": "python_version >= '3.9'", + "version": "==2.33.0" + }, + "pyjwt": { + "hashes": [ + "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", + "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb" + ], + "markers": "python_version >= '3.9'", + "version": "==2.10.1" + }, + "pytest": { + "hashes": [ + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==8.3.5" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.9.0.post0" + }, + "python-dotenv": { + "hashes": [ + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.1.0" + }, + "pytz": { + "hashes": [ + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" + ], + "version": "==2025.2" + }, + "pyyaml": { + "hashes": [ + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.2" + }, + "qh3": { + "hashes": [ + "sha256:0107f576a0524421e1b0f9e0437d2881a1835b1b6105eadd7ea0c1c9bf2da917", + "sha256:06159707895c606a321ccb5630347a2d2a44ee584f22945e5b22b0ad34f21ec8", + "sha256:06255835f99ea1af9e5d358056011686fcccbafaba893454027daa62ab6f701f", + "sha256:09b2305a954e61a9ed8b46a7a45f54e8d95ef870a47d5fd1836e14c7600d3b92", + "sha256:0a51dcffae03a89ddbab1884860569e0d1dbbf95deee47457c1fd29b4ac8d220", + "sha256:0a5d1cd881b7d43481ad60262cf3390a555e0e51751bc2af70ba4a612487e797", + "sha256:0e1c273660f9b8511c22d0b082137556e46d6a7eccf132bd82f95d29f90488b2", + "sha256:0e540cc7e7da65da30381bdb73a789a8635c6aaef98688d904eee3bc587654a5", + "sha256:10ed818f47dc522350a12641e8f2bea19ff824f8ce373c23a8e594b3481fd7a4", + "sha256:195b4ad58cf5a8da218e2368d34f47628c14581f3cc9863fc0406b32e137f3a6", + "sha256:1a80d07249c7ccbaa57bb9015b5ead0ead7ac1940cd5483548dfe56db99ce7a4", + "sha256:1cf0b18823801078d2294a0356abc2be34b4a224bea863a87029c1c97d6c34e0", + "sha256:1fac2ab4b8a2e50894b54a19416cd363defe0fb33f52754686ea58999f98dfc5", + "sha256:205cdaea9da8881b31b76eb6da5b88c9558ba96bc16a3ecf11333098ac7f3859", + "sha256:2294e78bcc40728a3a772df0f8ecf8b8756616d06dd001029016876aa4e5c9de", + "sha256:235236ab195d34e7cd18d186e46b7a4f8aceafe246bf36b42913f72627ded414", + "sha256:25eef1f2be50d79d23e01a567c719e46e4892518a5ccc96685fcb4746357320b", + "sha256:2ae147b756c3adf59699756feb9e07d4a69674f57b4e13d6c25f9d1dc3c8707c", + "sha256:2c9cdd7ea49c79b671e7de35dad61d2aa91920e2498d0c6dfa932d5e05070a5e", + "sha256:2dc9f269d7316b0a44e61ae7a11ffd8daa800b3f5ba773de2e9d8c4ee636a896", + "sha256:2f94d69edb0070ef4ec414deabfc2369aa2100b11bf4a4f2f393f2c28c4bc7ba", + "sha256:311da331e31c55afc3f4f4f2ba9d07a1d700ffb7db5aa4f58300b9f56f2523dc", + "sha256:3578844a9ff4c342a409d010f909782afc52a31680876f7fab65bf133aa3f4db", + "sha256:4032c2898b4c0ff7a25cf7d68c3b1f2abdcaf4f25cc8b6802a941a842f9a95b6", + "sha256:40abd150eddfa0884c139bd281e87ff920d4cd52d685fc4ef25ddcc77ff7a220", + "sha256:43e32602651d07f8a0860ba0a45d8c8fe9ccd537030e7632d1258f7b84881416", + "sha256:45a21d25fe17168f4db09fcaabee5dd171763ad1bd8753c257297837f5ba9197", + "sha256:45bfbb126e31ecf63ef74c249d38d07e149c0663b4a191cf9e2e3445a80758d5", + "sha256:4745667c9956bcfd74ff677edd4c73d6cb578b6b47c5fb3d246aaa223dd6a004", + "sha256:4936a5d8915866b4f08ab18018f41ed93a2593788ad0a80796aada2e23d402e5", + "sha256:4a45a9698b3bcae05f91356f50df8dab3c3fdef3187548b9c4a396a6eb6760b5", + "sha256:4b84c1ca283278e2e22a3b9e2ce8ea55c0a1797d6e86255640a1b6293fe18b2a", + "sha256:4dc88397ed7f3b46f542f87e19050a7f82267225009ce65651ac44cb55b204b1", + "sha256:4e10a872077373c71d7938fb1a7ae0561f2e79aad2b1b5323dbb6325a389041a", + "sha256:4f1b5dcb4d9da5b441e0b14216b816be7b5b5d080c2ccb957adf84266411ff6b", + "sha256:50d25182d598312197f500a65acebf5430391764e6ffcdb73d96e80c5dd06fc7", + "sha256:529c5b9e27fced27befce26e2699eca3110c576f6427dfbd26e30b7666b2d6d1", + "sha256:571da625b22e953731307539b44b2177f6ab13b6142d7698c0f28b9379ae1be6", + "sha256:5a9de89e2480b385a99613798d375e69a0a53d4575bd74b133307c8e83a84751", + "sha256:5bcc46cf89cb1036c2d029c01f360c82180329997a75728b20dc205f34114327", + "sha256:5dfa6238a6236f2bb3ecaac9befd23cee0bcbb9e497003fb3aef875e19325c61", + "sha256:6342b961b18037e3df8692e8914c576816a966bf29f913ee2728e7e838bde9bd", + "sha256:65e112c175a0b0328822dd0d19ead9ef1d7925359d154fb52e46b080945eef38", + "sha256:6f8a2b15c4dd58133e92f95d4312efd09b87ec15b881885629dff70e89f1e751", + "sha256:726f749444d1cc73c1bf221343dc6fdbde2541ffe30860d2d5ef6e310a1f5478", + "sha256:742f39cd807df31c21e035aec63f6f61e139a60545cffb16e8e87f61609d7cba", + "sha256:7840c18ec27aa08ecdd8ff23df348c124378c6f3edf9a0e02b16a5a4ce504c89", + "sha256:79d1de24d3c7345719af8333b64f19a8777dd50a059851bfcfa583c7109eddf2", + "sha256:7ba9303c5334d64b547483be92c4bbacd37964ff3abd0b1e8c82c63ec6f7b3ec", + "sha256:85587d9dfbd2f7f8622cf57f3c1a19cee441b5607a982cdf4c08ef38d45d5a36", + "sha256:8711b86e447e689d1b693419708b6ad64bf0c57091b94a3f65c6d4bd7cfb7d9a", + "sha256:877edc4db25309d86af07d992926394936f491cce84fce439961729552e942fe", + "sha256:8bb17669e362d3456bebd5c69abb0c26e8ab29c10894f123c715b0217aece479", + "sha256:8bb17a1e50e35a8d07cab784caea68b33f739391ccb5e3161afb9db0bde8faf4", + "sha256:8d4640a6bb3aa29797bdcf0c5bae4e86da5f2fbf84b67a7fad549fa34c19aa98", + "sha256:90697f3d9e4b3ddccfb31b40637bac6d44b39288cd57f78e51ff13e70916eccc", + "sha256:90f127f57c00b111ea3ffd95f4c12ad83efebd10310fd718d66771dd64e568f1", + "sha256:95f8f70bca1e880da7559ef38b7f1778a3b39b586fc829b8a7e989e912aa988f", + "sha256:9a60c102a01dfa8c5d737499c9a5d5e7c2b6642009c9b80b27f228ec50ce6fb0", + "sha256:9c7f1821ec749ea29bd9d079e4f13a552371731d0b664962a60cbb2f31d571b5", + "sha256:9f81ee66fadedbfd4d5c49e64151db3b6f353b041ddf5ab0b151340a4467e038", + "sha256:9f8e530e29e1afe9231b1100645aa5cc240b823c0e4162f70046270a3559400c", + "sha256:a0c647db3f156e8c94a63c1fa0fc4f2ce8b70f0eb12f2726e6c19493198b1e99", + "sha256:a0cda60607ab4ffc14fa8425ea7c9ae78ad60923c3c8be94d19c14f83198b1cf", + "sha256:a5bff397d49da302b5afbdf244dd7ca480a827f5de856d957df05dfd7e73b490", + "sha256:a94bd391b955b24948b2986845f9c6ad8abc709c2d57d0515daeacf16a2a3a4c", + "sha256:ad4572bd37c1a6a7a12ff47da4f3578a13e3c8ee85a1f02d2435dfdc6d9ed394", + "sha256:b13b7de1686f1b5da7526dc4f0de410a685f5cb654e984b09ddd8d14be6fffc0", + "sha256:b1724c43c5c0d08b68c3407467e07794b9adf153b6de8300d61883e8d95fa640", + "sha256:b27d29cb718df9ed006f8c75a89dd90534437761b2477dc7a4145bde0daa60fc", + "sha256:b3afa3a78b0f011ff5a09dea37d74fcea9269b318d2828f18b2fbf9dde625a71", + "sha256:bd6a61007e678284178bb00931af59f686a2a55797505e0886241050ec5c243c", + "sha256:befeca45fd7787c08a3286fb72caaccfa4c3962760981dfeb0992f5ba9be5cb2", + "sha256:c2d31b8233f406e00f180e221986f436765c3bb06839e72c898feca31fef1d4e", + "sha256:c3e2518ce442b70314892a594e21157deb13fbc436f77ad6555439cfd9912035", + "sha256:c8d5fbee607db24ef6c7b0bd08c21226d10782df4149b9d6f1f1516c7c85092b", + "sha256:cc2cc804998e852bdffcc87e8d008043ffa85efe6d3516d9784714d709f14774", + "sha256:cd8a681107c6118f60a0714671cec7b301533f25984a5c898e547a33a01af75c", + "sha256:d056831ebf3fa8116672ae970ad19a9f5f1427a2217cd0e01c1eaac5f8222668", + "sha256:d5ac3e8e3f66ff88819205dbc67e6f771cbb80529325ca9f3bc03fa00c5c83aa", + "sha256:dba15ca2da7859300ae79d2ea2eb8bb0eb827b93a2f104981783add16a97058a", + "sha256:de6cabb89248b60ea9bb9d7848de78dfb824abfdc15f52448a8efe821dd7d559", + "sha256:e02f6d1cc2005b847176dd8770fdfe90f04a34a3f094b79a8369bde0aa8f6a04", + "sha256:e514bd4b27c953c46485b2be0ecd2421aa196c5a0cd7d67f1ccec16a56b00507", + "sha256:e53464124379764f982a69f5ab34d0d5c527e8ac1e788db86a25f79045e5b18d", + "sha256:e9cf59660a543bef86de457c671c1d78ad2d88c53bb9eb3fce6ce0cb9729d490", + "sha256:edfc1bc732bc5e62fdaea268a541eb442d5e04927cb27dfd8e92ef07213658d2", + "sha256:ee8e7a66be70a18f5e0558f2f6a89e39c608f87b027234848f76a6699975dcf8", + "sha256:effb7072efef7dca10a98c24be0cc882a40edc78e293b41f5b6dc7f1952215ed", + "sha256:f04e4ee7e3c123ac7f21cee6f819cfa9b5a376e656257dfa7a4d133b3590bdd9", + "sha256:f0531c7abe963affebd3fb6cf9ea87eb8c63a0240535d81d0223945bd41be254", + "sha256:f5afd1c216315682a6bbf606618de0e3817ed8eeafc27ad7660ef2f581d4fd46", + "sha256:f93d3c74e00268ac6042c080653a34d0f0e8903697fd8dc480c1e3de81c90faf", + "sha256:fbc4e6452cc48c3e1398fe930349e2ec9ad76a2c00e729f3e797700c2f0646e6", + "sha256:fc73fc2889a01a43737c7a7c7fb9ee13aa56065b22abbed0e787cc58a3747808" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.2" + }, + "referencing": { + "hashes": [ + "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", + "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" + ], + "markers": "python_version >= '3.9'", + "version": "==0.36.2" + }, + "requests": { + "hashes": [ + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + ], + "markers": "python_version >= '3.8'", + "version": "==2.32.3" + }, + "rpds-py": { + "hashes": [ + "sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046", + "sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724", + "sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33", + "sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc", + "sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032", + "sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a", + "sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7", + "sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c", + "sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718", + "sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc", + "sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d", + "sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272", + "sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f", + "sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d", + "sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b", + "sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb", + "sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef", + "sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b", + "sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45", + "sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4", + "sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796", + "sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3", + "sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c", + "sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9", + "sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f", + "sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029", + "sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9", + "sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399", + "sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586", + "sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda", + "sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91", + "sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b", + "sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a", + "sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c", + "sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405", + "sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5", + "sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143", + "sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a", + "sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c", + "sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78", + "sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0", + "sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350", + "sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7", + "sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba", + "sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664", + "sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a", + "sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56", + "sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e", + "sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d", + "sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1", + "sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964", + "sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791", + "sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124", + "sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e", + "sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120", + "sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad", + "sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc", + "sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c", + "sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e", + "sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba", + "sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797", + "sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149", + "sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5", + "sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240", + "sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034", + "sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25", + "sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7", + "sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d", + "sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793", + "sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba", + "sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d", + "sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d", + "sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391", + "sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e", + "sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f", + "sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7", + "sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd", + "sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f", + "sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb", + "sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea", + "sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e", + "sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052", + "sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd", + "sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47", + "sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d", + "sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9", + "sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8", + "sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875", + "sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65", + "sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e", + "sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114", + "sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44", + "sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9", + "sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a", + "sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205", + "sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164", + "sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58", + "sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3", + "sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6", + "sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97", + "sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6", + "sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae", + "sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727", + "sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098", + "sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c", + "sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1", + "sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8", + "sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d", + "sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103", + "sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30", + "sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d", + "sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5", + "sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07", + "sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83" + ], + "markers": "python_version >= '3.9'", + "version": "==0.24.0" + }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.17.0" + }, + "tinydb": { + "hashes": [ + "sha256:f7dfc39b8d7fda7a1ca62a8dbb449ffd340a117c1206b68c50b1a481fb95181d", + "sha256:f97030ee5cbc91eeadd1d7af07ab0e48ceb04aa63d4a983adbaca4cba16e86c3" + ], + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==4.8.2" + }, + "tuspy": { + "hashes": [ + "sha256:156734eac5c61a046cfecd70f14119f05be92cce198eb5a1a99a664482bedb89", + "sha256:7fc5ac8fb25de37c96c90213f83a1ffdede7f48a471cb5a15a2f57846828a79a" + ], + "markers": "python_full_version >= '3.5.3'", + "version": "==1.1.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" + ], + "markers": "python_version >= '3.8'", + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" + }, + "tzdata": { + "hashes": [ + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" + ], + "markers": "python_version >= '2'", + "version": "==2025.2" + }, + "urllib3": { + "hashes": [ + "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", + "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.3.0" + }, + "urllib3-future": { + "hashes": [ + "sha256:255fa9ba873e9045a5fb2e9838e2b108be35519c29e7f3accff13ee4c417a1cf", + "sha256:7243b5bb8d8cdbcbff342bc31b885e35662c4dcfd94d097473cce1bd02944cbf" + ], + "markers": "python_version >= '3.7'", + "version": "==2.12.914" + }, + "verlib2": { + "hashes": [ + "sha256:2862f19528db400d130253a2b71c7c3616ee14e1d54bf6833bc0929d2cddd141", + "sha256:cf8e2be044b834a2670f2d4c20a93cfc674933c0070543a6f61d531439cca200" + ], + "markers": "python_version >= '3.6'", + "version": "==0.3.1" + }, + "wassima": { + "hashes": [ + "sha256:10508102696d5e2cf4df6942a8ae251c136a49dc32591e9c3f7dd007f5ea1c2f", + "sha256:1102836ba373912537eba891e7e5893532d4ee915ee2486e981b73f925f63c37", + "sha256:11887557464e0c3f9694fb16406bb56c1fb1566178cd04bfb5b4624fad183b31", + "sha256:12c855cc5b96a2ac32d405ab7de1563fc91be54108b4fb16b06d125d07ea892b", + "sha256:134e863b692c35afe8f5ccbe8082fa39963804e20439a4c7aa98510197034704", + "sha256:17f129f4d36591772d906bcc893b76b236363fda61b575067ddfa8250f84ad30", + "sha256:17f132ffbab294902f8740708f27fd995ea04182fe4b4fde20be563f8a010715", + "sha256:18bc78b2230c6f1f9ddbeb6ca38439fea4cc8f60836af4f3538ed259e60e5eb8", + "sha256:194c3fad38603618dec03307d10a4ece852516df56560e04fb2562506f79c175", + "sha256:1b18ec743ab98dcbfc221749026b23fc573891651342f20971e53bdbf56d28ae", + "sha256:1fa19a3652509edd18f693cd9c873d8f73c9d1624eae6c3bf93e561b18ae2766", + "sha256:24bdb1a2b90c215e11ed7ce82ed7eada339c7dca8e0366916e4e3215b3b9d8d3", + "sha256:27d518f0863788c826faf387326f3babb3ea95a0b908f5b3ad2bc1fcc3c5a37d", + "sha256:350b5854dfb3eeb95cd17723b0f3503de0c01454da5ae7d60f192be2009239eb", + "sha256:3b3a4c8ffa76147507f0c88c5cc8c76ef96ab93b81e49b288a3a0b94ebfb34af", + "sha256:3e00fa8ff1aef7d8aad2e1b957add6cba8549a42e415400bd72ff1b61dc9da9d", + "sha256:3f29045dd0a7c287f850f1dc3948632a2d2cf7dd7ec02271c5f248f058da5650", + "sha256:4a528244e4a0f9e01b8593b1c8a60ac1d80ce8b13fe079f44b38328e4be075e3", + "sha256:4c4f5ca102fd083aa2b05c65a1fd18175e3dc7a889525fd2964219ee3c51edef", + "sha256:52358d86195954816231d2aa8c2919b85075320b6d3ba5b96216985c3182bfa0", + "sha256:52f473233ec4d57322c6295e85b3912dc1fc400d6308a04bd427b863934aa74e", + "sha256:556cded582aef3089de889b5a6efcf6d87fabfec55d574fcc3a4ada21308d487", + "sha256:564eda7bf0420c8cbebe5e8efc15f1b27fdcb37ebc4c2f92b8461ca83381b223", + "sha256:57a0ab5aed596f129fd4ea7584336b11fbef25c07d1351e37a959901dea8728e", + "sha256:58f1fddd660da8c8f30f4b8460129e2f217c226cd1b54b1cabb6465881fd788a", + "sha256:597b0d8ba697f4319bc1f301ed31630ca783c9fe82d2a2434dd2f7f709c4e394", + "sha256:5b194f0de77a4ae7bcf217a3ccd10798e94ca430cec6307628098a61cd2ac230", + "sha256:5f5ee564f4b836ed1b70ddb187c817e8f6f1ffb521a636bb20676f07b523396b", + "sha256:601f96340e4c8071994a39a76d4278e8e1d087cf385781dba795c5334262d865", + "sha256:61bfa09f38c36f1b1e6e44e7af888bb8f9d739e86099082a3b45875651a425e2", + "sha256:67fd323b8ad0e057c06b153983d8c50f812aad979ac89b07ed6952c345f6da02", + "sha256:69cb51f629d118256da3d2373575190c7e30d3fa67c344dc655f6c8ab3e83f0d", + "sha256:6b1d7ceeede8d8eed48616d2d33ed23d2dff307d0b17c577eafdadafe86a0478", + "sha256:6b7d696155ddd7ab5739ac221e8854115d0d8171bbf805074d9484083de386aa", + "sha256:6d23e9483756b81850b82e8b7ed20fd23de22b50d6a678f765c660d4206b7ce9", + "sha256:7b0229fecc849234f2a2d11e948ac38a9bab02d201fa4d6ad43c143e18c1a66e", + "sha256:7c53050b670d702eed541503175bd5441fc4bdf3898714f8eac8c6ae9db548ac", + "sha256:7d65676f1fc138d1742f704bf490045571b9c2c48cab7d2c2076a52729c143e5", + "sha256:7db25328c40cd574e5a68ef6507c5af4d1fa2a44cb3c028ff9ca6b522f8faf32", + "sha256:83ce1b09e9eb2ae033c303b74ecc4f3186bbc0897db1d8cd9942153b0631b8e0", + "sha256:86c509900cbb90b7b75155c580b22af591b696fa059059bcdbd75bc74179df85", + "sha256:87f80d0075f0d396b73d41bb1626a2dd5607e0db4b74cb17e55d874fcd538971", + "sha256:8b719755d556649f2fbf226cf1ca8581ade114751df1facec96f94e75bffdb3c", + "sha256:8e739d4192758df6e5363791f527deb91c615d63020ee8965df4bcd1a217f9a5", + "sha256:923d3bf8770dfeb3d94bdfee1c5b5a081592de69766436a395e1e6203c19cf71", + "sha256:97772bb55cb47da3de49ca4b59309a9bd91ead730a7cfac1992932486fb41352", + "sha256:98bdfdf734144277132f34f770eeb6b0db2c4de87415f34b178adee766632f24", + "sha256:98f38b1b01e6f270b9279d76261d6f222b72ef06b025cbd4911b962bb6de4c98", + "sha256:99318b5ea78843e3c3e19cd56367216774674a99848f00a6f2dcf84e36039641", + "sha256:9c623ef06876d432dc8acc93ed3494d3453333d767b1b06bba1a016ea9d850c9", + "sha256:9d0f9720dfd0155432d23bcc3605fe5831cd0f586ede4f14ff6f3bebe8fb867a", + "sha256:9e79216760faac6395bee8ca4077a53a309312faba0f71982127ad8625861780", + "sha256:a470c908fd9baaecf41715ea3c30c57b530d598ae5e9de7e0bd532755e66bb1b", + "sha256:a634b9b79e059f45a56ff3ef6e7241662bc6f0e5a096ee6eed6770ea368e8278", + "sha256:acd8195a53d0e84ea95bdf15a2651c53b829a3ddead21b4a620b6a0c5e1ae2ff", + "sha256:addbd207df3718fc9d9de5b6c90a5e3fbe667830cf629186c9fdcafbb6578cb4", + "sha256:ae2aec9d55e108ae2d22fd0bda24450a6c13c116f9698b9e7ba2c6492c4fe715", + "sha256:af6b70ca9788964c5da5b59ca412b62db2ea7f2386a91c0117667bdd963e828c", + "sha256:afa7d60a9203db36a55b6f2868da90aaa829ab415a21fba7fa75678789aeb16f", + "sha256:b08c1931c44e3c034e645f3e3a7f4c47e8b0758fb8f09a52d1e880a307a1066f", + "sha256:b22e356914e606ff398c002b9925df4454c5deca9dbe55b3ba4a5c9b2365cf0f", + "sha256:b8c0f50397c51086df941b48057c82f85d9da000bf4fe6f4bc64c4f649b26a5b", + "sha256:bc068bcd79fe017866f536e0ad9424793220be34e3124476e17e6cb77a97e690", + "sha256:bc30f5a605a366acb7f301b3421508eaec3c1a515c960791bd776cb63d016302", + "sha256:c0d246b3f8a771578279eab9cfcb820dedefd3dd5dc0e34b37a337fe46271fc0", + "sha256:c0fee0a8593028bde17b57527b1ac21fea74f209b3522363e3ba0197ffaa6323", + "sha256:c139d5b103bb1f085d8918815d62ad946224a658ac1a7cc1b93dc44bd498ff9a", + "sha256:c25235cec12c0e38b4104268e312c9c2f3527ebc126d296cff69ea7aa13434dc", + "sha256:c7429d038dc383966c692e752010cbb4d5dab0e515f231aa01cd746aed9db359", + "sha256:c85cd2e64967c0dce2927ad7c62c090aae6d6b7f9e3a6b9fb91f58b890ea6adc", + "sha256:ca04984df012020dd846599b8555666c544982c2a91dc6135565e6708624eb71", + "sha256:cb7d43c07d58ba13736e70dc3e064496efeb1ed4475a28afb26b7a3b030b89df", + "sha256:d018e05cb61eed3050d45bd0c0ef9b75420899f6ae254e68e7f2ef26975098c9", + "sha256:d24d42881eb74729b34014e2e87f3a4d0419c43db309de2dff3f39118716865f", + "sha256:d6e17f218af856ca22c30d1a1ac58b19bccf768b8589eb8d6e45e1f1ff258404", + "sha256:d855d0be1759c5efc404c04977ee48a8b6260aef6441e72c10973924dbde5a73", + "sha256:dea0dcc0e50978ef73be8cb384694b71a6e64b46847ee7decad96dc85fbf650c", + "sha256:e1e9228049cf2442ac486a03a0d543c5dff3089a915a3e39ab809b22672e1d76", + "sha256:e26d052a248d5be2257d848d6078d932cc1fd4e8226639f550344d0a7a2b8813", + "sha256:ee6ccb8197936a308a4034c90a42b30b37c46b7cbda66101d439d6983f59b368", + "sha256:eea9c37b45e73cebb4670afd1779db138eeff0f84ffc0871d2fb90c04c8d3aa8", + "sha256:f195bf641276261e6bc5f79f52601850c9bdbff8af401483b4805dbff535ed30", + "sha256:f264827618400ebeab16708c8acf7870f693b03bfb4d7e95253eb9b35074db5c", + "sha256:f44ccd2eaa433ff1a10f70242dc33315fc192b81664696154127bdd66ad7d3b2", + "sha256:f7a6068d8857c403e105e62132a00e9d9d401bd0efbff7f8b5b5bc8ab768a2d8", + "sha256:f9886176fe4bf1ac008c02adb5bd103f1191799f1897777d203ee44f615325a5", + "sha256:fa1f38d5583d283b40f998e2f13471bfa952e0c423ff95ec2ec329f3e1898107", + "sha256:fa65494e7bd0e3ba33b3e5a5ab30c2b6e95d3d1762baaa56151a0861618dc261", + "sha256:fd7186e23963714bab3c9a2ab75d002078335110d2c9fc883c65cbce43717f26", + "sha256:fec32c22b521fcdeb9aa7dee4373b2d81ca2d3fc8edc532f3e189d6f4f6f1f81" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.2" + }, + "werkzeug": { + "hashes": [ + "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", + "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746" + ], + "markers": "python_version >= '3.9'", + "version": "==3.1.3" + }, + "yarl": { + "hashes": [ + "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", + "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", + "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318", + "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee", + "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", + "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1", + "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", + "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", + "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1", + "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", + "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", + "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", + "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", + "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc", + "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5", + "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", + "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", + "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", + "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24", + "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b", + "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910", + "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", + "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", + "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed", + "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", + "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04", + "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", + "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5", + "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", + "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", + "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", + "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b", + "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c", + "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", + "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34", + "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", + "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990", + "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", + "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", + "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", + "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", + "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6", + "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", + "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", + "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", + "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", + "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8", + "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", + "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e", + "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985", + "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8", + "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", + "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5", + "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690", + "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", + "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789", + "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", + "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", + "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", + "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", + "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", + "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9", + "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", + "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db", + "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde", + "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7", + "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", + "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", + "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", + "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", + "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", + "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", + "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", + "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd", + "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", + "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760", + "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", + "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", + "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", + "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", + "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719", + "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62" + ], + "markers": "python_version >= '3.9'", + "version": "==1.18.3" + } + }, + "develop": { + "certifi": { + "hashes": [ + "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", + "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe" + ], + "markers": "python_version >= '3.6'", + "version": "==2025.1.31" + }, + "charset-normalizer": { + "hashes": [ + "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", + "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", + "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", + "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", + "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", + "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", + "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", + "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", + "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", + "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", + "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", + "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", + "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", + "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", + "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", + "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", + "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", + "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", + "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", + "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", + "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", + "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", + "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", + "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", + "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", + "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", + "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", + "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", + "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", + "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", + "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", + "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", + "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", + "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", + "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", + "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", + "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", + "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", + "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", + "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", + "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", + "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", + "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", + "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", + "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", + "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", + "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", + "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", + "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", + "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", + "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", + "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", + "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", + "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", + "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", + "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", + "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", + "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", + "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", + "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", + "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", + "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", + "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", + "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", + "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", + "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", + "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", + "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", + "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", + "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", + "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", + "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", + "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", + "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", + "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", + "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", + "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", + "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", + "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", + "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", + "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", + "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", + "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", + "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", + "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", + "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", + "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", + "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", + "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", + "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", + "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", + "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.1" + }, + "coverage": { + "hashes": [ + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==7.7.1" + }, + "docker": { + "hashes": [ + "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", + "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" + ], + "markers": "python_version >= '3.8'", + "version": "==7.1.0" + }, + "idna": { + "hashes": [ + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.10" + }, + "iniconfig": { + "hashes": [ + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "packaging": { + "hashes": [ + "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", + "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f" + ], + "markers": "python_version >= '3.8'", + "version": "==24.2" + }, + "pluggy": { + "hashes": [ + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "pytest": { + "hashes": [ + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==8.3.5" + }, + "python-dotenv": { + "hashes": [ + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.1.0" + }, + "requests": { + "hashes": [ + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + ], + "markers": "python_version >= '3.8'", + "version": "==2.32.3" + }, + "requests-mock": { + "hashes": [ + "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", + "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" + ], + "index": "pypi", + "markers": "python_version >= '3.5'", + "version": "==1.12.1" + }, + "testcontainers": { + "hashes": [ + "sha256:348c72d369d0bd52b57ab4f07a965ae9562837098c28f0522b969b064b779f10", + "sha256:36bd2b58d91f2fc7ac4f4a73c6ec00e5e60c259c10f208dbfe3161029889be92" + ], + "index": "pypi", + "markers": "python_version >= '3.9' and python_version < '4.0'", + "version": "==4.9.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" + ], + "markers": "python_version >= '3.8'", + "version": "==4.13.0" + }, + "urllib3": { + "hashes": [ + "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", + "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.3.0" + }, + "wrapt": { + "hashes": [ + "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f", + "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c", + "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", + "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", + "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", + "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c", + "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", + "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", + "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8", + "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", + "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061", + "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", + "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb", + "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62", + "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984", + "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", + "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2", + "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", + "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7", + "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", + "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", + "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", + "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", + "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", + "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", + "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", + "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563", + "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a", + "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f", + "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", + "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9", + "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", + "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82", + "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9", + "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", + "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", + "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", + "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", + "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", + "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7", + "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", + "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", + "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", + "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a", + "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3", + "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a", + "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", + "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", + "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", + "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", + "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", + "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", + "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", + "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", + "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", + "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", + "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2", + "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22", + "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72", + "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061", + "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f", + "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9", + "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04", + "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", + "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9", + "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f", + "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", + "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", + "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", + "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", + "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", + "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", + "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", + "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6", + "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", + "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb", + "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119", + "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b", + "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.2" + } + } +} diff --git a/dbrepo-dashboard-service/README.md b/dbrepo-dashboard-service/README.md new file mode 100644 index 0000000000..a05a200d2d --- /dev/null +++ b/dbrepo-dashboard-service/README.md @@ -0,0 +1,14 @@ +# Search Service + +## Actuator + +- Health: http://localhost:5000/api/search/health +- Prometheus: http://localhost:5000/metrics + +## Swagger UI Endpoints + +- Swagger UI: http://localhost:5000/swagger-ui/ + +## OpenAPI Endpoints + +- OpenAPI v3 as .json: http://localhost:5000/api-search.json \ No newline at end of file diff --git a/dbrepo-dashboard-service/access.py b/dbrepo-dashboard-service/access.py deleted file mode 100644 index b72b2dcfbf..0000000000 --- a/dbrepo-dashboard-service/access.py +++ /dev/null @@ -1,30 +0,0 @@ -import logging - -from grafana_client.client import GrafanaException - -from api.dto import Permission -from dbrepo.api.dto import Database -from clients import grafana_client - -statistics_row_title = '${table_id}' - - -def update_anonymous_read_access(uid: str, is_public: bool, is_schema_public: bool) -> None: - grafana = grafana_client.connect() - permissions = grafana.dashboard.get_permissions_by_uid(uid) - viewer_role = [permission for permission in permissions if - 'permissionName' in permission and permission['permissionName'] != 'View'] - permission = '' - if is_public or is_schema_public: - permission = 'View' - if len(viewer_role) == 0: - logging.warning(f'Failed to find permissionName=View') - return None - try: - response = grafana_client.generic_post(f'/api/access-control/dashboards/{uid}/builtInRoles/Viewer', - Permission(permission=permission).model_dump()) - if response.status_code != 200: - raise OSError(f'Failed to update anonymous read access: {response.content}') - except GrafanaException as e: - raise OSError(f'Failed to update anonymous read access: {e.message}') - logging.info(f"Updated anonymous read access for dashboard with uid: {uid}") diff --git a/dbrepo-dashboard-service/app.py b/dbrepo-dashboard-service/app.py new file mode 100644 index 0000000000..eb50fe66c7 --- /dev/null +++ b/dbrepo-dashboard-service/app.py @@ -0,0 +1,237 @@ +import logging +import os +from http import HTTPStatus +from json import dumps +from typing import List, Any + +from dbrepo.api.dto import ApiError, Database, User +from dbrepo.core.api.exceptions import DashboardNotFound +from dbrepo.core.client.auth import AuthServiceClient +from dbrepo.core.client.dashboard import DashboardServiceClient +from flasgger import LazyJSONEncoder, Swagger, swag_from +from flask import Flask, request, Response +from flask_cors import CORS +from flask_httpauth import HTTPTokenAuth, HTTPBasicAuth, MultiAuth +from grafana_client.client import GrafanaClientError +from prometheus_flask_exporter import PrometheusMetrics +from pydantic import ValidationError + +logging.addLevelName(level=logging.NOTSET, levelName='TRACE') +logging.basicConfig(level=logging.DEBUG) + +from logging.config import dictConfig + +# logging configuration +dictConfig({ + 'version': 1, + 'formatters': { + 'default': { + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', + }, + 'simple': { + 'format': '[%(asctime)s] %(levelname)s: %(message)s', + }, + }, + 'handlers': {'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'simple' # default + }}, + 'root': { + 'level': 'DEBUG', + 'handlers': ['wsgi'] + } +}) + +# create app object +app = Flask(__name__) + +cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) + +metrics = PrometheusMetrics(app) +metrics.info("app_info", "Application info", version="0.0.1") +app.config["SWAGGER"] = {"openapi": "3.0.1", "title": "Swagger UI", "uiversion": 3} + +token_auth = HTTPTokenAuth(scheme='Bearer') +basic_auth = HTTPBasicAuth() +auth = MultiAuth(token_auth, basic_auth) + +swagger_config = { + "headers": [], + "specs": [ + { + "endpoint": "api-dashboard", + "route": "/api-dashboard.json", + "rule_filter": lambda rule: True, + "model_filter": lambda tag: True, # all in + } + ], + "static_url_path": "/flasgger_static", + "swagger_ui": True, + "specs_route": "/swagger-ui/", +} + +template = { + "openapi": "3.0.0", + "info": { + "title": "Database Repository Dashboard Service API", + "description": "Service that manages the dashboards", + "version": "1.8.0", + "contact": { + "name": "Prof. Andreas Rauber", + "email": "andreas.rauber@tuwien.ac.at" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0" + }, + }, + "externalDocs": { + "description": "Sourcecode Documentation", + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + }, + { + "url": "https://test.dbrepo.tuwien.ac.at", + "description": "Sandbox" + } + ], + "components": { + "schemas": { + "ApiError": { + "properties": { + "message": { + "example": "Message", + "type": "string" + }, + "status": { + "example": "BAD_REQUEST", + "type": "string" + }, + "code": { + "example": "error.dashboard.create", + "type": "string" + } + }, + "type": "object" + }, + }, + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT", + "in": "header" + }, + "basicAuth": { + "type": "http", + "scheme": "basic", + "in": "header" + } + }, + } +} + +swagger = Swagger(app, config=swagger_config, template=template) +app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost:8080") +app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") +app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") +app.config["BASE_URL"] = os.getenv("BASE_URL", "http://localhost") +app.config["JSON_DATASOURCE_NAME"] = os.getenv('JSON_DATASOURCE_NAME', 'dbrepojson0') +app.config["JWT_ALGORITHM"] = "HS256" +app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKEY", + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB") + '\n-----END PUBLIC KEY-----' +app.config["READONLY_USERNAME"] = os.getenv('READONLY_USERNAME', 'user') +app.config["READONLY_PASSWORD"] = os.getenv('READONLY_PASSWORD', 'user') + +app.json_encoder = LazyJSONEncoder + +headers = {'Content-Type': 'application/json'} + + +def dashboard_client(): + return DashboardServiceClient(os.getenv('DASHBOARD_UI_ENDPOINT', 'http://localhost:3000'), + os.getenv('SYSTEM_USERNAME', 'admin'), os.getenv('SYSTEM_PASSWORD', 'admin')) + + +def auth_client(): + return AuthServiceClient(app.config["AUTH_SERVICE_ENDPOINT"], app.config["AUTH_SERVICE_CLIENT"], + app.config["AUTH_SERVICE_CLIENT_SECRET"], app.config["JWT_PUBKEY"]) + + +@token_auth.verify_token +def verify_token(token: str) -> bool | User: + return auth_client().is_valid_token(token) + + +@basic_auth.verify_password +def verify_password(username: str, password: str) -> Any: + return auth_client().is_valid_password(username, password) + + +@token_auth.get_user_roles +def get_user_roles(user: User) -> List[str]: + return auth_client().get_user_roles(user) + + +@basic_auth.get_user_roles +def get_user_roles(user: User) -> List[str]: + return auth_client().get_user_roles(user) + + +@app.route("/health", methods=["GET"], endpoint="actuator_health") +def health(): + return dict({"status": "UP"}), 200 + + +@app.route("/api/dashboard", methods=["POST"], endpoint="create_dashboard") +@metrics.gauge(name='dbrepo_create_dashboard', description='Time needed to create dashboard') +@swag_from("ds-yml/create_dashboard.yml") +@auth.login_required(role=['system']) +def create_dashboard(): + for parameter in [param for param in ['is_public', 'is_schema_public', 'owner_username', 'database_name'] if + param not in request.json]: + return Response(ApiError(status='BAD_REQUEST', message=f'Missing required parameter: {parameter}', + code="error.dashboard.malformed").model_dump_json(), 400, headers) + + is_public = bool(request.json['is_public']) + is_schema_public = bool(request.json['is_schema_public']) + owner_username = request.json['owner_username'] + logging.debug( + f"endpoint create dashboard, is_public={is_public}, is_schema_public={is_schema_public}, owner_username={owner_username}") + try: + db = dashboard_client().create(request.json['database_name']) + dashboard_client().update_anonymous_read_access(db['uid'], is_public, is_schema_public) + return Response(dumps(db)), 201, headers + except GrafanaClientError as e: + dto = ApiError(status=HTTPStatus(e.status_code).phrase.upper(), + message=f"Failed to create dashboard: {e.response['message']}", code="error.dashboard.create") + if e.status_code == 409 or e.status_code == 412: + dto.code = "error.dashboard.exists" + return Response(dto.model_dump_json(), 409, headers) + return Response(dto.model_dump_json(), e.status_code, headers) + + +@app.route("/api/dashboard/<string:uid>", methods=["PUT"], endpoint="update_dashboard") +@metrics.gauge(name='dbrepo_update_dashboard', description='Time needed to update dashboard') +@swag_from("ds-yml/update_dashboard.yml") +@auth.login_required(role=['system']) +def update_dashboard(uid: str): + logging.debug(f'endpoint update dashboard, uid={uid}') + try: + database = Database.model_validate(request.json) + except ValidationError as e: + logging.error(f'Model malformed: {e}') + return Response(ApiError(status='BAD_REQUEST', message='Invalid database format', + code='error.database.malformed').model_dump_json(), 400, headers) + try: + dashboard_client().update(database) + except DashboardNotFound as e: + return Response(ApiError(status='NOT_FOUND', message=f"Failed to update dashboard: not found", + code="error.dashboard.missing").model_dump_json(), 404, headers) + dashboard_client().update_anonymous_read_access(uid, database.is_public, database.is_schema_public) + return Response(), 202, headers diff --git a/dbrepo-dashboard-service/clients/grafana_client.py b/dbrepo-dashboard-service/clients/grafana_client.py deleted file mode 100644 index 8f7d5aab0f..0000000000 --- a/dbrepo-dashboard-service/clients/grafana_client.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging -import os - -import requests -from requests import Response - -from grafana_client import GrafanaApi - -url = os.getenv('DASHBOARD_UI_ENDPOINT', 'http://localhost:3000') -username = os.getenv('SYSTEM_USERNAME', 'admin') -password = os.getenv('SYSTEM_PASSWORD', 'admin') - - -def connect() -> GrafanaApi: - return GrafanaApi.from_url(url=f'{url}', credential=(username, password)) - - -def generic_get(api_url: str) -> Response: - request_url = url + api_url - logging.debug(f'generic get url={request_url}, auth=({username}, <reacted>)') - return requests.get(request_url, auth=(username, password)) - - -def generic_post(api_url: str, payload: dict) -> Response: - request_url = url + api_url - logging.debug(f'generic post url={request_url}, payload={payload}, auth=({username}, <reacted>)') - return requests.post(request_url, json=payload, auth=(username, password)) diff --git a/dbrepo-dashboard-service/clients/keycloak_client.py b/dbrepo-dashboard-service/clients/keycloak_client.py deleted file mode 100644 index 7abb0a28a5..0000000000 --- a/dbrepo-dashboard-service/clients/keycloak_client.py +++ /dev/null @@ -1,35 +0,0 @@ -from dataclasses import dataclass -from typing import List - -import requests -from flask import current_app -from jwt import jwk_from_pem, JWT - - -@dataclass(init=True, eq=True) -class User: - username: str - roles: List[str] - - -class KeycloakClient: - - def obtain_user_token(self, username: str, password: str) -> str: - response = requests.post( - f"{current_app.config['AUTH_SERVICE_ENDPOINT']}/realms/dbrepo/protocol/openid-connect/token", - data={ - "username": username, - "password": password, - "grant_type": "password", - "client_id": current_app.config["AUTH_SERVICE_CLIENT"], - "client_secret": current_app.config["AUTH_SERVICE_CLIENT_SECRET"] - }) - body = response.json() - if "access_token" not in body: - raise AssertionError(f"Failed to obtain user token(s): {response.status_code}") - return response.json()["access_token"] - - def verify_jwt(self, access_token: str) -> User: - public_key = jwk_from_pem(str(current_app.config["JWT_PUBKEY"]).encode('utf-8')) - payload = JWT().decode(message=access_token, key=public_key, do_time_check=True) - return User(username=payload.get('client_id'), roles=payload.get('realm_access')["roles"]) diff --git a/dbrepo-dashboard-service/dashboard.py b/dbrepo-dashboard-service/dashboard.py deleted file mode 100644 index f8d4212be4..0000000000 --- a/dbrepo-dashboard-service/dashboard.py +++ /dev/null @@ -1,344 +0,0 @@ -import logging -import os - -from dbrepo.api.dto import Database, View - -from clients import grafana_client - -statistics_row_title = '${view_id}' - -base_url = os.getenv('BASE_URL', 'http://localhost') -datasource_uid = os.getenv('JSON_DATASOURCE_NAME', 'dbrepojson0') - - -def map_link(title: str, url: str) -> dict: - return dict(targetBlank=True, - asDropdown=False, - includeVars=False, - keepTime=False, - tags=[], - type='link', - icon='info', - title=title, - url=url) - - -def map_statistics_row(dashboard: dict) -> dict | None: - filtered_panels = [panel for panel in dashboard['panels'] if - panel['type'] == 'row' and panel['title'] == statistics_row_title] - if len(filtered_panels) == 0: - logging.warning(f"Failed to find statistics row title {statistics_row_title} in: {filtered_panels}") - return None - return filtered_panels[0] - - -def map_links(database: Database) -> [dict]: - links = [] - if len(database.identifiers) > 0: - links.append(map_link('Database', f"{base_url}/pid/{database.identifiers[0].id}")) - else: - links.append(map_link('Database', f"{base_url}/database/{database.id}")) - return links - - -def map_templating(database: Database) -> dict: - options = [dict(selected=False, - text=view.name, - value=str(view.id)) for view in database.views] - selected = dict(selected=True, - text=[view.name for view in database.views], - value=[str(view.id) for view in database.views]) - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(list=[dict(description='', - name='view_id', - hide=0, - includeAll=True, - multi=True, - datasource=datasource, - refresh=1, - regex='', - sort=0, - definition='dbrepo-json- (infinity) json', - query=dict(queryType='infinity', - query='', - infinityQuery=dict(format='table', - filters=[], - parser='backend', - refId='variable', - root_selector='', - source='url', - type='json', - url=f"/api/database/{database.id}/view", - columns=[dict(selector='id', - text='value', - type='string'), - dict( - selector='internal_name', - text='name', - type='string')], - url_options=dict(data='', - method='GET'))), - label='Datasource', - skipUrlSync=False, - type='query', - current=selected, - options=options)]) - - -def map_timeseries_panel(database: Database, view: View) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict( - title=view['name'], - type='timeseries', - datasource=datasource, - targets=[dict(datasource=datasource, - format='table', - global_query_id='', - hide=False, - refId='A', - root_selector='', - source='url', - type='json', - url=f"/api/database/{database['id']}/view/{view['id']}", - url_options=dict(data='', - method='GET'))], - gridPos=dict(h=8, - w=12, - x=0, - y=0), - options=dict(legend=dict(displayMode='list', - placement='bottom', - showLegend=True), - tooltip=dict(mode='single', - sort='none')), - fieldConfig=dict( - defaults=dict(color=dict(mode='palette-classic'), - custom=dict( - axisBorderShow=False, - axisCenteredZero=False, - axisColorMode='text', - axisLabel='', - axisPlacement='auto', - barAlignment=0, - drawStyle='line', - fillOpacity=0, - gradientMode='none', - hideFrom=dict(legend=False, - tooltip=False, - viz=False), - insertNulls=False, - lineInterpolation='linear', - lineWidth=1, - pointSize=5, - scaleDistribution=dict(type='linear'), - showPoints='auto', - spanNulls=False, - stacking=dict(group='A', - mode='none'), - thresholdsStyle=dict(mode='absolute'))))) - - -def map_statistics_panel(database_id: str, view: View) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict( - title=view.name, - type='table', - datasource=datasource, - targets=[dict(datasource=datasource, - columns=[], - filters=[], - format='table', - global_query_id='', - hide=False, - refId='A', - root_selector='', - source='url', - type='json', - url=f"/api/database/{database_id}/view/{view.id}/data", - url_options=dict(data='', - method='GET'))], - options=dict(cellHeight="sm", - showHeader=True, - footer=dict(countRows=False, - fields="", - reducer=["sum"], - show=False)), - gridPos=dict(h=8, - w=12, - x=12, - y=0), - transformations=dict(id="organize", - options=dict(excludeByName=dict(), - includeByName=dict(), - indexByName=dict( - HEADER_AVG=3, - HEADER_COL=0, - HEADER_STDDEV=4, - HEADER_MAX=2, - HEADER_MIN=1))), - fieldConfig=dict(defaults=dict(custom=dict(align="auto", - filterable="true", - cellOptions=dict(type="auto"), - inspect=False), - mappings=[], - thresholds=dict(mode="absolute", - steps=[dict(color="green", - value=None), - dict(color="red", - value=80) - ])), - overrides=[dict(matcher=dict(id="byName", - options="HEADER_COL"), - properties=[dict(id="custom.align", - value="center")]), - dict(matcher=dict(id="byName", - options="HEADER_MIN"), - properties=[dict(id="custom.width", - value=115)]), - dict(matcher=dict(id="byName", - options="HEADER_MAX"), - properties=[dict(id="custom.width", - value=115)]), - dict(matcher=dict(id="byName", - options="HEADER_AVG"), - properties=[dict(id="custom.width", - value=115)]), - dict(matcher=dict(id="byName", - options="HEADER_STDDEV"), - properties=[dict(id="custom.width", - value=115)]) - ])) - - -def map_overview_panel(database_id: str) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(title='Preview', - type='table', - fieldConfig=dict( - defaults=dict( - color=dict(mode='palette-classic'), - custom=dict(axisBorderShow=False, - axisCenteredZero=False, - axisColorMode='text', - axisLabel='', - axisPlacement='auto', - barAlignment=0, - drawStyle='line', - fillOpacity=0, - gradientMode='none', - hideFrom=dict( - legend=False, - tooltip=False, - viz=False), - insertNulls=False, - lineInterpolation='linear', - lineWidth=1, - pointSize=5, - scaleDistribution=dict( - type='linear'), - showPoints='auto', - spanNulls=False, - stacking=dict(group='A', - mode='none'), - thresholdsStyle=dict( - mode='off'))), - overrides=[]), - options=dict(legend=dict(displayMode='list', - placement='bottom', - showLegend=True, - calcs=[]), - tooltip=dict(mode='single', - sort='none')), - targets=[dict(format='json', - columns=[], - datasource=datasource, - filters=[], - global_query_id='', - refId='A', - root_selector='', - source='url', - type='json', - url='/api/database/' + database_id + '/view/${view_id}/data', - url_options=dict(data='', - method='GET'))], - datasource=datasource, - gridPos=dict(h=4, - w=12, - x=0, - y=0)) - - -def map_row() -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(collapsed=False, - repeat='view_id', - repeatDirection='h', - title=statistics_row_title, - type='row', - panels=[], - targets=[dict(refId='A', - datasource=datasource)], - gridPos=dict(h=1, - w=24, - x=0, - y=0)) - - -def map_panels(dashboard: dict, database: Database) -> [dict]: - if map_statistics_row(dashboard) is None: - dashboard['panels'].append(map_row()) - dashboard['panels'].append(map_overview_panel(database.id)) - for view in database.views: - dashboard['panels'].append(map_statistics_panel(database.id, view)) - return dashboard['panels'] - - -def find(uid: str): - grafana = grafana_client.connect() - return grafana.dashboard.get_dashboard(uid) - - -def create(database_name: str, uid: str = '') -> dict: - grafana = grafana_client.connect() - dashboard = dict(uid=uid, - title=f'{database_name} Overview', - tags=['dbrepo'], - timezone='browser', - fiscalYearStartMonth=1, - panels=[]) - dashboard['panels'] = [] - payload = dict(folderUid='', - overwrite=False, - dashboard=dashboard) - dashboard = grafana.dashboard.update_dashboard(payload) - logging.info(f"Created dashboard with uid: {dashboard['uid']}") - return dashboard - - -def delete(uid: str) -> None: - grafana = grafana_client.connect() - grafana.dashboard.delete_dashboard(uid) - - -def update(database: Database) -> None: - grafana = grafana_client.connect() - dashboard = find(database.dashboard_uid)['dashboard'] - # update metadata - if len(database.identifiers) > 0 and len(database.identifiers[0].titles) > 0: - dashboard['title'] = database.identifiers[0].titles[0].title - if len(database.identifiers) > 0 and len(database.identifiers[0].descriptions) > 0: - dashboard['description'] = database.identifiers[0].descriptions[0].description - dashboard['links'] = map_links(database) - dashboard['templating'] = map_templating(database) - # update panels - dashboard['panels'] = map_panels(dashboard, database) - payload = dict(folderUid='', - overwrite=True, - dashboard=dashboard) - response = grafana.dashboard.update_dashboard(payload) - logging.info(f"Updated dashboard with uid: {response['uid']}") diff --git a/dbrepo-dashboard-service/ds-yml/create_dashboard.yml b/dbrepo-dashboard-service/ds-yml/create_dashboard.yml new file mode 100644 index 0000000000..8499d13ed5 --- /dev/null +++ b/dbrepo-dashboard-service/ds-yml/create_dashboard.yml @@ -0,0 +1,55 @@ +tags: + - dashboard-endpoint +summary: "Create dashboard" +operationId: create_dashboard +description: "Creates a dashboard in the Dashboard UI. Requires role `system`." +consumes: + - "application/json" +produces: + - "application/json" +parameters: + - in: "body" + name: "body" + required: true + schema: + required: + - is_public + - is_schema_public + - database_name + - owner_username + type: object + properties: + is_public: + type: boolean + example: True + is_schema_public: + type: boolean + example: True + database_name: + type: string + example: "some_database" + owner_username: + type: string + example: "foobar" +responses: + 201: + description: Created dashboard successfully + content: + application/json: + schema: + type: object + 409: + description: "Dashboard exists with same name" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + 500: + description: "Unexpected system error" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' +security: + - bearerAuth: [ ] + - basicAuth: [ ] diff --git a/dbrepo-dashboard-service/ds-yml/update_dashboard.yml b/dbrepo-dashboard-service/ds-yml/update_dashboard.yml new file mode 100644 index 0000000000..0765ad9565 --- /dev/null +++ b/dbrepo-dashboard-service/ds-yml/update_dashboard.yml @@ -0,0 +1,43 @@ +tags: + - dashboard-endpoint +summary: "Update dashboard" +operationId: update_dashboard +description: "Updates a dashboard in the Dashboard UI. Requires role `system`." +consumes: + - "application/json" +produces: + - "application/json" +parameters: + - name: uid + in: path + required: true + schema: + type: string + format: uuid + - name: "body" + in: "body" + required: true + schema: + type: object +responses: + 202: + description: Updated dashboard successfully + content: + application/json: + schema: + type: object + 404: + description: "Dashboard not found" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' + 500: + description: "Unexpected system error" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiError' +security: + - bearerAuth: [ ] + - basicAuth: [ ] diff --git a/dbrepo-dashboard-service/init/.coveragerc b/dbrepo-dashboard-service/init/.coveragerc new file mode 100644 index 0000000000..9fd61fc166 --- /dev/null +++ b/dbrepo-dashboard-service/init/.coveragerc @@ -0,0 +1,7 @@ +[report] +omit = + # omit tests + ./tests/* + +[html] +directory = htmlcov \ No newline at end of file diff --git a/dbrepo-dashboard-service/init/Dockerfile b/dbrepo-dashboard-service/init/Dockerfile new file mode 100644 index 0000000000..91430ec40c --- /dev/null +++ b/dbrepo-dashboard-service/init/Dockerfile @@ -0,0 +1,25 @@ +FROM python:3.11-alpine3.21 +LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" + +RUN apk add --no-cache \ + curl \ + bash \ + jq + +COPY Pipfile Pipfile.lock ./ + +COPY ./lib ./lib + +RUN pip install pipenv && \ + pipenv install gunicorn && \ + pipenv install --system --deploy + +RUN adduser -D dbrepo --uid 1001 + +WORKDIR /app + +USER 1001 + +COPY --chown=1001 ./*.py ./ + +ENTRYPOINT [ "python", "./app.py" ] diff --git a/dbrepo-dashboard-service/init/Pipfile b/dbrepo-dashboard-service/init/Pipfile new file mode 100644 index 0000000000..54581fdc94 --- /dev/null +++ b/dbrepo-dashboard-service/init/Pipfile @@ -0,0 +1,27 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +flasgger = "*" +flask = "~=2.0" +flask-cors = "~=4.0" +flask-jwt-extended = "~=4.5" +prometheus-flask-exporter = "*" +python-dotenv = "~=1.0" +pytest = "*" +dbrepo = {path = "./lib/dbrepo-1.8.0.tar.gz"} +gunicorn = "*" +pydantic = "*" +flask_httpauth = "*" + +[dev-packages] +coverage = "*" +pytest = "*" +testcontainers = "*" +requests-mock = "*" +grafana-client = "*" + +[requires] +python_version = "3.11" diff --git a/dbrepo-dashboard-service/init/Pipfile.lock b/dbrepo-dashboard-service/init/Pipfile.lock new file mode 100644 index 0000000000..d358b22298 --- /dev/null +++ b/dbrepo-dashboard-service/init/Pipfile.lock @@ -0,0 +1,2094 @@ +{ + "_meta": { + "hash": { + "sha256": "ad6afa35e18bb5ae85ebf1fb3b09a23c86dfc500e6d07234fb89c5728e1fa0a9" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "aiohappyeyeballs": { + "hashes": [ + "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", + "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" + ], + "markers": "python_version >= '3.9'", + "version": "==2.6.1" + }, + "aiohttp": { + "hashes": [ + "sha256:04eb541ce1e03edc1e3be1917a0f45ac703e913c21a940111df73a2c2db11d73", + "sha256:05582cb2d156ac7506e68b5eac83179faedad74522ed88f88e5861b78740dc0e", + "sha256:0a29be28e60e5610d2437b5b2fed61d6f3dcde898b57fb048aa5079271e7f6f3", + "sha256:0b2501f1b981e70932b4a552fc9b3c942991c7ae429ea117e8fba57718cdeed0", + "sha256:0df3788187559c262922846087e36228b75987f3ae31dd0a1e5ee1034090d42f", + "sha256:12c5869e7ddf6b4b1f2109702b3cd7515667b437da90a5a4a50ba1354fe41881", + "sha256:14fc03508359334edc76d35b2821832f092c8f092e4b356e74e38419dfe7b6de", + "sha256:1a7169ded15505f55a87f8f0812c94c9412623c744227b9e51083a72a48b68a5", + "sha256:1c68e41c4d576cd6aa6c6d2eddfb32b2acfb07ebfbb4f9da991da26633a3db1a", + "sha256:20412c7cc3720e47a47e63c0005f78c0c2370020f9f4770d7fc0075f397a9fb0", + "sha256:22a8107896877212130c58f74e64b77f7007cb03cea8698be317272643602d45", + "sha256:28a3d083819741592685762d51d789e6155411277050d08066537c5edc4066e6", + "sha256:2b86efe23684b58a88e530c4ab5b20145f102916bbb2d82942cafec7bd36a647", + "sha256:2d0b46abee5b5737cb479cc9139b29f010a37b1875ee56d142aefc10686a390b", + "sha256:321238a42ed463848f06e291c4bbfb3d15ba5a79221a82c502da3e23d7525d06", + "sha256:3a8a0d127c10b8d89e69bbd3430da0f73946d839e65fec00ae48ca7916a31948", + "sha256:3a8b0321e40a833e381d127be993b7349d1564b756910b28b5f6588a159afef3", + "sha256:3b420d076a46f41ea48e5fcccb996f517af0d406267e31e6716f480a3d50d65c", + "sha256:3b512f1de1c688f88dbe1b8bb1283f7fbeb7a2b2b26e743bb2193cbadfa6f307", + "sha256:413fe39fd929329f697f41ad67936f379cba06fcd4c462b62e5b0f8061ee4a77", + "sha256:41cf0cefd9e7b5c646c2ef529c8335e7eafd326f444cc1cdb0c47b6bc836f9be", + "sha256:4848ae31ad44330b30f16c71e4f586cd5402a846b11264c412de99fa768f00f3", + "sha256:4b0a200e85da5c966277a402736a96457b882360aa15416bf104ca81e6f5807b", + "sha256:4e2e8ef37d4bc110917d038807ee3af82700a93ab2ba5687afae5271b8bc50ff", + "sha256:4edcbe34e6dba0136e4cabf7568f5a434d89cc9de5d5155371acda275353d228", + "sha256:51ba80d473eb780a329d73ac8afa44aa71dfb521693ccea1dea8b9b5c4df45ce", + "sha256:5409a59d5057f2386bb8b8f8bbcfb6e15505cedd8b2445db510563b5d7ea1186", + "sha256:572def4aad0a4775af66d5a2b5923c7de0820ecaeeb7987dcbccda2a735a993f", + "sha256:599b66582f7276ebefbaa38adf37585e636b6a7a73382eb412f7bc0fc55fb73d", + "sha256:59a05cdc636431f7ce843c7c2f04772437dd816a5289f16440b19441be6511f1", + "sha256:602d4db80daf4497de93cb1ce00b8fc79969c0a7cf5b67bec96fa939268d806a", + "sha256:65c75b14ee74e8eeff2886321e76188cbe938d18c85cff349d948430179ad02c", + "sha256:69bb252bfdca385ccabfd55f4cd740d421dd8c8ad438ded9637d81c228d0da49", + "sha256:6d3986112e34eaa36e280dc8286b9dd4cc1a5bcf328a7f147453e188f6fe148f", + "sha256:6dd9766da617855f7e85f27d2bf9a565ace04ba7c387323cd3e651ac4329db91", + "sha256:70ab0f61c1a73d3e0342cedd9a7321425c27a7067bebeeacd509f96695b875fc", + "sha256:749f1eb10e51dbbcdba9df2ef457ec060554842eea4d23874a3e26495f9e87b1", + "sha256:781c8bd423dcc4641298c8c5a2a125c8b1c31e11f828e8d35c1d3a722af4c15a", + "sha256:7e7abe865504f41b10777ac162c727af14e9f4db9262e3ed8254179053f63e6d", + "sha256:7f2dadece8b85596ac3ab1ec04b00694bdd62abc31e5618f524648d18d9dd7fa", + "sha256:86135c32d06927339c8c5e64f96e4eee8825d928374b9b71a3c42379d7437058", + "sha256:8778620396e554b758b59773ab29c03b55047841d8894c5e335f12bfc45ebd28", + "sha256:87f0e003fb4dd5810c7fbf47a1239eaa34cd929ef160e0a54c570883125c4831", + "sha256:8aa5c68e1e68fff7cd3142288101deb4316b51f03d50c92de6ea5ce646e6c71f", + "sha256:8d14e274828561db91e4178f0057a915f3af1757b94c2ca283cb34cbb6e00b50", + "sha256:8d1dd75aa4d855c7debaf1ef830ff2dfcc33f893c7db0af2423ee761ebffd22b", + "sha256:92007c89a8cb7be35befa2732b0b32bf3a394c1b22ef2dff0ef12537d98a7bda", + "sha256:92868f6512714efd4a6d6cb2bfc4903b997b36b97baea85f744229f18d12755e", + "sha256:948abc8952aff63de7b2c83bfe3f211c727da3a33c3a5866a0e2cf1ee1aa950f", + "sha256:95d7787f2bcbf7cb46823036a8d64ccfbc2ffc7d52016b4044d901abceeba3db", + "sha256:997b57e38aa7dc6caab843c5e042ab557bc83a2f91b7bd302e3c3aebbb9042a1", + "sha256:99b8bbfc8111826aa8363442c0fc1f5751456b008737ff053570f06a151650b3", + "sha256:9e73fa341d8b308bb799cf0ab6f55fc0461d27a9fa3e4582755a3d81a6af8c09", + "sha256:a0d2c04a623ab83963576548ce098baf711a18e2c32c542b62322a0b4584b990", + "sha256:a40087b82f83bd671cbeb5f582c233d196e9653220404a798798bfc0ee189fff", + "sha256:ad1f2fb9fe9b585ea4b436d6e998e71b50d2b087b694ab277b30e060c434e5db", + "sha256:b05774864c87210c531b48dfeb2f7659407c2dda8643104fb4ae5e2c311d12d9", + "sha256:b41693b7388324b80f9acfabd479bd1c84f0bc7e8f17bab4ecd9675e9ff9c734", + "sha256:b42dbd097abb44b3f1156b4bf978ec5853840802d6eee2784857be11ee82c6a0", + "sha256:b4e7c7ec4146a94a307ca4f112802a8e26d969018fabed526efc340d21d3e7d0", + "sha256:b59d096b5537ec7c85954cb97d821aae35cfccce3357a2cafe85660cc6295628", + "sha256:b9c60d1de973ca94af02053d9b5111c4fbf97158e139b14f1be68337be267be6", + "sha256:bccd2cb7aa5a3bfada72681bdb91637094d81639e116eac368f8b3874620a654", + "sha256:c32593ead1a8c6aabd58f9d7ee706e48beac796bb0cb71d6b60f2c1056f0a65f", + "sha256:c7571f99525c76a6280f5fe8e194eeb8cb4da55586c3c61c59c33a33f10cfce7", + "sha256:c8b2df9feac55043759aa89f722a967d977d80f8b5865a4153fc41c93b957efc", + "sha256:ca9f835cdfedcb3f5947304e85b8ca3ace31eef6346d8027a97f4de5fb687534", + "sha256:cc9253069158d57e27d47a8453d8a2c5a370dc461374111b5184cf2f147a3cc3", + "sha256:ced66c5c6ad5bcaf9be54560398654779ec1c3695f1a9cf0ae5e3606694a000a", + "sha256:d173c0ac508a2175f7c9a115a50db5fd3e35190d96fdd1a17f9cb10a6ab09aa1", + "sha256:d6edc538c7480fa0a3b2bdd705f8010062d74700198da55d16498e1b49549b9c", + "sha256:daf20d9c3b12ae0fdf15ed92235e190f8284945563c4b8ad95b2d7a31f331cd3", + "sha256:dc311634f6f28661a76cbc1c28ecf3b3a70a8edd67b69288ab7ca91058eb5a33", + "sha256:e2bc827c01f75803de77b134afdbf74fa74b62970eafdf190f3244931d7a5c0d", + "sha256:e365034c5cf6cf74f57420b57682ea79e19eb29033399dd3f40de4d0171998fa", + "sha256:e906da0f2bcbf9b26cc2b144929e88cb3bf943dd1942b4e5af066056875c7618", + "sha256:e9faafa74dbb906b2b6f3eb9942352e9e9db8d583ffed4be618a89bd71a4e914", + "sha256:ec6cd1954ca2bbf0970f531a628da1b1338f594bf5da7e361e19ba163ecc4f3b", + "sha256:f296d637a50bb15fb6a229fbb0eb053080e703b53dbfe55b1e4bb1c5ed25d325", + "sha256:f30fc72daf85486cdcdfc3f5e0aea9255493ef499e31582b34abadbfaafb0965", + "sha256:fe846f0a98aa9913c2852b630cd39b4098f296e0907dd05f6c7b30d911afa4c3" + ], + "markers": "python_version >= '3.9'", + "version": "==3.11.14" + }, + "aiosignal": { + "hashes": [ + "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", + "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54" + ], + "markers": "python_version >= '3.9'", + "version": "==1.3.2" + }, + "annotated-types": { + "hashes": [ + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" + ], + "markers": "python_version >= '3.8'", + "version": "==0.7.0" + }, + "attrs": { + "hashes": [ + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" + ], + "markers": "python_version >= '3.8'", + "version": "==25.3.0" + }, + "blinker": { + "hashes": [ + "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", + "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "certifi": { + "hashes": [ + "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", + "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe" + ], + "markers": "python_version >= '3.6'", + "version": "==2025.1.31" + }, + "charset-normalizer": { + "hashes": [ + "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", + "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", + "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", + "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", + "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", + "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", + "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", + "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", + "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", + "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", + "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", + "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", + "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", + "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", + "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", + "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", + "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", + "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", + "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", + "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", + "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", + "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", + "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", + "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", + "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", + "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", + "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", + "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", + "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", + "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", + "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", + "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", + "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", + "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", + "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", + "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", + "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", + "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", + "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", + "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", + "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", + "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", + "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", + "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", + "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", + "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", + "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", + "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", + "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", + "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", + "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", + "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", + "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", + "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", + "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", + "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", + "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", + "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", + "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", + "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", + "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", + "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", + "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", + "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", + "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", + "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", + "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", + "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", + "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", + "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", + "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", + "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", + "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", + "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", + "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", + "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", + "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", + "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", + "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", + "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", + "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", + "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", + "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", + "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", + "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", + "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", + "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", + "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", + "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", + "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", + "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", + "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.1" + }, + "click": { + "hashes": [ + "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", + "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.8" + }, + "dbrepo": { + "hashes": [ + "sha256:7b9a70cf1bd9d623e52ada74d5585df53716353d509f5d905f1b431dd91c28d6" + ], + "path": "./lib/dbrepo-1.8.0.tar.gz" + }, + "flasgger": { + "hashes": [ + "sha256:ca098e10bfbb12f047acc6299cc70a33851943a746e550d86e65e60d4df245fb" + ], + "index": "pypi", + "version": "==0.9.7.1" + }, + "flask": { + "hashes": [ + "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc", + "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2.3.3" + }, + "flask-cors": { + "hashes": [ + "sha256:38364faf1a7a5d0a55bd1d2e2f83ee9e359039182f5e6a029557e1f56d92c09a", + "sha256:493b98e2d1e2f1a4720a7af25693ef2fe32fbafec09a2f72c59f3e475eda61d2" + ], + "index": "pypi", + "version": "==4.0.2" + }, + "flask-httpauth": { + "hashes": [ + "sha256:66568a05bc73942c65f1e2201ae746295816dc009edd84b482c44c758d75097a", + "sha256:a58fedd09989b9975448eef04806b096a3964a7feeebc0a78831ff55685b62b0" + ], + "index": "pypi", + "version": "==4.8.0" + }, + "flask-jwt-extended": { + "hashes": [ + "sha256:52f35bf0985354d7fb7b876e2eb0e0b141aaff865a22ff6cc33d9a18aa987978", + "sha256:8085d6757505b6f3291a2638c84d207e8f0ad0de662d1f46aa2f77e658a0c976" + ], + "index": "pypi", + "markers": "python_version >= '3.9' and python_version < '4'", + "version": "==4.7.1" + }, + "frozenlist": { + "hashes": [ + "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", + "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", + "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6", + "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", + "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", + "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f", + "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", + "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", + "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", + "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", + "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec", + "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2", + "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c", + "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336", + "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4", + "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", + "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b", + "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c", + "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10", + "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08", + "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", + "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", + "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f", + "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10", + "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", + "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", + "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", + "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", + "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d", + "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923", + "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", + "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", + "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17", + "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0", + "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", + "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", + "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c", + "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a", + "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0", + "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", + "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab", + "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", + "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3", + "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", + "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", + "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604", + "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", + "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5", + "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", + "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", + "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", + "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", + "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d", + "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", + "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3", + "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", + "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", + "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", + "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf", + "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76", + "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba", + "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171", + "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb", + "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", + "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", + "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972", + "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", + "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", + "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9", + "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411", + "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723", + "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", + "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b", + "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99", + "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e", + "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", + "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", + "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb", + "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", + "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", + "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca", + "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", + "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", + "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f", + "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5", + "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307", + "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e", + "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2", + "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", + "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", + "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", + "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "gunicorn": { + "hashes": [ + "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", + "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==23.0.0" + }, + "idna": { + "hashes": [ + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.10" + }, + "iniconfig": { + "hashes": [ + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "itsdangerous": { + "hashes": [ + "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", + "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", + "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.6" + }, + "jsonschema": { + "hashes": [ + "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", + "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566" + ], + "markers": "python_version >= '3.8'", + "version": "==4.23.0" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", + "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf" + ], + "markers": "python_version >= '3.9'", + "version": "==2024.10.1" + }, + "markupsafe": { + "hashes": [ + "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", + "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", + "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", + "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", + "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", + "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", + "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", + "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", + "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", + "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", + "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", + "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", + "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", + "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", + "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", + "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", + "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", + "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", + "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", + "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", + "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", + "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", + "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", + "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", + "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", + "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", + "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", + "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", + "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", + "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", + "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", + "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", + "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", + "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", + "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", + "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", + "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", + "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", + "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", + "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", + "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", + "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", + "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", + "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", + "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", + "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", + "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", + "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", + "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", + "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", + "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", + "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", + "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", + "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", + "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", + "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", + "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", + "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", + "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", + "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", + "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50" + ], + "markers": "python_version >= '3.9'", + "version": "==3.0.2" + }, + "mistune": { + "hashes": [ + "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", + "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0" + ], + "markers": "python_version >= '3.8'", + "version": "==3.1.3" + }, + "multidict": { + "hashes": [ + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" + ], + "markers": "python_version >= '3.9'", + "version": "==6.2.0" + }, + "numpy": { + "hashes": [ + "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", + "sha256:0d54974f9cf14acf49c60f0f7f4084b6579d24d439453d5fc5805d46a165b542", + "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f", + "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", + "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0", + "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7", + "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", + "sha256:218f061d2faa73621fa23d6359442b0fc658d5b9a70801373625d958259eaca3", + "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146", + "sha256:2fa8fa7697ad1646b5c93de1719965844e004fcad23c91228aca1cf0800044a1", + "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", + "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc", + "sha256:4ba5054787e89c59c593a4169830ab362ac2bee8a969249dc56e5d7d20ff8df9", + "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592", + "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00", + "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", + "sha256:7051ee569db5fbac144335e0f3b9c2337e0c8d5c9fee015f259a5bd70772b7e8", + "sha256:7716e4a9b7af82c06a2543c53ca476fa0b57e4d760481273e09da04b74ee6ee2", + "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392", + "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb", + "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8", + "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", + "sha256:8146f3550d627252269ac42ae660281d673eb6f8b32f113538e0cc2a9aed42b9", + "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0", + "sha256:892c10d6a73e0f14935c31229e03325a7b3093fafd6ce0af704be7f894d95687", + "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", + "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", + "sha256:9eeea959168ea555e556b8188da5fa7831e21d91ce031e95ce23747b7609f8a4", + "sha256:a0258ad1f44f138b791327961caedffbf9612bfa504ab9597157806faa95194a", + "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39", + "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4", + "sha256:a84eda42bd12edc36eb5b53bbcc9b406820d3353f1994b6cfe453a33ff101775", + "sha256:ab2939cd5bec30a7430cbdb2287b63151b77cf9624de0532d629c9a1c59b1d5c", + "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd", + "sha256:adf8c1d66f432ce577d0197dceaac2ac00c0759f573f28516246351c58a85020", + "sha256:b4adfbbc64014976d2f91084915ca4e626fbf2057fb81af209c1a6d776d23e3d", + "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24", + "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", + "sha256:bd3ad3b0a40e713fc68f99ecfd07124195333f1e689387c180813f0e94309d6f", + "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba", + "sha256:cf28633d64294969c019c6df4ff37f5698e8326db68cc2b66576a51fad634880", + "sha256:d0f35b19894a9e08639fd60a1ec1978cb7f5f7f1eace62f38dd36be8aecdef4d", + "sha256:db1f1c22173ac1c58db249ae48aa7ead29f534b9a948bc56828337aa84a32ed6", + "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854", + "sha256:df2f57871a96bbc1b69733cd4c51dc33bea66146b8c63cacbfed73eec0883017", + "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", + "sha256:e642d86b8f956098b564a45e6f6ce68a22c2c97a04f5acd3f221f57b8cb850ae", + "sha256:e9e0a277bb2eb5d8a7407e14688b85fd8ad628ee4e0c7930415687b6564207a4", + "sha256:ea2bb7e2ae9e37d96835b3576a4fa4b3a97592fbea8ef7c3587078b0068b8f09", + "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", + "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", + "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee", + "sha256:f4162988a360a29af158aeb4a2f4f09ffed6a969c9776f8f3bdee9b06a8ab7e5", + "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", + "sha256:f7de08cbe5551911886d1ab60de58448c6df0f67d9feb7d1fb21e9875ef95e91" + ], + "markers": "python_version >= '3.10'", + "version": "==2.2.4" + }, + "packaging": { + "hashes": [ + "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", + "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f" + ], + "markers": "python_version >= '3.8'", + "version": "==24.2" + }, + "pandas": { + "hashes": [ + "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", + "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", + "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", + "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", + "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", + "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", + "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea", + "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", + "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", + "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348", + "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", + "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", + "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", + "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", + "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", + "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", + "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", + "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30", + "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", + "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", + "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", + "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", + "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", + "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", + "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", + "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761", + "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", + "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", + "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c", + "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c", + "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", + "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", + "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", + "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42", + "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", + "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39", + "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", + "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", + "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed", + "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", + "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", + "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319" + ], + "markers": "python_version >= '3.9'", + "version": "==2.2.3" + }, + "pika": { + "hashes": [ + "sha256:0779a7c1fafd805672796085560d290213a465e4f6f76a6fb19e378d8041a14f", + "sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.2" + }, + "pluggy": { + "hashes": [ + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "prometheus-client": { + "hashes": [ + "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb", + "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301" + ], + "markers": "python_version >= '3.8'", + "version": "==0.21.1" + }, + "prometheus-flask-exporter": { + "hashes": [ + "sha256:41fc9bbd7d48cc958ed8384aacf60c3621d9e903768be61c4e7f0c63872eaf1a", + "sha256:94922a636d4c1d8b68e1ee605c30a23e9bbb0b21756df8222aa919634871784c" + ], + "index": "pypi", + "version": "==0.23.2" + }, + "propcache": { + "hashes": [ + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" + ], + "markers": "python_version >= '3.9'", + "version": "==0.3.1" + }, + "pydantic": { + "hashes": [ + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==2.11.1" + }, + "pydantic-core": { + "hashes": [ + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" + ], + "markers": "python_version >= '3.9'", + "version": "==2.33.0" + }, + "pyjwt": { + "hashes": [ + "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", + "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb" + ], + "markers": "python_version >= '3.9'", + "version": "==2.10.1" + }, + "pytest": { + "hashes": [ + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==8.3.5" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.9.0.post0" + }, + "python-dotenv": { + "hashes": [ + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.1.0" + }, + "pytz": { + "hashes": [ + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" + ], + "version": "==2025.2" + }, + "pyyaml": { + "hashes": [ + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.2" + }, + "referencing": { + "hashes": [ + "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", + "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" + ], + "markers": "python_version >= '3.9'", + "version": "==0.36.2" + }, + "requests": { + "hashes": [ + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + ], + "markers": "python_version >= '3.8'", + "version": "==2.32.3" + }, + "rpds-py": { + "hashes": [ + "sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046", + "sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724", + "sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33", + "sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc", + "sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032", + "sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a", + "sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7", + "sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c", + "sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718", + "sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc", + "sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d", + "sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272", + "sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f", + "sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d", + "sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b", + "sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb", + "sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef", + "sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b", + "sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45", + "sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4", + "sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796", + "sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3", + "sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c", + "sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9", + "sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f", + "sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029", + "sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9", + "sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399", + "sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586", + "sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda", + "sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91", + "sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b", + "sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a", + "sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c", + "sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405", + "sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5", + "sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143", + "sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a", + "sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c", + "sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78", + "sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0", + "sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350", + "sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7", + "sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba", + "sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664", + "sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a", + "sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56", + "sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e", + "sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d", + "sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1", + "sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964", + "sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791", + "sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124", + "sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e", + "sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120", + "sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad", + "sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc", + "sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c", + "sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e", + "sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba", + "sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797", + "sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149", + "sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5", + "sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240", + "sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034", + "sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25", + "sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7", + "sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d", + "sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793", + "sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba", + "sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d", + "sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d", + "sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391", + "sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e", + "sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f", + "sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7", + "sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd", + "sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f", + "sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb", + "sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea", + "sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e", + "sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052", + "sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd", + "sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47", + "sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d", + "sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9", + "sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8", + "sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875", + "sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65", + "sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e", + "sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114", + "sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44", + "sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9", + "sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a", + "sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205", + "sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164", + "sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58", + "sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3", + "sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6", + "sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97", + "sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6", + "sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae", + "sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727", + "sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098", + "sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c", + "sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1", + "sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8", + "sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d", + "sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103", + "sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30", + "sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d", + "sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5", + "sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07", + "sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83" + ], + "markers": "python_version >= '3.9'", + "version": "==0.24.0" + }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.17.0" + }, + "tinydb": { + "hashes": [ + "sha256:f7dfc39b8d7fda7a1ca62a8dbb449ffd340a117c1206b68c50b1a481fb95181d", + "sha256:f97030ee5cbc91eeadd1d7af07ab0e48ceb04aa63d4a983adbaca4cba16e86c3" + ], + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==4.8.2" + }, + "tuspy": { + "hashes": [ + "sha256:156734eac5c61a046cfecd70f14119f05be92cce198eb5a1a99a664482bedb89", + "sha256:7fc5ac8fb25de37c96c90213f83a1ffdede7f48a471cb5a15a2f57846828a79a" + ], + "markers": "python_full_version >= '3.5.3'", + "version": "==1.1.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" + ], + "markers": "python_version >= '3.8'", + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" + }, + "tzdata": { + "hashes": [ + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" + ], + "markers": "python_version >= '2'", + "version": "==2025.2" + }, + "urllib3": { + "hashes": [ + "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", + "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.3.0" + }, + "werkzeug": { + "hashes": [ + "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", + "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746" + ], + "markers": "python_version >= '3.9'", + "version": "==3.1.3" + }, + "yarl": { + "hashes": [ + "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", + "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", + "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318", + "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee", + "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", + "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1", + "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", + "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", + "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1", + "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", + "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", + "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", + "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", + "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc", + "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5", + "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", + "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", + "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", + "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24", + "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b", + "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910", + "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", + "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", + "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed", + "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", + "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04", + "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", + "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5", + "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", + "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", + "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", + "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b", + "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c", + "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", + "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34", + "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", + "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990", + "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", + "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", + "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", + "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", + "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6", + "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", + "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", + "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", + "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", + "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8", + "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", + "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e", + "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985", + "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8", + "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", + "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5", + "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690", + "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", + "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789", + "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", + "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", + "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", + "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", + "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", + "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9", + "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", + "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db", + "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde", + "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7", + "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", + "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", + "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", + "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", + "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", + "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", + "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", + "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd", + "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", + "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760", + "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", + "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", + "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", + "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", + "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719", + "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62" + ], + "markers": "python_version >= '3.9'", + "version": "==1.18.3" + } + }, + "develop": { + "certifi": { + "hashes": [ + "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", + "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe" + ], + "markers": "python_version >= '3.6'", + "version": "==2025.1.31" + }, + "charset-normalizer": { + "hashes": [ + "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", + "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", + "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", + "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", + "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", + "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", + "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", + "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", + "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", + "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", + "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", + "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", + "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", + "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", + "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", + "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", + "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", + "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", + "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", + "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", + "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", + "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", + "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", + "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", + "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", + "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", + "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", + "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", + "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", + "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", + "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", + "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", + "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", + "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", + "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", + "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", + "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", + "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", + "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", + "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", + "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", + "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", + "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", + "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", + "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", + "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", + "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", + "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", + "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", + "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", + "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", + "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", + "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", + "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", + "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", + "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", + "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", + "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", + "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", + "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", + "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", + "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", + "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", + "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", + "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", + "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", + "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", + "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", + "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", + "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", + "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", + "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", + "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", + "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", + "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", + "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", + "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", + "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", + "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", + "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", + "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", + "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", + "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", + "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", + "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", + "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", + "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", + "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", + "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", + "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", + "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", + "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.1" + }, + "coverage": { + "hashes": [ + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==7.7.1" + }, + "docker": { + "hashes": [ + "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", + "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" + ], + "markers": "python_version >= '3.8'", + "version": "==7.1.0" + }, + "grafana-client": { + "hashes": [ + "sha256:2477a47b923fd0637947e620b0b777c641af18a3025464fa4505783dbf05dfcc", + "sha256:8cb61bb2a87ec07bca10974df276b9a1a95bfdb63f3a696f065692ffc9b8c389" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==4.3.2" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, + "idna": { + "hashes": [ + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.10" + }, + "iniconfig": { + "hashes": [ + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "jh2": { + "hashes": [ + "sha256:038091480cd1544e9389b0adbb1b1645a797689dcb68ceae7e45eec96ed24497", + "sha256:0c8e336df8ed1687590695f4469f480eeb4159bf13bb6193791c6530fe114b49", + "sha256:0c9bf2d5e4ef45c1686c6f76935e7ca263f5eae4de92bf5d1873a0e737e4eb7d", + "sha256:0faf6e96f74d27b8ca816b40217904891f91b664ed1c0388737949ceb50ac15d", + "sha256:10ea7f497e6226372e1d4fdbf42c8381f4887819a643ab930bff4072ad298d84", + "sha256:11650f7ed77ee1df30f25d6b3b74b2fa1c94124e074fd455abafea3cbc913d53", + "sha256:12ead3ee3e9c7caa00356b528a5cc7fe210fbe2060628af6e19ed76b8416572e", + "sha256:136b3c5b08883681fcb58f12393a5bbfa422d6e2d5ba887e263e776874276bc6", + "sha256:17d6e1691154ea9f726e43dcb717df48e56c66b5a01c90ad675c6494c36e5be1", + "sha256:19cb987915cc0d321746a12f2a693d087ffb721c37ac9a153cc088c57d4d90eb", + "sha256:1cdf15de698c4026e64fd914fead3180e52bf2a7bcbe44a3392404582dbf2d22", + "sha256:1e81e1c64e33506b8508ba5e3c7c139b2577e78b079c2c16a8e7a02a161f1080", + "sha256:2226c76e4ff2149c5d9f94bed22bf9c4f3411d38cc53d4a7ddfbe0899c8b558c", + "sha256:2837412fb7b684c6ce7392c8bc57440c6dbadaf1bde7a53144381f7df7083c1c", + "sha256:293f0f3da3c391e997e0d55fdb85540e98a8b0406622bb4ba57fb7617697f31e", + "sha256:2b9cc6c0239215a349d28c192fa4c4e7a7348eee7980531525c01bffe39eea80", + "sha256:2f3ad679f84ff236a0d7b71ddc4b3c09fe467abee2f1a86671f0cd417be5352b", + "sha256:358cad2f328c52c15756cf32b0ad17afb0d617e7cdfe93d59aa2616966d825b7", + "sha256:3663712305b509f79c002c8c0ca9994f716cadba576f5a59632dda1aec1ca8c6", + "sha256:41794820ccca039ca2ead6245f30b34601dd1456eee5b5dde620672bb989e79d", + "sha256:44b7e64aff542471c474c24f771eae5efd9152da02a12556f7cb7607020e1420", + "sha256:45770eb0990166026538d3c2fd7d92f17cfde13ca6567570c4baec3ce9162936", + "sha256:498060078a4d1b458e9381fefb027d85329397b50d65287712b3d48233e20836", + "sha256:4c2f18f337c2393f84e45e5011c8b02697b81638b1cec49da60a01b9ed067695", + "sha256:5162d6e475d2762035fb8ea25982bcbec6c58715e33bd0951499f743cd90b110", + "sha256:51e8c890bb59008c95b3a552cefd8bd9ce50a7466a6c920a78cf586e885d7449", + "sha256:56ad3839ac6ac5fd3d023cf59d4b04264b74bb4cb44c0780faf51d6b5ff38fbc", + "sha256:5821638ef0d7c973071810a6786f59b305172197f7e7e469a2ce169e7f4978e3", + "sha256:5ac1b2d379f4d40c13dcce537e69704452943cddbe991fd54a84fdb2da9026d5", + "sha256:5b465d4311b0429fe6fa85df8e2cfcb038c9fface95396dd14e838ecabaaadf2", + "sha256:5d8656b98057329bd03d968aac8d5198389cf51517511295cfc4cb827a507e39", + "sha256:5dcfb3e823ef4b91b70b92848570d1d8cfd584304bd2bd54272dc100c9494def", + "sha256:5e40d23ea43f683f3a7c032dde391104f609b05c21b6d284101120b51dbd50c1", + "sha256:63a01522bde161c713f7fa5ee5d850fee6386fc386073490ebcd438f14579cf2", + "sha256:6b2a3d7756035dde13571f4ad232629b78b7f35c2cd5fda7b464079fc697db3a", + "sha256:6b3be1a6bf6c965aea3b4e3a40df9d2c134c516d89c76cf2b6c81f67e6c5c6ed", + "sha256:6c7bea3357f2dc653756e6da55f66cd21c73d3875c8f3dc4e8d196a876252de0", + "sha256:6e6c8e229507cf29333a2f491cbaa7dff5b8a4a3e613af8090ccce9ce3e4f7a0", + "sha256:6fad27f2a63884ee45d491aebec4b1f38752cd6aaccc625038c21e7f43c02c49", + "sha256:71bfef52547c2b8b145897fa8d1b5142bc52313cfa38c0742e0ef755f0d09c60", + "sha256:72370d312323282b1bf74426e53fae861a310d7ae519b419da46673c38e7d147", + "sha256:76c7d36043a9c478b0c846fcec7da5cb095983722473e503e0122ccd170182b5", + "sha256:78d8a81ef51edb9a2f278a6fb278789b49e304b12bb21bccf2fe7e344f71a9fb", + "sha256:798a6b159ce32181a5e7ab7611c17d1080e74a5541fec47f961b728dab25a76f", + "sha256:7e370567f66a57e2c0e3ae2afcc6f126e1d6babd36831cfd0caad279b05c1c88", + "sha256:8004b845f606b95a8b17efa112aa10b327e46e95dcda604a257b4633d4ed45c8", + "sha256:80b20bf9ea4e709b3b9ae364ac298dfa872b084c186e5c1d60b0b79c79a7ee7e", + "sha256:87303f4bb1b493997f911a4f126123ccd2827d3a2e7dd2390cc6143fbc75805b", + "sha256:8d423f4631395b92dceda39f481a463498131ac02a58581124a44495491f715b", + "sha256:94ee262192db50fb9c069a0be7bb1a426fb1b43af26ce12bf4c6c30e13f46b56", + "sha256:960e4be2e7de340300ab4bcc2b45bed46be1d62330575b8265e6602dbcb9a14c", + "sha256:99397d5e1da6b345cec3e6125e2902b0e6864eb8eaa4be43a2013f059c502c93", + "sha256:9abbb8c1bad08817bad62ae1ea76c01bdbd0ee8c827d05f3ba038c9f6d6f14bb", + "sha256:9c0b8fadf80bc70d341032f92702bda1b0ed78c01e9c495f0df701938c99bcf5", + "sha256:9f977da9abae170eebdcf02bda33727c342fad5dcdbc08498bfdfb6cc6c65489", + "sha256:a6be712ca39d5e9c89b705bc9800be36739436fefb8d0b52b2d332f7d6d22a01", + "sha256:aa434418d6ee44b0ba3a5a407bc9e1543cf496328f43f149e9b58f74a63d5c21", + "sha256:ac4f778e32f7de0ba63346893a4af87c2280ffc1783f594a117be51d908a10da", + "sha256:ac85d65ee369c09b2904b55078ad589961e2e2e03c810963d35a26e6a3931425", + "sha256:ad5d78c664d39960435d4162db31117c8945ba74fb0c414e79ba85a8bdeafdec", + "sha256:ad91f57c3485d87a8edee558dafab0f08c716857d748731c0998dcefe9d3fd5f", + "sha256:afd255d42b340036883ca95bded553b29065b064e2fe5db64ad5988517db9694", + "sha256:b1c2c74f100a0c2110a8e30445554ae331860d32f145c60a2a1e1c27702022a2", + "sha256:b49a8c71378d40d43c6a56eaa536d7823baa43c27c93e082aeb60a9717be0c10", + "sha256:b5f52611323e8e35705e6750a760f32165b41c052d22da154ae343871e7cd50d", + "sha256:b6bf99ae529ac359263269710356d3ddb173c15d8f8dc8849ae794ab811e5cd0", + "sha256:ba361bf87c4701f11241be92c99ef5cf916865dd225955cccb2376bf76717b3c", + "sha256:bc351aa2158575e68943d8e1d5531719ad86bf6607776627ed5a1a60657664af", + "sha256:bd6eb7b1e12e4dd0b75cab1b023272f1333494add5ad61deedac738af1ffeede", + "sha256:bf8852595f5e2d2b072e24c29394b5aca7fba96ecc8656d56660535f9e9872c9", + "sha256:c1dd66541569a2bdbe92589cc96a89f470b20d168f2238fd463e1b59ee3e2d49", + "sha256:c36a7a004cba4e370d0675826eeefe4e42a256638b6b1432263ddb4af317bc02", + "sha256:c886cda61da4d39010be84802bed11bc75f03e8a6094cc18016957a2c80254d4", + "sha256:cc7aa83946f80c66a5d2dea7e165f15aa3eb21e7b74b24d8f850afc0d44bb00e", + "sha256:cea9c4bef70d1358bafec6019164abce362f4de15d79d1ecd64ae31c1749d77a", + "sha256:cfe1951e80869695857986be104a40a1e7fa8ec7de05f86bcbd7bd20854be764", + "sha256:d36cf6f139da3279644794fcfda18af425c8bb122ef9c2e7c762a937bbf7b0f4", + "sha256:d81308faaa9393b7e6ed20718d465c4c2b73c24d5e4826024961acf4b87b1524", + "sha256:db51ea1f9c5ac790848bc271fcdf4108ad1b77a77c6949a96320477962cf7ba5", + "sha256:dd05c18c920a15e00d7a52df37bffd3930fe2c004c690f9422b20e12077e6dbd", + "sha256:df05918a11e1db0198d00486e36673b4b4a89390e4458ff9479b4908dde357ac", + "sha256:e4c31dccf6be131709e545d0258eb5b75c5fac304857ad3976331c6740e8b9d6", + "sha256:e60954d673040430802b29fe5bba698e262182b5ba5f302ff4458e39f8101881", + "sha256:e60e2d2c88a0552e61c37172fe377f6a8abf479130a445314886de4a360ba940", + "sha256:e786f773ddc153846b2ebdb854011cfd1f7c874b8ee79cced3706801341c9f5d", + "sha256:e7cd91548fb95b69edd376f5204e27115ac7d093ec7d80066123a5bdb31c71d9", + "sha256:eaef2ea4f5602aefaaf3d6e8235f3b9ffde35aff15aac1c16cc802f6bbf0a3b5", + "sha256:ec8c5ea93a03775fbadd08462200cf34ce617ec75a032abfa44fd6d3a00e5424", + "sha256:eddeb8574bc9d9abb8491d4a46b60e553c2cea235b80373756acb06568101175", + "sha256:eeb300b0e4b428aab2f70d785cad4306529262af6de8c8c5fe6a4b41a674a434", + "sha256:f39d71ece8e97cf069e4154868eaac1256b133fe23e0459829432e4bb6406472", + "sha256:f4840ddad2b9d53710e92361391944da89e3576641a290066a1719520059247c", + "sha256:f70723a00bcbce0f9a216853139955be45da35741335eb3afead304e77662560", + "sha256:f829cf2ba5b553e6529d6238928c07096f1feb47f4ad536b7f06bca6cc77173f", + "sha256:f96386910467725895f7972939a6faabd6e96b1de0cc2c092e4bd2c40e956e25", + "sha256:fe259a9d6f555bc79aed9bb4b9a7fff73db443b4c483e4a81a428c8a2860428b" + ], + "markers": "python_version >= '3.7'", + "version": "==5.0.8" + }, + "niquests": { + "hashes": [ + "sha256:68e0a7e9f338466b3606945fffd11f75e3c90af7498aa9336ef03812323b7e36", + "sha256:86e484c2c60444aa96069c15f6295af6e25a8bad50781e1326df1b5c7ab48339" + ], + "markers": "python_version >= '3.7'", + "version": "==3.14.0" + }, + "packaging": { + "hashes": [ + "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", + "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f" + ], + "markers": "python_version >= '3.8'", + "version": "==24.2" + }, + "pluggy": { + "hashes": [ + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "pytest": { + "hashes": [ + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==8.3.5" + }, + "python-dotenv": { + "hashes": [ + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.1.0" + }, + "qh3": { + "hashes": [ + "sha256:0107f576a0524421e1b0f9e0437d2881a1835b1b6105eadd7ea0c1c9bf2da917", + "sha256:06159707895c606a321ccb5630347a2d2a44ee584f22945e5b22b0ad34f21ec8", + "sha256:06255835f99ea1af9e5d358056011686fcccbafaba893454027daa62ab6f701f", + "sha256:09b2305a954e61a9ed8b46a7a45f54e8d95ef870a47d5fd1836e14c7600d3b92", + "sha256:0a51dcffae03a89ddbab1884860569e0d1dbbf95deee47457c1fd29b4ac8d220", + "sha256:0a5d1cd881b7d43481ad60262cf3390a555e0e51751bc2af70ba4a612487e797", + "sha256:0e1c273660f9b8511c22d0b082137556e46d6a7eccf132bd82f95d29f90488b2", + "sha256:0e540cc7e7da65da30381bdb73a789a8635c6aaef98688d904eee3bc587654a5", + "sha256:10ed818f47dc522350a12641e8f2bea19ff824f8ce373c23a8e594b3481fd7a4", + "sha256:195b4ad58cf5a8da218e2368d34f47628c14581f3cc9863fc0406b32e137f3a6", + "sha256:1a80d07249c7ccbaa57bb9015b5ead0ead7ac1940cd5483548dfe56db99ce7a4", + "sha256:1cf0b18823801078d2294a0356abc2be34b4a224bea863a87029c1c97d6c34e0", + "sha256:1fac2ab4b8a2e50894b54a19416cd363defe0fb33f52754686ea58999f98dfc5", + "sha256:205cdaea9da8881b31b76eb6da5b88c9558ba96bc16a3ecf11333098ac7f3859", + "sha256:2294e78bcc40728a3a772df0f8ecf8b8756616d06dd001029016876aa4e5c9de", + "sha256:235236ab195d34e7cd18d186e46b7a4f8aceafe246bf36b42913f72627ded414", + "sha256:25eef1f2be50d79d23e01a567c719e46e4892518a5ccc96685fcb4746357320b", + "sha256:2ae147b756c3adf59699756feb9e07d4a69674f57b4e13d6c25f9d1dc3c8707c", + "sha256:2c9cdd7ea49c79b671e7de35dad61d2aa91920e2498d0c6dfa932d5e05070a5e", + "sha256:2dc9f269d7316b0a44e61ae7a11ffd8daa800b3f5ba773de2e9d8c4ee636a896", + "sha256:2f94d69edb0070ef4ec414deabfc2369aa2100b11bf4a4f2f393f2c28c4bc7ba", + "sha256:311da331e31c55afc3f4f4f2ba9d07a1d700ffb7db5aa4f58300b9f56f2523dc", + "sha256:3578844a9ff4c342a409d010f909782afc52a31680876f7fab65bf133aa3f4db", + "sha256:4032c2898b4c0ff7a25cf7d68c3b1f2abdcaf4f25cc8b6802a941a842f9a95b6", + "sha256:40abd150eddfa0884c139bd281e87ff920d4cd52d685fc4ef25ddcc77ff7a220", + "sha256:43e32602651d07f8a0860ba0a45d8c8fe9ccd537030e7632d1258f7b84881416", + "sha256:45a21d25fe17168f4db09fcaabee5dd171763ad1bd8753c257297837f5ba9197", + "sha256:45bfbb126e31ecf63ef74c249d38d07e149c0663b4a191cf9e2e3445a80758d5", + "sha256:4745667c9956bcfd74ff677edd4c73d6cb578b6b47c5fb3d246aaa223dd6a004", + "sha256:4936a5d8915866b4f08ab18018f41ed93a2593788ad0a80796aada2e23d402e5", + "sha256:4a45a9698b3bcae05f91356f50df8dab3c3fdef3187548b9c4a396a6eb6760b5", + "sha256:4b84c1ca283278e2e22a3b9e2ce8ea55c0a1797d6e86255640a1b6293fe18b2a", + "sha256:4dc88397ed7f3b46f542f87e19050a7f82267225009ce65651ac44cb55b204b1", + "sha256:4e10a872077373c71d7938fb1a7ae0561f2e79aad2b1b5323dbb6325a389041a", + "sha256:4f1b5dcb4d9da5b441e0b14216b816be7b5b5d080c2ccb957adf84266411ff6b", + "sha256:50d25182d598312197f500a65acebf5430391764e6ffcdb73d96e80c5dd06fc7", + "sha256:529c5b9e27fced27befce26e2699eca3110c576f6427dfbd26e30b7666b2d6d1", + "sha256:571da625b22e953731307539b44b2177f6ab13b6142d7698c0f28b9379ae1be6", + "sha256:5a9de89e2480b385a99613798d375e69a0a53d4575bd74b133307c8e83a84751", + "sha256:5bcc46cf89cb1036c2d029c01f360c82180329997a75728b20dc205f34114327", + "sha256:5dfa6238a6236f2bb3ecaac9befd23cee0bcbb9e497003fb3aef875e19325c61", + "sha256:6342b961b18037e3df8692e8914c576816a966bf29f913ee2728e7e838bde9bd", + "sha256:65e112c175a0b0328822dd0d19ead9ef1d7925359d154fb52e46b080945eef38", + "sha256:6f8a2b15c4dd58133e92f95d4312efd09b87ec15b881885629dff70e89f1e751", + "sha256:726f749444d1cc73c1bf221343dc6fdbde2541ffe30860d2d5ef6e310a1f5478", + "sha256:742f39cd807df31c21e035aec63f6f61e139a60545cffb16e8e87f61609d7cba", + "sha256:7840c18ec27aa08ecdd8ff23df348c124378c6f3edf9a0e02b16a5a4ce504c89", + "sha256:79d1de24d3c7345719af8333b64f19a8777dd50a059851bfcfa583c7109eddf2", + "sha256:7ba9303c5334d64b547483be92c4bbacd37964ff3abd0b1e8c82c63ec6f7b3ec", + "sha256:85587d9dfbd2f7f8622cf57f3c1a19cee441b5607a982cdf4c08ef38d45d5a36", + "sha256:8711b86e447e689d1b693419708b6ad64bf0c57091b94a3f65c6d4bd7cfb7d9a", + "sha256:877edc4db25309d86af07d992926394936f491cce84fce439961729552e942fe", + "sha256:8bb17669e362d3456bebd5c69abb0c26e8ab29c10894f123c715b0217aece479", + "sha256:8bb17a1e50e35a8d07cab784caea68b33f739391ccb5e3161afb9db0bde8faf4", + "sha256:8d4640a6bb3aa29797bdcf0c5bae4e86da5f2fbf84b67a7fad549fa34c19aa98", + "sha256:90697f3d9e4b3ddccfb31b40637bac6d44b39288cd57f78e51ff13e70916eccc", + "sha256:90f127f57c00b111ea3ffd95f4c12ad83efebd10310fd718d66771dd64e568f1", + "sha256:95f8f70bca1e880da7559ef38b7f1778a3b39b586fc829b8a7e989e912aa988f", + "sha256:9a60c102a01dfa8c5d737499c9a5d5e7c2b6642009c9b80b27f228ec50ce6fb0", + "sha256:9c7f1821ec749ea29bd9d079e4f13a552371731d0b664962a60cbb2f31d571b5", + "sha256:9f81ee66fadedbfd4d5c49e64151db3b6f353b041ddf5ab0b151340a4467e038", + "sha256:9f8e530e29e1afe9231b1100645aa5cc240b823c0e4162f70046270a3559400c", + "sha256:a0c647db3f156e8c94a63c1fa0fc4f2ce8b70f0eb12f2726e6c19493198b1e99", + "sha256:a0cda60607ab4ffc14fa8425ea7c9ae78ad60923c3c8be94d19c14f83198b1cf", + "sha256:a5bff397d49da302b5afbdf244dd7ca480a827f5de856d957df05dfd7e73b490", + "sha256:a94bd391b955b24948b2986845f9c6ad8abc709c2d57d0515daeacf16a2a3a4c", + "sha256:ad4572bd37c1a6a7a12ff47da4f3578a13e3c8ee85a1f02d2435dfdc6d9ed394", + "sha256:b13b7de1686f1b5da7526dc4f0de410a685f5cb654e984b09ddd8d14be6fffc0", + "sha256:b1724c43c5c0d08b68c3407467e07794b9adf153b6de8300d61883e8d95fa640", + "sha256:b27d29cb718df9ed006f8c75a89dd90534437761b2477dc7a4145bde0daa60fc", + "sha256:b3afa3a78b0f011ff5a09dea37d74fcea9269b318d2828f18b2fbf9dde625a71", + "sha256:bd6a61007e678284178bb00931af59f686a2a55797505e0886241050ec5c243c", + "sha256:befeca45fd7787c08a3286fb72caaccfa4c3962760981dfeb0992f5ba9be5cb2", + "sha256:c2d31b8233f406e00f180e221986f436765c3bb06839e72c898feca31fef1d4e", + "sha256:c3e2518ce442b70314892a594e21157deb13fbc436f77ad6555439cfd9912035", + "sha256:c8d5fbee607db24ef6c7b0bd08c21226d10782df4149b9d6f1f1516c7c85092b", + "sha256:cc2cc804998e852bdffcc87e8d008043ffa85efe6d3516d9784714d709f14774", + "sha256:cd8a681107c6118f60a0714671cec7b301533f25984a5c898e547a33a01af75c", + "sha256:d056831ebf3fa8116672ae970ad19a9f5f1427a2217cd0e01c1eaac5f8222668", + "sha256:d5ac3e8e3f66ff88819205dbc67e6f771cbb80529325ca9f3bc03fa00c5c83aa", + "sha256:dba15ca2da7859300ae79d2ea2eb8bb0eb827b93a2f104981783add16a97058a", + "sha256:de6cabb89248b60ea9bb9d7848de78dfb824abfdc15f52448a8efe821dd7d559", + "sha256:e02f6d1cc2005b847176dd8770fdfe90f04a34a3f094b79a8369bde0aa8f6a04", + "sha256:e514bd4b27c953c46485b2be0ecd2421aa196c5a0cd7d67f1ccec16a56b00507", + "sha256:e53464124379764f982a69f5ab34d0d5c527e8ac1e788db86a25f79045e5b18d", + "sha256:e9cf59660a543bef86de457c671c1d78ad2d88c53bb9eb3fce6ce0cb9729d490", + "sha256:edfc1bc732bc5e62fdaea268a541eb442d5e04927cb27dfd8e92ef07213658d2", + "sha256:ee8e7a66be70a18f5e0558f2f6a89e39c608f87b027234848f76a6699975dcf8", + "sha256:effb7072efef7dca10a98c24be0cc882a40edc78e293b41f5b6dc7f1952215ed", + "sha256:f04e4ee7e3c123ac7f21cee6f819cfa9b5a376e656257dfa7a4d133b3590bdd9", + "sha256:f0531c7abe963affebd3fb6cf9ea87eb8c63a0240535d81d0223945bd41be254", + "sha256:f5afd1c216315682a6bbf606618de0e3817ed8eeafc27ad7660ef2f581d4fd46", + "sha256:f93d3c74e00268ac6042c080653a34d0f0e8903697fd8dc480c1e3de81c90faf", + "sha256:fbc4e6452cc48c3e1398fe930349e2ec9ad76a2c00e729f3e797700c2f0646e6", + "sha256:fc73fc2889a01a43737c7a7c7fb9ee13aa56065b22abbed0e787cc58a3747808" + ], + "markers": "python_version >= '3.7'", + "version": "==1.4.2" + }, + "requests": { + "hashes": [ + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + ], + "markers": "python_version >= '3.8'", + "version": "==2.32.3" + }, + "requests-mock": { + "hashes": [ + "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", + "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" + ], + "index": "pypi", + "markers": "python_version >= '3.5'", + "version": "==1.12.1" + }, + "testcontainers": { + "hashes": [ + "sha256:348c72d369d0bd52b57ab4f07a965ae9562837098c28f0522b969b064b779f10", + "sha256:36bd2b58d91f2fc7ac4f4a73c6ec00e5e60c259c10f208dbfe3161029889be92" + ], + "index": "pypi", + "markers": "python_version >= '3.9' and python_version < '4.0'", + "version": "==4.9.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" + ], + "markers": "python_version >= '3.8'", + "version": "==4.13.0" + }, + "urllib3": { + "hashes": [ + "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", + "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.3.0" + }, + "urllib3-future": { + "hashes": [ + "sha256:255fa9ba873e9045a5fb2e9838e2b108be35519c29e7f3accff13ee4c417a1cf", + "sha256:7243b5bb8d8cdbcbff342bc31b885e35662c4dcfd94d097473cce1bd02944cbf" + ], + "markers": "python_version >= '3.7'", + "version": "==2.12.914" + }, + "verlib2": { + "hashes": [ + "sha256:2862f19528db400d130253a2b71c7c3616ee14e1d54bf6833bc0929d2cddd141", + "sha256:cf8e2be044b834a2670f2d4c20a93cfc674933c0070543a6f61d531439cca200" + ], + "markers": "python_version >= '3.6'", + "version": "==0.3.1" + }, + "wassima": { + "hashes": [ + "sha256:10508102696d5e2cf4df6942a8ae251c136a49dc32591e9c3f7dd007f5ea1c2f", + "sha256:1102836ba373912537eba891e7e5893532d4ee915ee2486e981b73f925f63c37", + "sha256:11887557464e0c3f9694fb16406bb56c1fb1566178cd04bfb5b4624fad183b31", + "sha256:12c855cc5b96a2ac32d405ab7de1563fc91be54108b4fb16b06d125d07ea892b", + "sha256:134e863b692c35afe8f5ccbe8082fa39963804e20439a4c7aa98510197034704", + "sha256:17f129f4d36591772d906bcc893b76b236363fda61b575067ddfa8250f84ad30", + "sha256:17f132ffbab294902f8740708f27fd995ea04182fe4b4fde20be563f8a010715", + "sha256:18bc78b2230c6f1f9ddbeb6ca38439fea4cc8f60836af4f3538ed259e60e5eb8", + "sha256:194c3fad38603618dec03307d10a4ece852516df56560e04fb2562506f79c175", + "sha256:1b18ec743ab98dcbfc221749026b23fc573891651342f20971e53bdbf56d28ae", + "sha256:1fa19a3652509edd18f693cd9c873d8f73c9d1624eae6c3bf93e561b18ae2766", + "sha256:24bdb1a2b90c215e11ed7ce82ed7eada339c7dca8e0366916e4e3215b3b9d8d3", + "sha256:27d518f0863788c826faf387326f3babb3ea95a0b908f5b3ad2bc1fcc3c5a37d", + "sha256:350b5854dfb3eeb95cd17723b0f3503de0c01454da5ae7d60f192be2009239eb", + "sha256:3b3a4c8ffa76147507f0c88c5cc8c76ef96ab93b81e49b288a3a0b94ebfb34af", + "sha256:3e00fa8ff1aef7d8aad2e1b957add6cba8549a42e415400bd72ff1b61dc9da9d", + "sha256:3f29045dd0a7c287f850f1dc3948632a2d2cf7dd7ec02271c5f248f058da5650", + "sha256:4a528244e4a0f9e01b8593b1c8a60ac1d80ce8b13fe079f44b38328e4be075e3", + "sha256:4c4f5ca102fd083aa2b05c65a1fd18175e3dc7a889525fd2964219ee3c51edef", + "sha256:52358d86195954816231d2aa8c2919b85075320b6d3ba5b96216985c3182bfa0", + "sha256:52f473233ec4d57322c6295e85b3912dc1fc400d6308a04bd427b863934aa74e", + "sha256:556cded582aef3089de889b5a6efcf6d87fabfec55d574fcc3a4ada21308d487", + "sha256:564eda7bf0420c8cbebe5e8efc15f1b27fdcb37ebc4c2f92b8461ca83381b223", + "sha256:57a0ab5aed596f129fd4ea7584336b11fbef25c07d1351e37a959901dea8728e", + "sha256:58f1fddd660da8c8f30f4b8460129e2f217c226cd1b54b1cabb6465881fd788a", + "sha256:597b0d8ba697f4319bc1f301ed31630ca783c9fe82d2a2434dd2f7f709c4e394", + "sha256:5b194f0de77a4ae7bcf217a3ccd10798e94ca430cec6307628098a61cd2ac230", + "sha256:5f5ee564f4b836ed1b70ddb187c817e8f6f1ffb521a636bb20676f07b523396b", + "sha256:601f96340e4c8071994a39a76d4278e8e1d087cf385781dba795c5334262d865", + "sha256:61bfa09f38c36f1b1e6e44e7af888bb8f9d739e86099082a3b45875651a425e2", + "sha256:67fd323b8ad0e057c06b153983d8c50f812aad979ac89b07ed6952c345f6da02", + "sha256:69cb51f629d118256da3d2373575190c7e30d3fa67c344dc655f6c8ab3e83f0d", + "sha256:6b1d7ceeede8d8eed48616d2d33ed23d2dff307d0b17c577eafdadafe86a0478", + "sha256:6b7d696155ddd7ab5739ac221e8854115d0d8171bbf805074d9484083de386aa", + "sha256:6d23e9483756b81850b82e8b7ed20fd23de22b50d6a678f765c660d4206b7ce9", + "sha256:7b0229fecc849234f2a2d11e948ac38a9bab02d201fa4d6ad43c143e18c1a66e", + "sha256:7c53050b670d702eed541503175bd5441fc4bdf3898714f8eac8c6ae9db548ac", + "sha256:7d65676f1fc138d1742f704bf490045571b9c2c48cab7d2c2076a52729c143e5", + "sha256:7db25328c40cd574e5a68ef6507c5af4d1fa2a44cb3c028ff9ca6b522f8faf32", + "sha256:83ce1b09e9eb2ae033c303b74ecc4f3186bbc0897db1d8cd9942153b0631b8e0", + "sha256:86c509900cbb90b7b75155c580b22af591b696fa059059bcdbd75bc74179df85", + "sha256:87f80d0075f0d396b73d41bb1626a2dd5607e0db4b74cb17e55d874fcd538971", + "sha256:8b719755d556649f2fbf226cf1ca8581ade114751df1facec96f94e75bffdb3c", + "sha256:8e739d4192758df6e5363791f527deb91c615d63020ee8965df4bcd1a217f9a5", + "sha256:923d3bf8770dfeb3d94bdfee1c5b5a081592de69766436a395e1e6203c19cf71", + "sha256:97772bb55cb47da3de49ca4b59309a9bd91ead730a7cfac1992932486fb41352", + "sha256:98bdfdf734144277132f34f770eeb6b0db2c4de87415f34b178adee766632f24", + "sha256:98f38b1b01e6f270b9279d76261d6f222b72ef06b025cbd4911b962bb6de4c98", + "sha256:99318b5ea78843e3c3e19cd56367216774674a99848f00a6f2dcf84e36039641", + "sha256:9c623ef06876d432dc8acc93ed3494d3453333d767b1b06bba1a016ea9d850c9", + "sha256:9d0f9720dfd0155432d23bcc3605fe5831cd0f586ede4f14ff6f3bebe8fb867a", + "sha256:9e79216760faac6395bee8ca4077a53a309312faba0f71982127ad8625861780", + "sha256:a470c908fd9baaecf41715ea3c30c57b530d598ae5e9de7e0bd532755e66bb1b", + "sha256:a634b9b79e059f45a56ff3ef6e7241662bc6f0e5a096ee6eed6770ea368e8278", + "sha256:acd8195a53d0e84ea95bdf15a2651c53b829a3ddead21b4a620b6a0c5e1ae2ff", + "sha256:addbd207df3718fc9d9de5b6c90a5e3fbe667830cf629186c9fdcafbb6578cb4", + "sha256:ae2aec9d55e108ae2d22fd0bda24450a6c13c116f9698b9e7ba2c6492c4fe715", + "sha256:af6b70ca9788964c5da5b59ca412b62db2ea7f2386a91c0117667bdd963e828c", + "sha256:afa7d60a9203db36a55b6f2868da90aaa829ab415a21fba7fa75678789aeb16f", + "sha256:b08c1931c44e3c034e645f3e3a7f4c47e8b0758fb8f09a52d1e880a307a1066f", + "sha256:b22e356914e606ff398c002b9925df4454c5deca9dbe55b3ba4a5c9b2365cf0f", + "sha256:b8c0f50397c51086df941b48057c82f85d9da000bf4fe6f4bc64c4f649b26a5b", + "sha256:bc068bcd79fe017866f536e0ad9424793220be34e3124476e17e6cb77a97e690", + "sha256:bc30f5a605a366acb7f301b3421508eaec3c1a515c960791bd776cb63d016302", + "sha256:c0d246b3f8a771578279eab9cfcb820dedefd3dd5dc0e34b37a337fe46271fc0", + "sha256:c0fee0a8593028bde17b57527b1ac21fea74f209b3522363e3ba0197ffaa6323", + "sha256:c139d5b103bb1f085d8918815d62ad946224a658ac1a7cc1b93dc44bd498ff9a", + "sha256:c25235cec12c0e38b4104268e312c9c2f3527ebc126d296cff69ea7aa13434dc", + "sha256:c7429d038dc383966c692e752010cbb4d5dab0e515f231aa01cd746aed9db359", + "sha256:c85cd2e64967c0dce2927ad7c62c090aae6d6b7f9e3a6b9fb91f58b890ea6adc", + "sha256:ca04984df012020dd846599b8555666c544982c2a91dc6135565e6708624eb71", + "sha256:cb7d43c07d58ba13736e70dc3e064496efeb1ed4475a28afb26b7a3b030b89df", + "sha256:d018e05cb61eed3050d45bd0c0ef9b75420899f6ae254e68e7f2ef26975098c9", + "sha256:d24d42881eb74729b34014e2e87f3a4d0419c43db309de2dff3f39118716865f", + "sha256:d6e17f218af856ca22c30d1a1ac58b19bccf768b8589eb8d6e45e1f1ff258404", + "sha256:d855d0be1759c5efc404c04977ee48a8b6260aef6441e72c10973924dbde5a73", + "sha256:dea0dcc0e50978ef73be8cb384694b71a6e64b46847ee7decad96dc85fbf650c", + "sha256:e1e9228049cf2442ac486a03a0d543c5dff3089a915a3e39ab809b22672e1d76", + "sha256:e26d052a248d5be2257d848d6078d932cc1fd4e8226639f550344d0a7a2b8813", + "sha256:ee6ccb8197936a308a4034c90a42b30b37c46b7cbda66101d439d6983f59b368", + "sha256:eea9c37b45e73cebb4670afd1779db138eeff0f84ffc0871d2fb90c04c8d3aa8", + "sha256:f195bf641276261e6bc5f79f52601850c9bdbff8af401483b4805dbff535ed30", + "sha256:f264827618400ebeab16708c8acf7870f693b03bfb4d7e95253eb9b35074db5c", + "sha256:f44ccd2eaa433ff1a10f70242dc33315fc192b81664696154127bdd66ad7d3b2", + "sha256:f7a6068d8857c403e105e62132a00e9d9d401bd0efbff7f8b5b5bc8ab768a2d8", + "sha256:f9886176fe4bf1ac008c02adb5bd103f1191799f1897777d203ee44f615325a5", + "sha256:fa1f38d5583d283b40f998e2f13471bfa952e0c423ff95ec2ec329f3e1898107", + "sha256:fa65494e7bd0e3ba33b3e5a5ab30c2b6e95d3d1762baaa56151a0861618dc261", + "sha256:fd7186e23963714bab3c9a2ab75d002078335110d2c9fc883c65cbce43717f26", + "sha256:fec32c22b521fcdeb9aa7dee4373b2d81ca2d3fc8edc532f3e189d6f4f6f1f81" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.2" + }, + "wrapt": { + "hashes": [ + "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f", + "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c", + "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", + "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", + "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", + "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c", + "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", + "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", + "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8", + "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", + "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061", + "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", + "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb", + "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62", + "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984", + "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", + "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2", + "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", + "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7", + "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", + "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", + "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", + "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", + "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", + "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", + "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", + "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563", + "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a", + "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f", + "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", + "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9", + "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", + "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82", + "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9", + "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", + "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", + "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", + "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", + "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", + "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7", + "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", + "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", + "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", + "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a", + "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3", + "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a", + "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", + "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", + "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", + "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", + "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", + "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", + "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", + "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", + "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", + "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", + "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2", + "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22", + "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72", + "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061", + "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f", + "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9", + "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04", + "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", + "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9", + "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f", + "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", + "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", + "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", + "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", + "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", + "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", + "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", + "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6", + "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", + "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb", + "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119", + "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b", + "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.2" + } + } +} diff --git a/dbrepo-dashboard-service/init/app.py b/dbrepo-dashboard-service/init/app.py new file mode 100644 index 0000000000..4ef58f55a2 --- /dev/null +++ b/dbrepo-dashboard-service/init/app.py @@ -0,0 +1,66 @@ +import logging +import os +from logging.config import dictConfig +from typing import List + +from dbrepo.RestClient import RestClient +from dbrepo.api.dto import Database +from dbrepo.core.client.dashboard import DashboardServiceClient + +logging.addLevelName(level=logging.NOTSET, levelName='TRACE') +logging.basicConfig(level=logging.DEBUG) + +# logging configuration +dictConfig({ + 'version': 1, + 'formatters': { + 'default': { + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', + }, + 'simple': { + 'format': '[%(asctime)s] %(levelname)s: %(message)s', + }, + }, + 'handlers': {'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'simple' # default + }}, + 'root': { + 'level': 'DEBUG', + 'handlers': ['wsgi'] + } +}) + + +def dashboard_client(): + return DashboardServiceClient(os.getenv('DASHBOARD_UI_ENDPOINT', 'http://localhost:3000'), + os.getenv('SYSTEM_USERNAME', 'admin'), os.getenv('SYSTEM_PASSWORD', 'admin')) + + +def rest_client(): + return RestClient(endpoint=os.getenv("METADATA_SERVICE_ENDPOINT", "http://metadata-service:8080"), + username=os.getenv('SYSTEM_USERNAME', 'admin'), password=os.getenv('SYSTEM_PASSWORD', 'admin')) + + +def fetch_databases() -> List[Database]: + databases = [] + for index, database in enumerate(rest_client().get_databases()): + logging.debug(f"fetching database details for database id: {database.id}") + databases.append(rest_client().get_database(database_id=database.id)) + logging.info(f"Fetched {len(databases)} database(s)") + return databases + + +def upsert_dashboard(database: Database) -> None: + db = dashboard_client().find(database.dashboard_uid) + if db is None: + db = dashboard_client().create(database.internal_name, database.dashboard_uid) + rest_client().update_database_dashboard(database.id, database.dashboard_uid) + dashboard_client().update(db['uid']) + + +if __name__ == "__main__": + for database in fetch_databases(): + upsert_dashboard(database) + logging.info("Finished. Exiting.") diff --git a/dbrepo-dashboard-service/init/lib/dbrepo-1.8.0-py3-none-any.whl b/dbrepo-dashboard-service/init/lib/dbrepo-1.8.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..86bf040fdef558afb682d4aa0d41e2cbf4958787 GIT binary patch literal 88162 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≀rW;DlsxaORk-=Roq6-IYrZGs z&rY`d_Hf;N*A7+I<QUNzcf@8sdllI_vrJ*rg4#=&GQYX!s%_=}q4hK3ANzCX1iJ<I z4hn32_iys^@E1p9AFjAs75EapGS~Vgt{KC?zyO*bk-=S=hkLlX`f#83@I8Bx7c%p) zImqCO@q;4&v);O1Iw$ov1!?%{YU*m7Jbzv@?1I7e3(TjoiddgMpZ=ms>^0jIv8B&a z)FL&fh)i8p)T**9T2mxM>h-gy&zHVZdlp($$cWa&NQ`Ex<78l9U}s=pP{Hl0lKg`B zoYb<^9KDi?5^ql}FWnQ*nb3?n6Io%v%*Mc=$IHMVi`%FmS7-kqm#x>1&syvz!gk@W z4fmM|hYxYPxG5<Mn$@Uyc4$m$Sib#O+4h%`Tf^V#b{DVySG~H+<lUxiKM#g{pQihH zjoiNN+!x}NS=9eoM7m6zm;1SE&P8KY*|TkxTXc`F>U_OXOmI$7-{W65A3tSs$e8hK z+P~hF-xGiEe!iaU|6Hxk<kKgWlzrN_C*7J^Q6<Vh@!`g)lh=Kjm-arL$032E_VAiD z|7D%Cel6*Z)O?j)T=MSjrPf&+xw&3@C>7smJ2<a#xAMccg**+4lNP-&*W>wYC4Z=( zIZ@^K?6<v>%F0;U`eJq}tlMxiBP}fO;jCL)c?yfdt3~=4zC3fu{kJsC%0yai@|%UP zbEXttwLG>W^`VaILMO}Jy{VfgZ-~3#dCPwXb19<$)3J}bQ?GhXPP^N7`KMxCMDRWz zS+0X?kND21+^=s`nSQ-NM@jebu`hG{6||T&9BU6eQ^{`Mv+{SZ`GuOD557)~KJY+D z+uFh-@%&sr)l3czi9nyQ7svmWlq^dBqtcXnP%G;;e|PXzQMo5B!c(lawU?<~77<=L zt$xmi%+TzU>8}HHcvksUHZ-jGer3|K)BD!2)+ff_yj=bvIoUOo|JkPJ$`?1U`ptYY z;YeA&$RgE@oKEGPeSSd#6T;QbKM@f6-CKQ=|L8$(&%Wi47M89#f9aKv+<}6^zB19Y zH%D#mSVc@_n{wwXgKxdT<o$iuuIK%hH<oIDz3u!9gOnRH)dS;ID#hRB9!^(OlNb1{ zSD<mn{N%|=Ds0vw3|$XSXdCtZ%D&?gyQ}c0@Y1zmuOr!)MH@Qq`E2q!oGs_Ut|{L& zQYPO#^0MmcS<Z$9NAzd@WBwj_MfLX8IIm}~)ZG7^cyi{H?oyLo-)&l2m=4a|GyByw zi__B;oOf6=A2=`k!{};V#;zBWa&K^6R=6bfQe^(EdlnbETEe(yHy>sZ^b3A?`IOdY z8ym61ECw?i>{q<s{r^_k-_vfMlfK?QxNC`DsYB#xmx%kH3vO36{QFr`l9nmt^tw{% zXRuq$9wmVl^B;57KiZcy`}y3h$3Lq5Hm&c=T&boxN4BhXt4Q{Yc@H)};nuJY(tSG9 z{&?fRmb}GQ+U9FYIVKv2UAl0D>#*ir_q*r5Mkaq^d;USM;MeU(`VTa@g1_E0pY=n+ zHF#>}pRF(d`Kp~~ws!gY;o+4<$-x@0n>S9f+Z!&Lt60~{S{?AFMl_Z^rv32Tu%{`N zECy4K#Ba!qOD+Ashu2I;F8SV1K~=T7>3N~Mvo>2M$IV*S{4Oed-{GAuSCw}^+4FpL z@4_S8+fFU2d$X-rI-*U*NaV&9pTnKD*Wc$Q_pRg-yM8e!%SunNS2XkK(I<=&%5leT zg{%*<DEiGL6n;bPEL&Dpa=Z5CH3n-c?!Nc=x@VbHV^pK#BqinrCQOR!i(X7#aYrxQ zW6DdWdk+P3Pdt}iRbnf({P#XTuGI~ev;Af;&R<;k(Nu1M;EWnazUzDT<<z&8EuYMm z#aOyXtMZx5S??WlHuXv`oOonT@%2r%g`Y2MxbgYPqYK(aHGWsauFO@`ng061Dud~9 zayd0#H=PV*rwD)WF6nkI3v*2~a%MYV&{4JZWBvT*|H)bAzkV;-TYuZn-8f)l@w_#0 zC$HowxEMQp4@!K`l^=S&WYL7J3S8HN^*((r=lT8K%Rab@@6?pi`BSxnOQz4t+;qsr z;p-2^vp#$0Moq91(b><H$=+|w@k`vX((lLVXa9oq{O4~kwbNPO)yeNv^0A7ocxh$C z_RDow9WQ)c$Jbs|tDfQFWBz#G+A}eAV$Sg*uP=QLH)U_xAAEn|`^<a%332mh%cst> zxjpHtJ)hC(Y_tDuyJwZyw(mIVc5_Gh^y(e%FIQ$|GA`u%yzhQu+3gU1YX?37hQk_u zbzu%qW!sWvp8YNRIANuY)yu|<Pj_p7Gd}ph`q?a>&Ea1dHMx=vS1x+@UPAJK2G8#^ zrK<Dn_bklW%3&08ree~kRmCSt&u&S&Saaveu_oo4_a{o8o^j(|fI>r?y>k09-qSf% zcI=03_WYL>m>J_3Q`(>W>)L@66MHrbxkRsFGE~0Yv-N(X=eoDC^BL`U4?c>#`-tJe z?fC)Tj7%cTA`A=+91M4+R!6ZYxL9ssW?)F;W?%q`g66wHcu6COgdXGIm|IxjoRgWF z2imZQZUXNc-41zX1_pBubQ7L2!w-V+Ei5U)X~GkkjJKE785jzeGNQS`oE>gLP--!5 z6F_c-&C&~jI8eN#(MBI`LVP@Yc?Y^5K+0kI#XuY=UecI{(4Sb4sgK8uiR#;hWJDPl zw9^<E1flvt)RM*}sAi;;<m(kwqC4U3#oW2K7#J7|7#SEuLHeM0N#lDLxEDZ9NX<*m zPf0DpVnpt_#v=zA85s7kF)&C#wS%Z7jelHGjexIt!D7nnsqf2IvNA9n5J!*C&+aIu z<R%srV7Q~osRp#R1HR}+9OM8fUeb8Z7j6RhXb>F1X^LiuG}HhPwWN{N57iJ*px`j* z?u@#qs|8IWxr_`9zgQR;P~+ACi$R!?!<t+jHTmm@!=U9q$qbNI7RVtWyrl7=Kc-{g z>r{%-g4YtwUveNbpm<4RMgXc&$>1D^E6F*`tBv}3Hh8lp3j@Oz9>{)ns8I|{8kb== zE3vdB1I<lUku_0Am$ck!5@2Acih&GyA<SV9#p<S%#Nv#k{KTRZG{XX#>!JdRMADcA z7#QU385lrKZiHdSQn4CVoSImajP9(Qz?vxe9-(`xEDQ|J0_dU6T!!7GlKi5?bkHd? z$hpe^E!08Fco2?Cu0k~m?loKi|IDf;N_hL8RB<K-hVLxs0k#CEaf!*vsm16i;*(WP z)S5F(rZKQEFzn`GU{HcNjDdk+N#l<iTyBHA5-kEiiS_LKmA~1z85kU#7#L7fm_;Kl z^9mC4QghJE0<C)kIR{oSg1Q$VJ_s*qtm;8ED?c|UGYMCiZTF~+;^jUX@5{o#ATEgR ztnFBhO3u$KE=kNQK@T#JSu1?{X7@5NFtl)@o8>SOo3m12EAr612r{eJvFM8xI|GA@ zC3<@0oPy1)+|<P4(jxRk1~SQI9$Tz%J_AGKZ&n5cP$)t1lE&KE*i6dL#pg%#BbA_r zF)V33$Hj=}fF<Ol4~jzcLoX2Kln7!o2X+JovN<5%q3`HNm~&qQn>nDBhG@YJat=rv zEJcA<WP<o0yreNr8=EnR!W38H0-1`wJ`-dj2rp?|N61uo+JM`H#ntF*EJ0?2@RCL^ z9RjWfg+nsd6_>~%4Dy5=+QLYX1t7en@fR_cU|S}MZUx9VSm>jcgUfZX`2%fnBeHRz zxf1lnjUeMecuC_6xN!uRI-(njJ^=$V5QLXB&a{QO5yMc}bPT#-=mS6?gFtvmW11^Y z!@$Eq=q8~L+JH;}VNmM|r%5P7IOry#kKKSw1K}-=?ru0ugpA|_c(byBlxi?&FdXM* MU}*JWWME(b0It$gO#lD@ literal 0 HcmV?d00001 diff --git a/dbrepo-dashboard-service/init/lib/dbrepo-1.8.0.tar.gz b/dbrepo-dashboard-service/init/lib/dbrepo-1.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b0c21d94d641cdddaede16449367638abc78d5e8 GIT binary patch literal 97755 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±N%zn*Czgikg|`$Cvti@^D&j$nhspf5Y#( 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 A+W-In literal 0 HcmV?d00001 diff --git a/dbrepo-search-service/init/tests/rsa/rs256.key b/dbrepo-dashboard-service/init/tests/rsa/rs256.key similarity index 100% rename from dbrepo-search-service/init/tests/rsa/rs256.key rename to dbrepo-dashboard-service/init/tests/rsa/rs256.key diff --git a/dbrepo-search-service/init/tests/rsa/rsa256.pkey b/dbrepo-dashboard-service/init/tests/rsa/rsa256.pkey similarity index 100% rename from dbrepo-search-service/init/tests/rsa/rsa256.pkey rename to dbrepo-dashboard-service/init/tests/rsa/rsa256.pkey diff --git a/dbrepo-dashboard-service/init/tests/test_app.py b/dbrepo-dashboard-service/init/tests/test_app.py new file mode 100644 index 0000000000..60f3ec44cf --- /dev/null +++ b/dbrepo-dashboard-service/init/tests/test_app.py @@ -0,0 +1,100 @@ +import unittest + +import requests_mock +from dbrepo.api.dto import Database, Table, Constraints, Column, ColumnType, ConceptBrief, UnitBrief, \ + UserBrief, ContainerBrief, ImageBrief, DatabaseBrief +from dbrepo.api.exceptions import NotExistsError + +from app import fetch_databases + +req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", + name="Test", + internal_name="test_tuw1", + owner=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + contact=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + exchange_name="dbrepo", + is_public=True, + is_schema_public=True, + is_dashboard_enabled=True, + container=ContainerBrief(id="7efe8b27-6cdc-4387-80e3-92ee28f4a7c5", + name="MariaDB", + internal_name="mariadb", + image=ImageBrief(id="f97791b4-baf4-4b18-8f7d-3084818e6549", + name="mariadb", + version="11.1.3", + default=True)), + tables=[Table(id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", + database_id="209acf92-5c9b-4633-ad99-113c86f6e948", + name="Data", + internal_name="data", + owner=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + constraints=Constraints(uniques=[], foreign_keys=[], checks=[], primary_key=[]), + is_versioned=False, + queue_name="dbrepo", + routing_key="dbrepo.1.1", + is_public=True, + is_schema_public=True, + columns=[Column(id="7bef7e68-88f1-438e-9b94-0a77afd21471", + database_id="209acf92-5c9b-4633-ad99-113c86f6e948", + table_id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", + name="ID", + ord=0, + internal_name="id", + type=ColumnType.BIGINT, + is_null_allowed=False, + size=20, + d=0, + concept=ConceptBrief(id="fb32ecf6-1f68-49b4-85ee-04e76263cbef", + uri="http://www.wikidata.org/entity/Q2221906"), + unit=UnitBrief(id="a67d735e-32ef-4917-b412-fe099c6757a1", + uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), + val_min=0, + val_max=10)] + )]) + + +class AppUnitTest(unittest.TestCase): + + def test_fetch_databases_succeeds(self): + with requests_mock.Mocker() as mock: + # mock + mock.get('/api/database', + json=[DatabaseBrief(id='209acf92-5c9b-4633-ad99-113c86f6e948', + name="Test", + internal_name="test_tuw1", + owner_id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + is_public=True, + is_schema_public=True, + contact=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo")).model_dump()]) + mock.get(f'/api/database/{req.id}', json=req.model_dump()) + # test + response = fetch_databases() + self.assertEqual(1, len(response)) + + def test_fetch_databases_empty_succeeds(self): + with requests_mock.Mocker() as mock: + # mock + mock.get('/api/database', json=[]) + # test + response = fetch_databases() + self.assertEqual(0, len(response)) + + def test_fetch_databases_not_found_fails(self): + with requests_mock.Mocker() as mock: + # mock + mock.get('/api/database', + json=[DatabaseBrief(id='209acf92-5c9b-4633-ad99-113c86f6e948', + name="Test", + internal_name="test_tuw1", + owner_id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + is_public=True, + is_schema_public=True, + contact=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo")).model_dump()]) + mock.get(f'/api/database/{req.id}', status_code=404) + # test + try: + fetch_databases() + except NotExistsError: + pass \ No newline at end of file diff --git a/dbrepo-dashboard-service/lib/dbrepo-1.8.0-py3-none-any.whl b/dbrepo-dashboard-service/lib/dbrepo-1.8.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..86bf040fdef558afb682d4aa0d41e2cbf4958787 GIT binary patch literal 88162 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≀rW;DlsxaORk-=Roq6-IYrZGs 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 MU}*JWWME(b0It$gO#lD@ literal 0 HcmV?d00001 diff --git a/dbrepo-dashboard-service/lib/dbrepo-1.8.0.tar.gz b/dbrepo-dashboard-service/lib/dbrepo-1.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b0c21d94d641cdddaede16449367638abc78d5e8 GIT binary patch literal 97755 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±N%zn*Czgikg|`$Cvti@^D&j$nhspf5Y#( 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 A+W-In literal 0 HcmV?d00001 diff --git a/dbrepo-dashboard-service/panel.py b/dbrepo-dashboard-service/panel.py deleted file mode 100644 index acb3d548bb..0000000000 --- a/dbrepo-dashboard-service/panel.py +++ /dev/null @@ -1,252 +0,0 @@ -import os - -datasource_uid = os.getenv('JSON_DATASOURCE_NAME', 'dbrepojson0') - -statistics_row_title = '${view_id}' - - -def _get_start_index(dashboard: dict) -> int: - return [panel['title'] for panel in dashboard['panels']].index(statistics_row_title) - - -def get_panels(dashboard: dict) -> [dict]: - return [] - - -def map_timeseries_panel(database_id: str) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(title='${view_id}', - type='timeseries', - datasource=datasource, - targets=[dict(datasource=datasource, - format='table', - global_query_id='', - hide=False, - refId='A', - root_selector='', - source='url', - type='json', - url='/api/database/' + database_id + '/view/${view_id}/data', - url_options=dict(data='', - method='GET'))], - gridPos=dict(h=8, - w=12, - x=12, - y=8), - options=dict(legend=dict(displayMode='list', - placement='bottom', - showLegend=True), - tooltip=dict(mode='single', - sort='none')), - fieldConfig=dict( - defaults=dict(color=dict(mode='palette-classic'), - custom=dict( - axisBorderShow=False, - axisCenteredZero=False, - axisColorMode='text', - axisLabel='', - axisPlacement='auto', - barAlignment=0, - drawStyle='line', - fillOpacity=0, - gradientMode='none', - hideFrom=dict(legend=False, - tooltip=False, - viz=False), - insertNulls=False, - lineInterpolation='linear', - lineWidth=1, - pointSize=5, - scaleDistribution=dict(type='linear'), - showPoints='auto', - spanNulls=False, - stacking=dict(group='A', - mode='none'), - thresholdsStyle=dict(mode='absolute'))))) - - -def map_number_panel(database_id: str, title: str, root_selector: str, y: int = 0) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(title=title, - type='stat', - datasource=datasource, - targets=[dict(datasource=datasource, - columns=[], - filters=[], - format='table', - global_query_id='', - hide=False, - refId='A', - root_selector=root_selector, - source='url', - type='json', - url='/api/database/' + database_id + '/view/${view_id}/statistic', - url_options=dict(data='', - method='GET'))], - fieldConfig=dict(defaults=dict(mappings=[], - thresholds=dict(mode='absolute', - steps=[dict(color='blue', - value=None)]), - unit=''), - overrides=[]), - gridPos=dict(h=4, - w=6, - x=18, - y=y), - options=dict(colorMode='background', - graphMode='area', - justifyMode='auto', - orientation='auto', - reduceOptions=dict(calcs=[], - fields='/.*/', - values=True), - showPercentChange=False, - textMode='auto', - wideLayout=True)) - - -def map_statistics_panel(database_id: str) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(title='Statistics', - type='table', - gridPos=dict(h=8, - w=12, - x=0, - y=8), - datasource=datasource, - targets=[dict(datasource=datasource, - columns=[], - filters=[], - format='table', - global_query_id='', - hide=False, - refId='A', - root_selector='columns', - source='url', - type='json', - url='/api/database/' + database_id + '/view/${view_id}/statistic', - url_options=dict(data='', - method='GET'))], - options=dict(cellHeight="sm", - showHeader=True, - footer=dict(countRows=False, - fields="", - reducer=["sum"], - show=False)), - transformations=[dict(id="organize", - options=dict(excludeByName=dict(), - includeByName=dict(), - indexByName=dict(name=0, - val_min=1, - val_max=2, - mean=3, - median=4, - std_dev=5), - renameByName=dict(name="Name", - mean="Mean", - median="Median", - std_dev="std.dev", - val_min="Minimum", - val_max="Maximum")))], - fieldConfig=dict(defaults=dict(custom=dict(align="auto", - filterable="true", - cellOptions=dict(type="auto"), - inspect=False), - mappings=[], - thresholds=dict(mode="absolute", - steps=[dict(color="green", - value=None), - dict(color="red", - value=80) - ])), - overrides=[])) - - -def map_overview_panel(database_id: str) -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(title='Datasource Preview', - type='table', - gridPos=dict(h=8, - w=18, - x=0, - y=4), - fieldConfig=dict( - defaults=dict( - color=dict(mode='palette-classic'), - custom=dict(axisBorderShow=False, - axisCenteredZero=False, - axisColorMode='text', - axisLabel='', - axisPlacement='auto', - barAlignment=0, - drawStyle='line', - fillOpacity=0, - gradientMode='none', - hideFrom=dict( - legend=False, - tooltip=False, - viz=False), - insertNulls=False, - lineInterpolation='linear', - lineWidth=1, - pointSize=5, - scaleDistribution=dict( - type='linear'), - showPoints='auto', - spanNulls=False, - stacking=dict(group='A', - mode='none'), - thresholdsStyle=dict( - mode='off'))), - overrides=[]), - options=dict(legend=dict(displayMode='list', - placement='bottom', - showLegend=True, - calcs=[]), - tooltip=dict(mode='single', - sort='none')), - targets=[dict(format='json', - columns=[], - datasource=datasource, - filters=[], - global_query_id='', - refId='A', - root_selector='', - source='url', - type='json', - url='/api/database/' + database_id + '/view/${view_id}/data', - url_options=dict(data='', - method='GET'))], - datasource=datasource) - - -def map_row() -> dict: - datasource = dict(uid=datasource_uid, - type='yesoreyeram-infinity-datasource') - return dict(collapsed=False, - repeat='view_id', - repeatDirection='h', - title=statistics_row_title, - type='row', - panels=[], - targets=[dict(refId='A', - datasource=datasource)], - gridPos=dict(h=1, - w=24, - x=0, - y=0)) - - -def map_panels(dashboard: dict, database: Database) -> [dict]: - if get_statistics_row(dashboard) is None: - dashboard['panels'].append(map_row()) # repeating - dashboard['panels'].append(map_overview_panel(database.id)) # left top - dashboard['panels'].append(map_number_panel(database.id, 'Total Entries', 'rows', 0)) # right top - dashboard['panels'].append(map_number_panel(database.id, 'Variables', '$count(columns)', 4)) # right top - dashboard['panels'].append(map_statistics_panel(database.id)) # left - dashboard['panels'].append(map_timeseries_panel(database.id)) # middle - return dashboard['panels'] diff --git a/dbrepo-dashboard-service/test.sh b/dbrepo-dashboard-service/test.sh new file mode 100644 index 0000000000..40328cd5dd --- /dev/null +++ b/dbrepo-dashboard-service/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash +PIPENV_PIPFILE=./dbrepo-search-service/Pipfile +source ./dbrepo-search-service/venv/bin/activate +pip install pipenv +pipenv install gunicorn && pipenv install --dev --system --deploy +cd ./dbrepo-search-service/ && coverage run -m pytest test/test_app.py test/test_jwt.py test/test_opensearch_client.py test/test_keycloak_client.py --junitxml=report.xml && coverage html && coverage report > ./coverage.txt +cat ./coverage.txt | grep -o 'TOTAL[^%]*%' \ No newline at end of file diff --git a/dbrepo-dashboard-service/tests/conftest.py b/dbrepo-dashboard-service/tests/conftest.py new file mode 100644 index 0000000000..da1c56e9eb --- /dev/null +++ b/dbrepo-dashboard-service/tests/conftest.py @@ -0,0 +1,48 @@ +import logging +import os + +import pytest +from dbrepo.core.client.dashboard import DashboardServiceClient +from tests.grafana import GrafanaContainer + +logging.basicConfig(level=logging.DEBUG) + + +@pytest.fixture(scope="session") +def session(request): + """ + Create one Grafana container per test run only (admin:admin) + :param request: / + :return: The Grafana container + """ + logging.debug("[fixture] creating grafana container") + container = GrafanaContainer() + logging.debug("[fixture] starting grafana container") + container.start() + os.environ['DASHBOARD_UI_ENDPOINT'] = container.get_url() + os.environ['SYSTEM_USERNAME'] = 'admin' + os.environ['SYSTEM_PASSWORD'] = 'admin' + + # destructor + def stop_grafana(): + container.stop() + + request.addfinalizer(stop_grafana) + return container + + +@pytest.fixture(scope="function", autouse=True) +def cleanup(request, session): + """ + Clean up after each test by removing dashboards (=so it's empty again) + :param request: / + :param session: / + :return: + """ + dashboard_client = DashboardServiceClient(os.getenv('DASHBOARD_UI_ENDPOINT', 'http://localhost:3000'), + os.getenv('SYSTEM_USERNAME', 'admin'), + os.getenv('SYSTEM_PASSWORD', 'admin')) + logging.info("[fixture] clean dashboards") + for dashboard in dashboard_client.get_client().search.search_dashboards(): + dashboard_client.get_client().dashboard.delete_dashboard(dashboard['uid']) + logging.debug(f"[fixture] deleted dashboard {dashboard['uid']}") diff --git a/dbrepo-dashboard-service/tests/grafana/__init__.py b/dbrepo-dashboard-service/tests/grafana/__init__.py new file mode 100644 index 0000000000..46e29e9c76 --- /dev/null +++ b/dbrepo-dashboard-service/tests/grafana/__init__.py @@ -0,0 +1,28 @@ +import requests +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs, wait_container_is_ready + + +class GrafanaContainer(DockerContainer): + MGMT_PORT = 3000 + + def __init__(self, image: str = "bitnami/grafana:11", **kwargs) -> None: + super().__init__(image=image, **kwargs) + self.with_exposed_ports(self.MGMT_PORT) + + def get_url(self) -> str: + return f"http://{self.get_container_host_ip()}:{self.get_exposed_port(self.MGMT_PORT)}" + + @wait_container_is_ready(requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) + def _readiness_probe(self) -> None: + try: + response = requests.get(f"{self.get_url()}/api/health", timeout=1) + except requests.exceptions.ConnectionError: + response = requests.get(f"{self.get_url()}/healthz", timeout=1) + response.raise_for_status() + wait_for_logs(self, "HTTP Server Listen") + + def start(self) -> "GrafanaContainer": + super().start() + self._readiness_probe() + return self diff --git a/dbrepo-dashboard-service/tests/rsa/rs256.key b/dbrepo-dashboard-service/tests/rsa/rs256.key new file mode 100644 index 0000000000..86b3eaf5c6 --- /dev/null +++ b/dbrepo-dashboard-service/tests/rsa/rs256.key @@ -0,0 +1,3 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQABAoIBADNcMt6hAHub4JTAYS6Mra0EPRBO2XhWmACBrv3+8ETClXd5475KPLDewgRVtlmtbwU8G8awUXESQgPS9lfiqvQhPreA3cHlm6oP2WMKOEtakr2s8I+frsTBLCo0Ini9RaSzjoVVgS0zofyhASKi+T970MafSj5P3XNb8YBFdXgoYDiA7FXLH6a/+m7LScL+wGcFMAAeYESxZbMQLfH3v8L+4EcTraiwjLG17ZdlF3dpybMyUSse6ZQ/PdlyvBuzzLXhN6Ce2gd9ATfS+YWTzo7Yf+GU+ex5bIpVOfHqtuM/hyq7YGKENClsXwNZIAoFnvGCbvECAfgyapVrD30IfykCgYEA0rgsSZ82pxT40NxwgBD1g9lbNVBKXphRB/3S078qusUzJjT7AldEj4imGPhAbI7bI8gAeWJsp1XJWkjM8ktaVrh+NQl7p8e9OPh0pQF/5Bdg8ajbjXESpjnaU66pVYRQy/d+jNli/YRAHX5RUfsBl+6W4+WSVMGmKBiqJsur+ecCgYEAz1YVXClcmUnyZem5B+2E9noIzjF6ROE+jIb6rawM85P3Xd0lXtECQavtxw+Qk7I32qOwrxl1UpK2foVel3pazi+4OpMfmqtYGenRP1Zk1cZwrDo0cIemTDGjj3kJ8tYn12CGolFQpJZgK6OHzvG0tOxI5VZgjIViWNPe1PGWXtUCgYEAxXGNDe8BZs1f11S2lUlOw5yGug3hoYFXbAWJ5p7Ziuf8ZXB/QlJDC7se54a11wKEk6Jzz0lKRgE8CjzszJuOqnN0zn10QGIIC7nCklo1W6QMUmPGVWH994N976tZP6gbjQL6sT+AYcvpx7j0ubxYYeRNvnz+ACzzY964kGGHY0ECgYEAumlwPPNnMN7+VEjGNm2D7UMdJZ3wi3tkjF5ThdA5uMohTsAk+FG80KSu3RmOaGyEsUwY7+VYyYvlDm4E9PZqLBVVczyR3rMNPAcwPd0EPfvzk7WlLkOX7ct3fehaXH3VRlyfz9KCSeh1wOZ/lT1VtpD2nVOC7PSDzs92+kfXZZ0CgYAnrD1y4skgXkdwolZ3unn3EFyGm2d+X5aMTHwQPdWxqoNIAl/9wdghlzihwnPhhsxq1WzlxuC3V2IMrNPtRx70Mi+FbSmR5m4Xx5RptgMtMlwno+L40PzNJgMjHGjt0wcx3Vel8wuohDtnqMyS7P5nG1/TQx0Cyzwn7QOXlNpgbQ== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/dbrepo-dashboard-service/tests/rsa/rsa256.pkey b/dbrepo-dashboard-service/tests/rsa/rsa256.pkey new file mode 100644 index 0000000000..857dfb22be --- /dev/null +++ b/dbrepo-dashboard-service/tests/rsa/rsa256.pkey @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB +-----END PUBLIC KEY----- diff --git a/dbrepo-dashboard-service/tests/test_integration_app.py b/dbrepo-dashboard-service/tests/test_integration_app.py new file mode 100644 index 0000000000..de95ad5abd --- /dev/null +++ b/dbrepo-dashboard-service/tests/test_integration_app.py @@ -0,0 +1,208 @@ +import time +import unittest + +import jwt +from dbrepo.api.dto import Database, Table, Constraints, Column, ColumnType, ConceptBrief, UnitBrief, \ + UserBrief, ContainerBrief, ImageBrief + +from app import app + +req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", + name="Test", + internal_name="test_tuw1", + dashboard_uid="2432cf61e71dea", + owner=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + contact=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + exchange_name="dbrepo", + is_public=True, + is_schema_public=True, + is_dashboard_enabled=True, + container=ContainerBrief(id="7efe8b27-6cdc-4387-80e3-92ee28f4a7c5", + name="MariaDB", + internal_name="mariadb", + image=ImageBrief(id="f97791b4-baf4-4b18-8f7d-3084818e6549", + name="mariadb", + version="11.1.3", + default=True)), + tables=[Table(id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", + database_id="209acf92-5c9b-4633-ad99-113c86f6e948", + name="Data", + internal_name="data", + owner=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), + constraints=Constraints(uniques=[], foreign_keys=[], checks=[], primary_key=[]), + is_versioned=False, + queue_name="dbrepo", + routing_key="dbrepo.1.1", + is_public=True, + is_schema_public=True, + columns=[Column(id="7bef7e68-88f1-438e-9b94-0a77afd21471", + database_id="209acf92-5c9b-4633-ad99-113c86f6e948", + table_id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", + name="ID", + ord=0, + internal_name="id", + type=ColumnType.BIGINT, + is_null_allowed=False, + size=20, + d=0, + concept=ConceptBrief(id="fb32ecf6-1f68-49b4-85ee-04e76263cbef", + uri="http://www.wikidata.org/entity/Q2221906"), + unit=UnitBrief(id="a67d735e-32ef-4917-b412-fe099c6757a1", + uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), + val_min=0, + val_max=10)] + )]) + + +class AppIntegrationTest(unittest.TestCase): + + def token(self, roles: [str], iat: int = int(time.time())): + claims = { + 'iat': iat, + 'uid': 'c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502', + 'preferred_username': 'foo', + 'realm_access': { + 'roles': roles + } + } + with open('./tests/rsa/rs256.key', 'rb') as fh: + return jwt.JWT().encode(claims, jwt.jwk_from_pem(fh.read()), alg='RS256') + + def test_create_dashboard_fails(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard', + headers={'Authorization': f'Bearer {self.token(["system"])}'}) + self.assertEqual(415, response.status_code) + + def test_health_succeeds(self): + with app.test_client() as test_client: + # test + response = test_client.get('/health') + self.assertEqual(200, response.status_code) + + def test_create_dashboard_no_auth_fails(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard') + self.assertEqual(401, response.status_code) + + def test_create_dashboard_no_body_fails(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard', + headers={'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'}) + self.assertEqual(400, response.status_code) + + def test_create_dashboard_empty_body_fails(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard', + headers={'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'}, + json={}) + self.assertEqual(400, response.status_code) + + def test_create_dashboard_malformed_body_fails(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard', + headers={'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'}, + json=dict({'is_public': True})) + self.assertEqual(400, response.status_code) + + def test_create_dashboard_succeeds(self): + with app.test_client() as test_client: + # test + response = test_client.post('/api/dashboard', + headers={'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'}, + json=dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'})) + self.assertEqual(201, response.status_code) + + def test_update_dashboard_no_auth_fails(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + json_payload = dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'}) + # mock + response = test_client.post('/api/dashboard', headers=headers, json=json_payload) + # test + response = test_client.put(f"/api/dashboard/{response.json['uid']}") + self.assertEqual(401, response.status_code) + + def test_update_dashboard_no_body_fails(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + json_payload = dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'}) + # mock + response = test_client.post('/api/dashboard', headers=headers, json=json_payload) + # test + response = test_client.put(f"/api/dashboard/{response.json['uid']}", + headers=headers) + self.assertEqual(400, response.status_code) + + def test_update_dashboard_empty_body_fails(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + json_payload = dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'}) + # mock + response = test_client.post('/api/dashboard', headers=headers, json=json_payload) + # test + response = test_client.put(f"/api/dashboard/{response.json['uid']}", headers=headers, json={}) + self.assertEqual(400, response.status_code) + + def test_update_dashboard_malformed_body_fails(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + json_payload = dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'}) + # mock + response = test_client.post('/api/dashboard', headers=headers, json=json_payload) + # test + response = test_client.put(f"/api/dashboard/{response.json['uid']}", headers=headers, + json=dict({'is_public': True})) + self.assertEqual(400, response.status_code) + + def test_update_dashboard_succeeds(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + json_payload = dict({'is_public': True, + 'is_schema_public': True, + 'database_name': 'some_database', + 'owner_username': 'foobar'}) + # mock + response = test_client.post('/api/dashboard', headers=headers, json=json_payload) + req.dashboard_uid = response.json['uid'] + # test + response = test_client.put(f"/api/dashboard/{response.json['uid']}", headers=headers, + json=req.model_dump()) + self.assertEqual(202, response.status_code) + + def test_update_dashboard_not_found_fails(self): + with app.test_client() as test_client: + headers = {'Authorization': f'Bearer {self.token(["system"])}', + 'Content-Type': 'application/json'} + # test + response = test_client.put(f"/api/dashboard/idonotexist", headers=headers, json=req.model_dump()) + self.assertEqual(404, response.status_code) diff --git a/dbrepo-dashboard-ui/Dockerfile b/dbrepo-dashboard-ui/Dockerfile new file mode 100644 index 0000000000..07a30f99ab --- /dev/null +++ b/dbrepo-dashboard-ui/Dockerfile @@ -0,0 +1,9 @@ +FROM docker.io/bitnami/grafana:11 AS runtime +LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" + +WORKDIR /app + +COPY --chown=grafana:grafana ./dashboards /app/dashboards +COPY --chown=grafana:grafana ./provisioning /etc/grafana/provisioning +COPY --chown=grafana:grafana ./grafana.ini /etc/grafana/grafana.ini +COPY --chown=grafana:grafana ./ldap.toml /etc/grafana/ldap.toml diff --git a/dbrepo-dashboard-service/dashboards/system.json b/dbrepo-dashboard-ui/dashboards/System/dbrepo.json similarity index 96% rename from dbrepo-dashboard-service/dashboards/system.json rename to dbrepo-dashboard-ui/dashboards/System/dbrepo.json index e6f81bda40..6ce787d456 100644 --- a/dbrepo-dashboard-service/dashboards/system.json +++ b/dbrepo-dashboard-ui/dashboards/System/dbrepo.json @@ -30,7 +30,7 @@ "title": "Docs", "tooltip": "", "type": "link", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.6/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" } ], "panels": [ @@ -49,7 +49,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Quality of Service", "fieldConfig": { @@ -115,7 +115,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -135,7 +135,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -185,7 +185,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -206,7 +206,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -253,7 +253,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -274,7 +274,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -321,7 +321,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -337,7 +337,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -354,7 +354,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -389,7 +389,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -437,7 +437,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -457,7 +457,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Top 10 by number of accesses", "fieldConfig": { @@ -511,7 +511,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "editorMode": "code", "expr": "topk(10, dbrepo_datasource_data_get_total)", @@ -540,7 +540,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -602,7 +602,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -622,7 +622,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -684,7 +684,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -704,7 +704,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -754,7 +754,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -774,7 +774,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -824,7 +824,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -844,7 +844,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -895,7 +895,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -915,7 +915,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -978,7 +978,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -998,7 +998,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -1078,7 +1078,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -1111,7 +1111,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Quality of Service", "fieldConfig": { @@ -1176,7 +1176,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1196,7 +1196,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -1245,7 +1245,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1265,7 +1265,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -1314,7 +1314,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1334,7 +1334,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -1395,7 +1395,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1415,7 +1415,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Ready and unacknowledged messages stored in memory", "fieldConfig": { @@ -1476,7 +1476,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1496,7 +1496,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Messages delivered to consumers but not yet acknowledged", "fieldConfig": { @@ -1557,7 +1557,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1577,7 +1577,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Messages for received protocol messages", "fieldConfig": { @@ -1685,7 +1685,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1718,7 +1718,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -1798,7 +1798,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "code", @@ -1818,7 +1818,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -1889,7 +1889,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -1909,7 +1909,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -2046,7 +2046,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -2068,7 +2068,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Heap and non-heap memory summed", "fieldConfig": { @@ -2206,7 +2206,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "disableTextWrap": false, "editorMode": "builder", @@ -2227,7 +2227,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "Top 10 by frequency of access", "fieldConfig": { @@ -2282,7 +2282,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "editorMode": "code", "expr": "topk(10, rate(dbrepo_table_data_get_total[$__range]))", @@ -2298,7 +2298,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "fieldConfig": { "defaults": { @@ -2404,7 +2404,7 @@ { "datasource": { "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "editorMode": "code", "expr": "rate(flask_http_request_duration_seconds_count{status!~\"200|201|202\"}[$__rate_interval])", @@ -2421,8 +2421,14 @@ "refresh": "1m", "schemaVersion": 39, "tags": [ - "provisioned", - "dbrepo" + "ui", + "dashboard", + "metadata", + "data", + "gateway", + "analyse", + "metrics", + "auth" ], "templating": { "list": [] @@ -2433,7 +2439,7 @@ }, "timepicker": {}, "timezone": "browser", - "title": "DBRepo - Overview", + "title": "DBRepo", "uid": "bdz20owu8zn5se", "version": 8, "weekStart": "" diff --git a/dbrepo-dashboard-service/dashboards/rabbitmq.json b/dbrepo-dashboard-ui/dashboards/System/rabbitmq.json similarity index 99% rename from dbrepo-dashboard-service/dashboards/rabbitmq.json rename to dbrepo-dashboard-ui/dashboards/System/rabbitmq.json index a8db65695f..6958b05e83 100644 --- a/dbrepo-dashboard-service/dashboards/rabbitmq.json +++ b/dbrepo-dashboard-ui/dashboards/System/rabbitmq.json @@ -41,7 +41,7 @@ "datasource": { "default": true, "type": "prometheus", - "uid": "P18F45E9DC7E75912" + "uid": "dbrepometrics0" }, "description": "", "fieldConfig": { @@ -8056,7 +8056,7 @@ "refresh": "15s", "schemaVersion": 34, "style": "dark", - "tags": ["provisioned", "rabbitmq"], + "tags": ["rabbitmq", "amqp", "mqtt"], "templating": { "list": [ { @@ -8157,7 +8157,7 @@ ] }, "timezone": "", - "title": "RabbitMQ - Overview", + "title": "Broker Service", "uid": "Kn5xm-gZk", "version": 20220805, "weekStart": "", diff --git a/dbrepo-dashboard-service/grafana.ini b/dbrepo-dashboard-ui/grafana.ini similarity index 89% rename from dbrepo-dashboard-service/grafana.ini rename to dbrepo-dashboard-ui/grafana.ini index 1f8d9c1ef3..7b7d22ccb5 100644 --- a/dbrepo-dashboard-service/grafana.ini +++ b/dbrepo-dashboard-ui/grafana.ini @@ -1,7 +1,6 @@ [server] protocol = http domain = localhost -root_url = http://%(domain)s/dashboard/ http_port = 3000 [security] diff --git a/dbrepo-dashboard-service/ldap.toml b/dbrepo-dashboard-ui/ldap.toml similarity index 92% rename from dbrepo-dashboard-service/ldap.toml rename to dbrepo-dashboard-ui/ldap.toml index 4523531361..c6ca55f79d 100644 --- a/dbrepo-dashboard-service/ldap.toml +++ b/dbrepo-dashboard-ui/ldap.toml @@ -12,7 +12,7 @@ timeout = 10 # User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" # Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))" -search_filter = "(cn=%s)" +search_filter = "(uid=%s)" # An array of base dns to search through search_base_dns = ["${LDAP_ROOT}"] @@ -22,11 +22,11 @@ group_search_filter = "(&(objectClass=groupOfNames)(member=cn=%s,ou=users,${LDAP group_search_filter_user_attribute = "uid" [servers.attributes] -name = "givenName" +name = "cn" surname = "sn" -username = "cn" +username = "uid" member_of = "member" -email = "email" +email = "mail" [[servers.group_mappings]] group_dn = "cn=${LDAP_ADMIN_USERNAME},ou=users,${LDAP_ROOT}" diff --git a/dbrepo-dashboard-ui/provisioning/dashboards/provider.yaml b/dbrepo-dashboard-ui/provisioning/dashboards/provider.yaml new file mode 100644 index 0000000000..a11a2c20b4 --- /dev/null +++ b/dbrepo-dashboard-ui/provisioning/dashboards/provider.yaml @@ -0,0 +1,20 @@ +apiVersion: 1 + +providers: + # <string> an unique provider name. Required + - name: 'dbrepo' + # <int> Org id. Default to 1 + orgId: 1 + # <string> provider type. Default to 'file' + type: file + # <bool> disable dashboard deletion + disableDeletion: false + # <int> how often Grafana will scan for changed dashboards + updateIntervalSeconds: 10 + # <bool> allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # <string, required> path to dashboard files on disk. Required when using the 'file' type + path: /app/dashboards + # <bool> use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: true \ No newline at end of file diff --git a/dbrepo-dashboard-ui/provisioning/datasources/infinity.yaml b/dbrepo-dashboard-ui/provisioning/datasources/infinity.yaml new file mode 100644 index 0000000000..ce1409240e --- /dev/null +++ b/dbrepo-dashboard-ui/provisioning/datasources/infinity.yaml @@ -0,0 +1,17 @@ +apiVersion: 1 + +datasources: + - name: dbrepo-json + uid: dbrepojson0 + type: yesoreyeram-infinity-datasource + basicAuth: true + basicAuthUser: user + url: http://localhost + jsonData: + auth_method: 'basicAuth' + httpHeaderName1: Accept + allowedHosts: + - 'http://localhost' + secureJsonData: + basicAuthPassword: user + httpHeaderValue1: application/json diff --git a/dbrepo-dashboard-ui/provisioning/datasources/prometheus.yaml b/dbrepo-dashboard-ui/provisioning/datasources/prometheus.yaml new file mode 100644 index 0000000000..493954f181 --- /dev/null +++ b/dbrepo-dashboard-ui/provisioning/datasources/prometheus.yaml @@ -0,0 +1,7 @@ +apiVersion: 1 + +datasources: + - name: dbrepo-metrics + type: prometheus + uid: dbrepometrics0 + url: http://metric-db:9090 diff --git a/dbrepo-data-service/Dockerfile b/dbrepo-data-service/Dockerfile index 9edf1375fb..7468f1c568 100644 --- a/dbrepo-data-service/Dockerfile +++ b/dbrepo-data-service/Dockerfile @@ -1,5 +1,5 @@ ###### FIRST STAGE ###### -FROM dbrepo-metadata-service:build AS dependency +FROM dbrepo-core:build AS dependency LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" ###### SECOND STAGE ###### @@ -10,7 +10,7 @@ COPY ./pom.xml ./ RUN mvn -fn dependency:go-offline -COPY --from=dependency /root/.m2/repository/at/tuwien /root/.m2/repository/at/tuwien +COPY --from=dependency /root/.m2/repository/at/ac/tuwien/ifs/dbrepo /root/.m2/repository/at/ac/tuwien/ifs/dbrepo COPY ./querystore ./querystore COPY ./report ./report @@ -28,7 +28,7 @@ RUN apk add --no-cache curl bash jq WORKDIR /app -RUN adduser -S -u 1001 data-service +RUN adduser -D dbrepo --uid 1001 USER 1001 diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 338d6a5d73..bd2a9027b5 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -16,7 +16,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> <name>dbrepo-data-service</name> - <version>1.7.3</version> + <version>1.8.0</version> <description>Service that manages the data</description> @@ -28,7 +28,7 @@ <module>report</module> </modules> - <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/</url> + <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/</url> <developers> <developer> <name>Martin Weise</name> @@ -94,39 +94,13 @@ <dependencies> <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-validation</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-security</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.security</groupId> - <artifactId>spring-security-test</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.springframework.cloud</groupId> - <artifactId>spring-cloud-starter-bootstrap</artifactId> - <version>${spring-cloud.version}</version> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - <version>${guava.version}</version> + <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- Spark --> <dependency> @@ -166,13 +140,12 @@ <artifactId>hadoop-aws</artifactId> <version>${hadoop.version}</version> </dependency> - <!-- Open API --> + <!-- Data Source --> <dependency> - <groupId>org.springdoc</groupId> - <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> - <version>${springdoc-openapi.version}</version> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>${mariadb.version}</version> </dependency> - <!-- Data Source --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> @@ -203,12 +176,6 @@ <version>${micrometer.version}</version> <scope>test</scope> </dependency> - <!-- IDE --> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <scope>compile</scope> - </dependency> <!-- Mapping --> <dependency> <groupId>org.mapstruct</groupId> @@ -221,11 +188,6 @@ <artifactId>mapstruct</artifactId> <version>${mapstruct.version}</version> </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-jsr310</artifactId> - <version>${jackson-datatype.version}</version> - </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> @@ -252,29 +214,12 @@ <artifactId>keycloak-admin-client</artifactId> <version>${keycloak.version}</version> </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-hibernate6</artifactId> - <version>${jackson-datatype.version}</version> - </dependency> <!-- Authentication --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>${jwt.version}</version> </dependency> - <!-- DTOs --> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-api</artifactId> - <version>${project.version}</version> - </dependency> - <!-- Exceptions --> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-repositories</artifactId> - <version>${project.version}</version> - </dependency> <!-- AMPQ --> <dependency> <groupId>org.springframework.amqp</groupId> @@ -293,19 +238,8 @@ </dependency> <!-- Testing --> <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-test</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> @@ -378,7 +312,8 @@ <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>@{argLine} -ea -Xmx4g -Xss4m -XX:MaxMetaspaceSize=2g + -XX:ReservedCodeCacheSize=${CodeCacheSize} ${extraJavaTestArgs} </argLine> </configuration> diff --git a/dbrepo-data-service/querystore/pom.xml b/dbrepo-data-service/querystore/pom.xml index 2410a8e9fe..2e2c7d2674 100644 --- a/dbrepo-data-service/querystore/pom.xml +++ b/dbrepo-data-service/querystore/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-data-service-querystore</artifactId> <name>dbrepo-data-service-querystore</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies/> diff --git a/dbrepo-data-service/report/pom.xml b/dbrepo-data-service/report/pom.xml index b2dab3ebd0..22839d6f4e 100644 --- a/dbrepo-data-service/report/pom.xml +++ b/dbrepo-data-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>report</artifactId> <name>dbrepo-data-service-report</name> - <version>1.7.3</version> + <version>1.8.0</version> <description> This module is only intended for the pipeline coverage report. See the detailed report in the respective modules diff --git a/dbrepo-data-service/rest-service/pom.xml b/dbrepo-data-service/rest-service/pom.xml index c0f90e3cd6..a8590a762d 100644 --- a/dbrepo-data-service/rest-service/pom.xml +++ b/dbrepo-data-service/rest-service/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>rest-service</artifactId> <name>dbrepo-data-service-rest-service</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>services</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </dependency> </dependencies> 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 ba1a0e76da..91f3e4410b 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 @@ -1,10 +1,10 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.CreateAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.CacheService; import io.swagger.v3.oas.annotations.Operation; 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 752aa83196..bf6bbc4879 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 @@ -1,12 +1,12 @@ package at.tuwien.endpoints; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AccessService; import at.tuwien.service.CacheService; @@ -94,6 +94,7 @@ public class DatabaseEndpoint extends RestEndpoint { final DatabaseDto database = containerService.createDatabase(container, data); containerService.createQueryStore(container, data.getInternalName()); accessService.create(database, metadataMapper.createDatabaseDtoToPrivilegedUserDto(data), AccessTypeDto.WRITE_ALL); + accessService.create(database, metadataMapper.createDatabaseDtoToReadonlyUserDto(data), AccessTypeDto.READ); return ResponseEntity.status(HttpStatus.CREATED) .body(database); } catch (SQLException e) { diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/RestEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/RestEndpoint.java index 45cea4371c..a9edad9674 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/RestEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/RestEndpoint.java @@ -1,6 +1,6 @@ package at.tuwien.endpoints; -import at.tuwien.api.user.UserDetailsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDetailsDto; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.springframework.security.core.Authentication; 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 fb076ce3a2..fcc9d3cdec 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,14 +1,14 @@ package at.tuwien.endpoints; -import at.tuwien.ExportResourceDto; -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.QueryPersistDto; -import at.tuwien.api.database.query.SubsetDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryPersistDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.CacheService; 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 8e1fef5bac..e801ce2a45 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 @@ -1,14 +1,14 @@ package at.tuwien.endpoints; -import at.tuwien.ExportResourceDto; -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.columns.ColumnDto; -import at.tuwien.api.database.table.internal.TableCreateDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.*; @@ -297,7 +297,7 @@ public class TableEndpoint extends RestEndpoint { final HttpHeaders headers = new HttpHeaders(); if (request.getMethod().equals("HEAD")) { headers.set("Access-Control-Expose-Headers", "X-Count"); - headers.set("X-Count", "" + tableService.getCount(database, table, timestamp)); + headers.set("X-Count", "" + tableService.getCount(database, table.getInternalName(), timestamp)); return ResponseEntity.ok() .headers(headers) .build(); @@ -701,8 +701,9 @@ public class TableEndpoint extends RestEndpoint { MetadataServiceException, TableMalformedException, DatabaseNotFoundException { log.debug("endpoint generate table statistic, databaseId={}, tableId={}", databaseId, tableId); final DatabaseDto database = cacheService.getDatabase(databaseId); + final TableDto table = cacheService.getTable(databaseId, tableId); try { - return ResponseEntity.ok(tableService.getStatistics(database, cacheService.getTable(databaseId, tableId))); + return ResponseEntity.ok(tableService.getStatistics(database, table.getInternalName())); } 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/UploadEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/UploadEndpoint.java index 9d338e42bf..41982ebc36 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/UploadEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/UploadEndpoint.java @@ -1,9 +1,9 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.file.UploadResponseDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.file.UploadResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.service.StorageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; 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 add04964d0..245ca0ca26 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 @@ -1,12 +1,13 @@ 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.error.ApiErrorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.*; import at.tuwien.validation.EndpointValidator; @@ -48,6 +49,7 @@ public class ViewEndpoint extends RestEndpoint { private final DSLContext context; private final ViewService viewService; private final CacheService cacheService; + private final TableService tableService; private final MariaDbMapper mariaDbMapper; private final SubsetService subsetService; private final StorageService storageService; @@ -56,12 +58,13 @@ public class ViewEndpoint extends RestEndpoint { @Autowired public ViewEndpoint(DSLContext context, ViewService viewService, CacheService cacheService, - MariaDbMapper mariaDbMapper, SubsetService subsetService, + TableService tableService, MariaDbMapper mariaDbMapper, SubsetService subsetService, StorageService storageService, DatabaseService databaseService, EndpointValidator endpointValidator) { this.context = context; this.viewService = viewService; this.cacheService = cacheService; + this.tableService = tableService; this.mariaDbMapper = mariaDbMapper; this.subsetService = subsetService; this.storageService = storageService; @@ -339,4 +342,47 @@ public class ViewEndpoint extends RestEndpoint { } } + @GetMapping("/{viewId}/statistic") + @Observed(name = "dbrepo_view_statistic") + @Operation(summary = "Get view statistic", + description = "Gets basic statistical properties (min, max, mean, median, std.dev) of numerical columns of a view with id.", + hidden = true) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Generated view statistic", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = TableStatisticDto.class))}), + @ApiResponse(responseCode = "400", + description = "Failed to obtain column statistic", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find view or database in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<TableStatisticDto> statistic(@NotNull @PathVariable("databaseId") UUID databaseId, + @NotNull @PathVariable("viewId") UUID viewId) + throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, + MetadataServiceException, TableMalformedException, DatabaseNotFoundException, ViewNotFoundException, + QueryMalformedException { + log.debug("endpoint generate view statistic, databaseId={}, viewId={}", databaseId, viewId); + final DatabaseDto database = cacheService.getDatabase(databaseId); + final ViewDto view = cacheService.getView(databaseId, viewId); + try { + return ResponseEntity.ok(cacheService.getStatistic(database, view)); + } 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/handlers/ApiExceptionHandler.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index 0926b1cf02..8485d507c5 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 @@ -1,7 +1,7 @@ package at.tuwien.handlers; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import io.swagger.v3.oas.annotations.Hidden; import lombok.extern.log4j.Log4j2; import org.springframework.http.HttpHeaders; @@ -115,6 +115,20 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(DashboardServiceException.class) + public ResponseEntity<ApiErrorDto> handle(DashboardServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.BAD_GATEWAY) + @ExceptionHandler(DashboardServiceConnectionException.class) + public ResponseEntity<ApiErrorDto> handle(DashboardServiceConnectionException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(DatabaseMalformedException.class) 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 655741cc23..5f8b39704b 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 @@ -1,13 +1,13 @@ 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.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.FilterDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.FilterTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; import at.tuwien.endpoints.RestEndpoint; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.service.CacheService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-data-service/rest-service/src/main/resources/application.yml b/dbrepo-data-service/rest-service/src/main/resources/application.yml index 53c0858bbd..f008cde99b 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml @@ -17,6 +17,10 @@ spring: time_zone: UTC application: name: data-service + servlet: + multipart: + max-file-size: "${MAX_UPLOAD_SIZE:2GB}" + max-request-size: "${MAX_UPLOAD_SIZE:2GB}" rabbitmq: host: "${BROKER_HOST:broker-service}" virtual-host: "${BROKER_VIRTUALHOST:dbrepo}" @@ -41,6 +45,8 @@ management: enabled: true server: port: 8080 + tomcat: + max-swallow-size: -1 logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -68,14 +74,11 @@ dbrepo: password: "${AUTH_SERVICE_ADMIN_PASSWORD:admin}" client: "${AUTH_SERVICE_CLIENT:dbrepo-client}" clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}" - sql: - forbidden: "${NOT_SUPPORTED_KEYWORDS: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,--}" grant: default: read: "${GRANT_DEFAULT_READ:SELECT}" write: "${GRANT_DEFAULT_WRITE:SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" - website: "${BASE_URL:http://localhost}" - credentialCacheTimeout: "${CREDENTIAL_CACHE_TIMEOUT:60}" + credentialCacheTimeout: "${CREDENTIAL_CACHE_TIMEOUT:300}" minConcurrent: "${MIN_CONCURRENT_CONSUMERS:2}" maxConcurrent: "${MAX_CONCURRENT_CONSUMERS:6}" requeueRejected: ${REQUEUE_REJECTED:false} 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 e03ea299a2..f0b3bb8784 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 @@ -1,8 +1,8 @@ package at.tuwien.config; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; import lombok.extern.log4j.Log4j2; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbContainerConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbContainerConfig.java index 7aa18e3b9e..2d0e156117 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbContainerConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbContainerConfig.java @@ -1,7 +1,8 @@ package at.tuwien.config; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import lombok.extern.log4j.Log4j2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.testcontainers.containers.MariaDBContainer; @@ -10,8 +11,9 @@ import org.testcontainers.images.PullPolicy; /** * This class configures the MariaDB container for the integration tests. */ +@Log4j2 @Configuration -public class MariaDbContainerConfig extends AbstractUnitTest { +public class MariaDbContainerConfig extends BaseTest { public static CustomMariaDBContainer getContainer() { return CustomMariaDBContainer.getInstance(); @@ -36,7 +38,7 @@ public class MariaDbContainerConfig extends AbstractUnitTest { if (instance == null) { instance = new CustomMariaDBContainer(MARIADB_IMAGE); instance.withImagePullPolicy(PullPolicy.alwaysPull()); - instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT); + instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, IMAGE_1_DEFAULT_PORT); instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME); instance.withPassword(BaseTest.CONTAINER_1_PRIVILEGED_PASSWORD); instance.withInitScript("init/users.sql"); 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 d41e0609ba..36579a1954 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 @@ -1,15 +1,14 @@ package at.tuwien.endpoint; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.tuwien.endpoints.AccessEndpoint; -import at.tuwien.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.CacheService; -import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -28,7 +27,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class AccessEndpointUnitTest extends AbstractUnitTest { +public class AccessEndpointUnitTest extends BaseTest { @Autowired private AccessEndpoint accessEndpoint; @@ -39,11 +38,6 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @MockBean private AccessService accessService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseUnavailableException, 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 e2a6c550d0..7c318d10ae 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 @@ -1,17 +1,16 @@ package at.tuwien.endpoint; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.tuwien.endpoints.DatabaseEndpoint; -import at.tuwien.exception.*; import at.tuwien.service.AccessService; -import at.tuwien.service.ContainerService; import at.tuwien.service.CacheService; +import at.tuwien.service.ContainerService; import at.tuwien.service.DatabaseService; -import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +32,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class DatabaseEndpointUnitTest extends AbstractUnitTest { +public class DatabaseEndpointUnitTest extends BaseTest { @Autowired private DatabaseEndpoint databaseEndpoint; @@ -50,11 +49,6 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @MockBean private CacheService credentialService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseUnavailableException, RemoteUnavailableException, @@ -68,7 +62,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doNothing() .when(containerService) - .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNALNAME); + .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNAL_NAME); doNothing() .when(accessService) .create(eq(DATABASE_1_PRIVILEGED_DTO), any(UserDto.class), any(AccessTypeDto.class)); @@ -90,7 +84,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doNothing() .when(containerService) - .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNALNAME); + .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNAL_NAME); doNothing() .when(accessService) .create(eq(DATABASE_1_PRIVILEGED_DTO), any(UserDto.class), any(AccessTypeDto.class)); @@ -148,7 +142,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(QueryStoreCreateException.class) .when(containerService) - .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNALNAME); + .createQueryStore(CONTAINER_1_DTO, DATABASE_1_INTERNAL_NAME); /* test */ assertThrows(ContainerNotFoundException.class, () -> { 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 92bead3674..7c21fa5ebf 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,23 +1,22 @@ package at.tuwien.endpoint; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.database.query.QueryPersistDto; -import at.tuwien.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryPersistDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.tuwien.endpoints.SubsetEndpoint; -import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.StorageService; import at.tuwien.service.SubsetService; -import at.tuwien.test.AbstractUnitTest; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SparkSession; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -36,13 +35,13 @@ import java.util.List; import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class SubsetEndpointUnitTest extends AbstractUnitTest { +public class SubsetEndpointUnitTest extends BaseTest { @Autowired private SubsetEndpoint subsetEndpoint; @@ -68,11 +67,6 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @MockBean private MetadataServiceGateway metadataServiceGateway; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void list_publicDataPrivateSchemaAnonymous_succeeds() throws QueryNotFoundException, 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 3a5a62731b..528c9c16ed 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 @@ -1,24 +1,24 @@ package at.tuwien.endpoint; -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.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.tuwien.endpoints.TableEndpoint; -import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.SubsetService; import at.tuwien.service.TableService; -import at.tuwien.test.AbstractUnitTest; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SparkSession; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -27,7 +27,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; @@ -47,7 +46,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class TableEndpointUnitTest extends AbstractUnitTest { +public class TableEndpointUnitTest extends BaseTest { @Autowired private TableEndpoint tableEndpoint; @@ -83,17 +82,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { public static Stream<Arguments> anyAccess_parameters() { return Stream.of( - Arguments.arguments("read", DATABASE_1_USER_2_READ_ACCESS_DTO), - Arguments.arguments("write_own", DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO), - Arguments.arguments("write_all", DATABASE_1_USER_2_WRITE_ALL_ACCESS_DTO) + Arguments.arguments("read", AccessTypeDto.READ), + Arguments.arguments("write_own", AccessTypeDto.WRITE_OWN), + Arguments.arguments("write_all", AccessTypeDto.WRITE_ALL) ); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseUnavailableException, TableMalformedException, ViewNotFoundException, @@ -177,7 +171,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(TABLE_8_DTO); when(credentialService.getDatabase(DATABASE_3_ID)) .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(tableService.getStatistics(any(DatabaseDto.class), any(TableDto.class))) + when(tableService.getStatistics(any(DatabaseDto.class), anyString())) .thenReturn(TABLE_8_STATISTIC_DTO); /* test */ @@ -197,7 +191,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .getStatistics(any(DatabaseDto.class), any(TableDto.class)); + .getStatistics(any(DatabaseDto.class), anyString()); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -322,7 +316,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .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))) + when(tableService.getCount(any(DatabaseDto.class), anyString(), any(Instant.class))) .thenReturn(3L); when(subsetService.getData(eq(DATABASE_2_DTO), anyString())) .thenReturn(mock); @@ -432,7 +426,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @WithMockUser(username = USER_2_USERNAME) @MethodSource("anyAccess_parameters") - public void getData_private_succeeds(String name, DatabaseAccessDto access) throws DatabaseUnavailableException, + public void getData_private_succeeds(String name, AccessTypeDto type) throws DatabaseUnavailableException, TableNotFoundException, QueryMalformedException, RemoteUnavailableException, PaginationException, MetadataServiceException, NotAllowedException, DatabaseNotFoundException, StorageUnavailableException, FormatNotAvailableException { final Dataset<Row> mock = sparkSession.emptyDataFrame(); @@ -443,7 +437,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) - .thenReturn(access); + .thenReturn(DatabaseAccessDto.builder() + .user(USER_2_BRIEF_DTO) + .huserid(USER_2_ID) + .hdbid(DATABASE_1_ID) + .type(type) + .build()); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); when(httpServletRequest.getMethod()) @@ -1345,7 +1344,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @WithMockUser(username = USER_2_USERNAME) @MethodSource("anyAccess_parameters") - public void getData_privateDataPrivateSchemaTextCsv_succeeds(String name, DatabaseAccessDto access) + public void getData_privateDataPrivateSchemaTextCsv_succeeds(String name, AccessTypeDto type) throws TableNotFoundException, NotAllowedException, StorageUnavailableException, QueryMalformedException, RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, DatabaseUnavailableException, FormatNotAvailableException, PaginationException { @@ -1357,7 +1356,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) - .thenReturn(access); + .thenReturn(DatabaseAccessDto.builder() + .user(USER_2_BRIEF_DTO) + .huserid(USER_2_ID) + .hdbid(DATABASE_1_ID) + .type(type) + .build()); when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) 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 5ce2990700..dfed71fbbb 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 @@ -1,20 +1,19 @@ package at.tuwien.endpoint; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.tuwien.endpoints.ViewEndpoint; -import at.tuwien.exception.*; import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.SubsetService; import at.tuwien.service.ViewService; -import at.tuwien.test.AbstractUnitTest; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SparkSession; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +36,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class ViewEndpointUnitTest extends AbstractUnitTest { +public class ViewEndpointUnitTest extends BaseTest { @MockBean private ViewService viewService; @@ -60,11 +59,6 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Autowired private SparkSession sparkSession; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java index b87793a8bc..c41b8c326c 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java @@ -1,12 +1,10 @@ package at.tuwien.gateway; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -22,17 +20,12 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class InterceptorUnitTest extends AbstractUnitTest { +public class InterceptorUnitTest extends BaseTest { @MockBean @Qualifier("keycloakRestTemplate") private RestTemplate restTemplate; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void intercept_succeeds() { 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 1ea87d2fc1..8052efff55 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 @@ -1,16 +1,15 @@ package at.tuwien.gateway; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +33,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { +public class MetadataServiceGatewayUnitTest extends BaseTest { @MockBean @Qualifier("internalRestTemplate") @@ -43,11 +42,6 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { @Autowired private MetadataServiceGateway metadataServiceGateway; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void getTableById_succeeds() throws TableNotFoundException, RemoteUnavailableException, MetadataServiceException { @@ -130,7 +124,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Port", "" + CONTAINER_1_PORT); headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Jdbc-Method", IMAGE_1_JDBC); + headers.set("X-Jdbc-Method", IMAGE_1_JDBC_METHOD); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method X-Host X-Port"); /* mock */ @@ -232,7 +226,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Port", "" + CONTAINER_1_PORT); headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Jdbc-Method", IMAGE_1_JDBC); + headers.set("X-Jdbc-Method", IMAGE_1_JDBC_METHOD); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method X-Host X-Port"); /* mock */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java index 7dcb0343ac..063234a012 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java @@ -1,8 +1,8 @@ package at.tuwien.handlers; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -21,15 +21,15 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import static at.tuwien.test.utils.EndpointUtils.getErrorCodes; -import static at.tuwien.test.utils.EndpointUtils.getExceptions; +import static at.ac.tuwien.ifs.dbrepo.core.test.utils.EndpointUtils.getErrorCodes; +import static at.ac.tuwien.ifs.dbrepo.core.test.utils.EndpointUtils.getExceptions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest -public class ApiExceptionHandlerTest extends AbstractUnitTest { +public class ApiExceptionHandlerTest extends BaseTest { @Autowired private ApiExceptionHandler apiExceptionHandler; 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 bf63189bf2..8400a37cb9 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 @@ -1,16 +1,15 @@ package at.tuwien.listener; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MetadataServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.RemoteUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; 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.CacheService; -import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.amqp.core.Message; @@ -31,7 +30,6 @@ import java.util.HashMap; import static at.tuwien.utils.RabbitMqUtils.buildMessage; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @Log4j2 @@ -40,7 +38,7 @@ import static org.mockito.Mockito.when; @Testcontainers @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -public class DefaultListenerIntegrationTest extends AbstractUnitTest { +public class DefaultListenerIntegrationTest extends BaseTest { @MockBean private CacheService credentialService; @@ -56,7 +54,6 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* database */ MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); @@ -78,20 +75,4 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { assertTrue(output.getAll().contains("successfully inserted tuple")); } - @Test - @Disabled - public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, MetadataServiceException { - 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 */ - doThrow(TableNotFoundException.class) - .when(credentialService) - .getTable(DATABASE_1_ID, TABLE_1_ID); - - /* test */ - defaultListener.onMessage(request); - assertTrue(output.getAll().contains("Failed to insert tuple")); - } - } 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 686a134dc5..ebff4c3fd9 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 @@ -1,13 +1,13 @@ package at.tuwien.listener; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MetadataServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.RemoteUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; 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.CacheService; -import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,7 +36,7 @@ import static org.mockito.Mockito.when; @SpringBootTest @ExtendWith({SpringExtension.class, OutputCaptureExtension.class}) @Testcontainers -public class DefaultListenerUnitTest extends AbstractUnitTest { +public class DefaultListenerUnitTest { @MockBean private CacheService credentialService; @@ -50,13 +50,12 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Container private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); - @BeforeEach - public void beforeEach() throws SQLException { - genesis(); - /* metadata database */ - MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); - MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); - } +// @BeforeEach +// public void beforeEach() throws SQLException { +// /* metadata database */ +// MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); +// MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); +// } @Test public void onMessage_routingKeyDatabaseAndTableMissing_fails(CapturedOutput output) { @@ -76,35 +75,35 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { assertTrue(output.getAll().contains("Failed to map database and table")); } - @Test - public void onMessage_messageMalformed_fails(CapturedOutput output) throws TableNotFoundException, - 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_DTO); - when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); - - /* test */ - defaultListener.onMessage(request); - assertTrue(output.getAll().contains("Failed to read object")); - } - - @Test - public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, MetadataServiceException { - final Message request = buildMessage(TABLE_1_ROUTING_KEY, "{\"id\": 1}", new HashMap<>()); - - /* mock */ - doThrow(TableNotFoundException.class) - .when(credentialService) - .getTable(DATABASE_1_ID, TABLE_1_ID); - - /* test */ - defaultListener.onMessage(request); - assertTrue(output.getAll().contains("Failed to find table")); - } +// @Test +// public void onMessage_messageMalformed_fails(CapturedOutput output) throws TableNotFoundException, +// 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_DTO); +// when(credentialService.getDatabase(DATABASE_1_ID)) +// .thenReturn(DATABASE_1_PRIVILEGED_DTO); +// +// /* test */ +// defaultListener.onMessage(request); +// assertTrue(output.getAll().contains("Failed to read object")); +// } +// +// @Test +// public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, +// RemoteUnavailableException, MetadataServiceException { +// final Message request = buildMessage(TABLE_1_ROUTING_KEY, "{\"id\": 1}", new HashMap<>()); +// +// /* mock */ +// doThrow(TableNotFoundException.class) +// .when(credentialService) +// .getTable(DATABASE_1_ID, TABLE_1_ID); +// +// /* test */ +// defaultListener.onMessage(request); +// assertTrue(output.getAll().contains("Failed to find table")); +// } } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mapper/MariaDbMapperUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mapper/MariaDbMapperUnitTest.java index a1a3ef4dad..ffd7a9cdcc 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mapper/MariaDbMapperUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mapper/MariaDbMapperUnitTest.java @@ -1,6 +1,6 @@ package at.tuwien.mapper; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -12,12 +12,12 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.stream.Stream; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class MariaDbMapperUnitTest extends AbstractUnitTest { +public class MariaDbMapperUnitTest extends BaseTest { @Autowired private MariaDbMapper mariaDbMapper; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java index a7a83a6184..50f371a9a8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java @@ -1,6 +1,6 @@ package at.tuwien.mvc; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,7 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @SpringBootTest @AutoConfigureObservability -public class ActuatorEndpointMvcTest extends AbstractUnitTest { +public class ActuatorEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java index b5ed475ea8..a2ef7f201c 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java @@ -1,8 +1,8 @@ package at.tuwien.mvc; -import at.tuwien.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; import at.tuwien.endpoints.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -30,7 +30,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc @SpringBootTest -public class OpenApiEndpointMvcTest extends AbstractUnitTest { +public class OpenApiEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; @@ -68,6 +68,7 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { } private void generic_openApiDocs(Class<?> endpoint) { + final String packageScope = "at.ac.tuwien.ifs.dbrepo"; final List<Method> methods = Arrays.stream(endpoint.getMethods()) .filter(m -> m.getDeclaringClass().equals(endpoint)) .toList(); @@ -76,9 +77,9 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { final List<Class<?>> exceptions = Arrays.stream(m.getExceptionTypes()) .toList(); final List<Class<?>> invalidExceptions = exceptions.stream() - .filter(e -> !e.getName().startsWith("at.tuwien.")) + .filter(e -> !e.getName().startsWith(packageScope)) .toList(); - assertTrue(invalidExceptions.isEmpty(), "method '" + m.getName() + "' throws exception(s) outside package scope at.tuwien: " + invalidExceptions.stream().map(Class::getName).toList()); + assertTrue(invalidExceptions.isEmpty(), "method '" + m.getName() + "' throws exception(s) outside package scope " + packageScope + ": " + invalidExceptions.stream().map(Class::getName).toList()); exceptions.forEach(exception -> { final int status = exception.getAnnotation(ResponseStatus.class) .code() 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 de1c875e0a..164aa99c06 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 @@ -1,16 +1,16 @@ package at.tuwien.mvc; -import at.tuwien.api.database.query.ImportDto; -import at.tuwien.api.database.query.QueryPersistDto; -import at.tuwien.api.database.table.TupleDeleteDto; -import at.tuwien.api.database.table.TupleDto; -import at.tuwien.api.database.table.TupleUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryPersistDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleDeleteDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleUpdateDto; import at.tuwien.config.MetricsConfig; import at.tuwien.endpoints.SubsetEndpoint; import at.tuwien.endpoints.TableEndpoint; import at.tuwien.endpoints.ViewEndpoint; import at.tuwien.listener.DefaultListener; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import io.micrometer.observation.tck.TestObservationRegistry; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; @@ -42,7 +42,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest @Import(MetricsConfig.class) @AutoConfigureObservability -public class PrometheusEndpointMvcTest extends AbstractUnitTest { +public class PrometheusEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java index f3f0cb9799..1371d58bb3 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java @@ -2,7 +2,7 @@ package at.tuwien.mvc; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.SubsetService; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,7 +25,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @SpringBootTest @AutoConfigureObservability -public class SubsetEndpointMvcTest extends AbstractUnitTest { +public class SubsetEndpointMvcTest extends BaseTest { @MockBean private MetadataServiceGateway metadataServiceGateway; 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 abcfd4a175..55eacd882c 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 @@ -1,10 +1,10 @@ package at.tuwien.service; -import at.tuwien.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class AccessServiceIntegrationTest extends AbstractUnitTest { +public class AccessServiceIntegrationTest extends BaseTest { @Autowired private AccessService accessService; @@ -42,9 +42,8 @@ public class AccessServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java index ef4f8713c8..d495fac306 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java @@ -1,11 +1,11 @@ package at.tuwien.service; -import at.tuwien.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.exception.QueryStoreCreateException; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryStoreCreateException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class ContainerServiceIntegrationTest extends AbstractUnitTest { +public class ContainerServiceIntegrationTest extends BaseTest { @Autowired private ContainerService containerService; @@ -43,10 +43,9 @@ public class ContainerServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException, InterruptedException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); + MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); Thread.sleep(1000) /* wait for test container some more */; } @@ -54,12 +53,12 @@ public class ContainerServiceIntegrationTest extends AbstractUnitTest { public void create_succeeds() throws SQLException, DatabaseMalformedException { /* mock */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); /* test */ final DatabaseDto response = containerService.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_CREATE_INTERNAL); assertNull(response.getName()); - assertEquals(DATABASE_1_INTERNALNAME, response.getInternalName()); + assertEquals(DATABASE_1_INTERNAL_NAME, response.getInternalName()); assertEquals(EXCHANGE_DBREPO_NAME, response.getExchangeName()); assertNotNull(response.getOwner()); assertEquals(USER_1_ID, response.getOwner().getId()); @@ -82,7 +81,7 @@ public class ContainerServiceIntegrationTest extends AbstractUnitTest { public void createQueryStore_succeeds() throws SQLException, QueryStoreCreateException { /* test */ - createQueryStore_generic(DATABASE_1_INTERNALNAME); + createQueryStore_generic(DATABASE_1_INTERNAL_NAME); } protected void createQueryStore_generic(String databaseName) throws SQLException, QueryStoreCreateException { 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 95121ad704..994d011360 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 @@ -1,15 +1,15 @@ package at.tuwien.service; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.CacheServiceImpl; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,7 +27,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class CredentialServiceUnitTest extends AbstractUnitTest { +public class CredentialServiceUnitTest extends BaseTest { @Autowired private CacheServiceImpl credentialService; @@ -37,7 +37,6 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* cache */ credentialService.invalidateAll(); } 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 40fdb982ab..cccba468ff 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 @@ -1,25 +1,25 @@ package at.tuwien.service; -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.*; -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; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; -import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.database.table.internal.TableCreateDto; -import at.tuwien.api.identifier.IdentifierDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.ConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.CreateForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyReferenceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ReferenceTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary.PrimaryKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -45,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class DatabaseServiceIntegrationTest extends AbstractUnitTest { +public class DatabaseServiceIntegrationTest extends BaseTest { @Autowired private DatabaseService databaseService; @@ -60,11 +60,10 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException, InterruptedException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_2_PRIVILEGED_DTO); Thread.sleep(1000) /* wait for test container some more */; } @@ -113,9 +112,9 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { MariaDbConfig.grantWriteAccess(DATABASE_1_PRIVILEGED_DTO, USER_1_USERNAME); /* pre-condition */ - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_1_PASSWORD); + MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNAL_NAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_1_PASSWORD); try { - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); + MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNAL_NAME, "CREATE SEQUENCE debug NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); fail(); } catch (SQLException e) { /* ignore */ @@ -123,7 +122,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { /* test */ databaseService.update(DATABASE_1_PRIVILEGED_DTO, request); - MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNALNAME, "CREATE SEQUENCE debug2 NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); + MariaDbConfig.mockQuery(CONTAINER_1_HOST, CONTAINER_1_PORT, DATABASE_1_INTERNAL_NAME, "CREATE SEQUENCE debug2 NOCACHE", USER_1_USERNAME, USER_2_PASSWORD); } @Test @@ -189,7 +188,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { assertTrue(response.getIsVersioned()); assertEquals(DATABASE_2_PUBLIC, response.getIsPublic()); assertNotNull(response.getOwner()); - assertEquals(DATABASE_2_OWNER, response.getOwner().getId()); + assertEquals(USER_2_ID, response.getOwner().getId()); assertEquals(USER_2_NAME, response.getOwner().getName()); assertEquals(USER_2_USERNAME, response.getOwner().getUsername()); assertEquals(USER_2_FIRSTNAME, response.getOwner().getFirstname()); @@ -307,8 +306,8 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { assertNotNull(fk0.getOnDelete()); assertNotNull(fk0.getOnUpdate()); assertNotNull(fk0.getReferencedTable()); - assertEquals(TABLE_2_INTERNALNAME, fk0.getReferencedTable().getName()); - assertEquals(TABLE_2_INTERNALNAME, fk0.getReferencedTable().getInternalName()); + assertEquals(TABLE_2_INTERNAL_NAME, fk0.getReferencedTable().getName()); + assertEquals(TABLE_2_INTERNAL_NAME, fk0.getReferencedTable().getInternalName()); } @Test @@ -600,8 +599,8 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { /* test */ final TableDto response = databaseService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO); - assertEquals(TABLE_4_INTERNALNAME, response.getName()); - assertEquals(TABLE_4_INTERNALNAME, response.getInternalName()); + assertEquals(TABLE_4_INTERNAL_NAME, response.getName()); + assertEquals(TABLE_4_INTERNAL_NAME, response.getInternalName()); final List<ColumnDto> columns = response.getColumns(); assertEquals(TABLE_4_COLUMNS.size(), columns.size()); assertColumn(columns.get(0), null, null, DATABASE_1_ID, "timestamp", "timestamp", ColumnTypeDto.TIMESTAMP, null, null, false, null); @@ -616,7 +615,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { @Test public void createTable_malformed_fails() { - final at.tuwien.api.database.table.internal.TableCreateDto request = TableCreateDto.builder() + final at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto request = TableCreateDto.builder() .name("missing_foreign_key") .columns(List.of()) .constraints(CreateTableConstraintsDto.builder() @@ -637,7 +636,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { @Test public void createTable_compositePrimaryKey_fails() throws TableNotFoundException, TableMalformedException, SQLException, TableExistsException { - final at.tuwien.api.database.table.internal.TableCreateDto request = TableCreateDto.builder() + final at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto request = TableCreateDto.builder() .name("composite_primary_key") .columns(List.of(CreateTableColumnDto.builder() .name("name") 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 6996ecb9f4..190614876b 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,13 +2,13 @@ package at.tuwien.service; 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.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MetadataServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.RemoteUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.QueueServiceRabbitMqImpl; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -32,7 +32,7 @@ import static org.mockito.Mockito.when; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class QueueServiceIntegrationTest extends AbstractUnitTest { +public class QueueServiceIntegrationTest extends BaseTest { @Autowired private QueueServiceRabbitMqImpl queueService; @@ -50,9 +50,8 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java index 4344c9abb3..dd563deb70 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java @@ -1,12 +1,12 @@ package at.tuwien.service; -import at.tuwien.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; import at.tuwien.config.S3Config; -import at.tuwien.exception.MalformedException; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; -import at.tuwien.exception.TableMalformedException; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; import org.apache.spark.sql.Dataset; @@ -48,7 +48,7 @@ import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class StorageServiceIntegrationTest extends AbstractUnitTest { +public class StorageServiceIntegrationTest extends BaseTest { @Autowired private StorageService storageService; @@ -84,7 +84,6 @@ public class StorageServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* 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/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index d05979af36..a3b0561bcc 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 @@ -1,12 +1,12 @@ package at.tuwien.service; -import at.tuwien.api.database.query.*; -import at.tuwien.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.*; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; @@ -39,7 +39,7 @@ import static org.mockito.Mockito.when; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class SubsetServiceIntegrationTest extends AbstractUnitTest { +public class SubsetServiceIntegrationTest extends BaseTest { @Autowired private SubsetService subsetService; @@ -60,9 +60,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } 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 77e91361db..b46ed8d484 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 @@ -1,13 +1,13 @@ package at.tuwien.service; -import at.tuwien.api.database.query.ImportDto; -import at.tuwien.api.database.table.*; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnStatisticDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.config.S3Config; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import com.google.common.io.Files; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeAll; @@ -45,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class TableServiceIntegrationTest extends AbstractUnitTest { +public class TableServiceIntegrationTest extends BaseTest { @Autowired private TableService tableService; @@ -74,11 +74,10 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* metadata database */ - 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.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNAL_NAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_3_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); MariaDbConfig.createInitDatabase(DATABASE_3_PRIVILEGED_DTO); /* s3 */ @@ -307,24 +306,28 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getStatistics_succeeds() throws TableMalformedException, SQLException, TableNotFoundException { /* test */ - final TableStatisticDto response = tableService.getStatistics(DATABASE_1_PRIVILEGED_DTO, TABLE_2_DTO); + final TableStatisticDto response = tableService.getStatistics(DATABASE_1_PRIVILEGED_DTO, TABLE_2_INTERNAL_NAME); assertEquals(TABLE_2_COLUMNS.size(), response.getColumns().size()); - log.trace("response rows: {}", response.getRows()); - assertEquals(3L, response.getRows()); - assertEquals(Set.of("location", "lat", "lng"), response.getColumns().keySet()); - final ColumnStatisticDto column0 = response.getColumns().get("location"); + assertEquals(TABLE_2_COLUMNS.size(), response.getTotalColumns()); + log.trace("response rows: {}", response.getTotalRows()); + assertEquals(3L, response.getTotalRows()); + assertEquals(List.of("location", "lat", "lng"), response.getColumns().stream().map(ColumnStatisticDto::getName).toList()); + final ColumnStatisticDto column0 = response.getColumns().get(0); + assertEquals("location", column0.getName()); assertNull(column0.getMin()); assertNull(column0.getMax()); assertNull(column0.getMean()); assertNull(column0.getMedian()); assertNull(column0.getStdDev()); - final ColumnStatisticDto column3 = response.getColumns().get("lat"); + final ColumnStatisticDto column3 = response.getColumns().get(3); + assertEquals("lat", column0.getName()); assertEquals(BigDecimal.valueOf(-36.0653583), column3.getMin()); assertEquals(BigDecimal.valueOf(-33.847927), column3.getMax()); assertNotNull(column3.getMean()); assertNotNull(column3.getMedian()); assertNotNull(column3.getStdDev()); - final ColumnStatisticDto column4 = response.getColumns().get("lng"); + final ColumnStatisticDto column4 = response.getColumns().get(4); + assertEquals("lng", column0.getName()); assertEquals(BigDecimal.valueOf(146.9112214), column4.getMin()); assertEquals(BigDecimal.valueOf(150.6517942), column4.getMax()); assertNotNull(column4.getMean()); @@ -343,7 +346,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void delete_notFound_fails() throws SQLException { /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); + MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNAL_NAME); /* test */ assertThrows(QueryMalformedException.class, () -> { @@ -355,7 +358,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getCount_succeeds() throws SQLException, QueryMalformedException { /* test */ - final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, null); + final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNAL_NAME, null); assertEquals(3, response); } @@ -363,7 +366,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getCount_timestamp_succeeds() throws SQLException, QueryMalformedException { /* test */ - final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, Instant.ofEpochSecond(0)); + final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNAL_NAME, Instant.ofEpochSecond(0)); assertEquals(0, response); } @@ -371,11 +374,11 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getCount_notFound_fails() throws SQLException { /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); + MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNAL_NAME); /* test */ assertThrows(QueryMalformedException.class, () -> { - tableService.getCount(DATABASE_2_PRIVILEGED_DTO, TABLE_5_DTO, null); + tableService.getCount(DATABASE_2_PRIVILEGED_DTO, TABLE_5_INTERNAL_NAME, null); }); } @@ -395,7 +398,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void history_notFound_fails() throws SQLException { /* mock */ - MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); + MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNAL_NAME); /* test */ assertThrows(TableNotFoundException.class, () -> { 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 5e99f4afbc..7f5180e4ab 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 @@ -2,8 +2,8 @@ package at.tuwien.service; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.ViewMalformedException; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.ViewMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ import java.sql.SQLException; @SpringBootTest @ExtendWith(SpringExtension.class) @Testcontainers -public class ViewServiceIntegrationTest extends AbstractUnitTest { +public class ViewServiceIntegrationTest extends BaseTest { @Autowired private ViewService viewService; @@ -31,9 +31,8 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java index 6ed73e8a01..6a7a08cf26 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/MariaDbUtilTest.java @@ -1,6 +1,6 @@ package at.tuwien.utils; -import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; import org.junit.jupiter.api.Test; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java index d833d3fc1a..0f865a3929 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java @@ -1,7 +1,7 @@ package at.tuwien.validation; -import at.tuwien.exception.PaginationException; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.exception.PaginationException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -18,7 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @AutoConfigureMockMvc @SpringBootTest @AutoConfigureObservability -public class EndpointValidatorUnitTest extends AbstractUnitTest { +public class EndpointValidatorUnitTest extends BaseTest { @Autowired private EndpointValidator endpointValidator; diff --git a/dbrepo-data-service/services/pom.xml b/dbrepo-data-service/services/pom.xml index b02ce620c7..27d773f4d2 100644 --- a/dbrepo-data-service/services/pom.xml +++ b/dbrepo-data-service/services/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>services</artifactId> <name>dbrepo-data-service-services</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service-querystore</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </dependency> </dependencies> 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 1e9d1c4bf0..81590fbe4d 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 @@ -1,7 +1,7 @@ package at.tuwien.auth; -import at.tuwien.api.auth.RealmAccessDto; -import at.tuwien.api.user.UserDetailsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.RealmAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDetailsDto; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.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 7af0e8cab0..047469e772 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,6 +1,6 @@ package at.tuwien.auth; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; import at.tuwien.service.CredentialService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +28,7 @@ public class BasicAuthenticationProvider implements AuthenticationManager { public Authentication authenticate(Authentication auth) throws AuthenticationException { final TokenDto tokenDto = credentialService.getAccessToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); + log.debug("set basic auth principal username: {}", userDetails.getUsername()); 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 5ba81ea4b3..e5549a35b1 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 @@ -1,6 +1,6 @@ package at.tuwien.auth; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; import at.tuwien.config.GatewayConfig; import at.tuwien.service.CredentialService; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/CacheConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/CacheConfig.java index 603491c970..2466f40a2b 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/CacheConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/CacheConfig.java @@ -1,12 +1,13 @@ package at.tuwien.config; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.beans.factory.annotation.Value; @@ -52,6 +53,11 @@ public class CacheConfig { return new ExpiryCache<UUID, ContainerDto>().build(); } + @Bean + public Cache<UUID, TableStatisticDto> statisticCache() { + return new ExpiryCache<UUID, TableStatisticDto>().build(); + } + @Bean public Cache<String, TokenDto> tokenCache() { return new ExpiryCache<String, TokenDto>().build(); 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 21fbf674db..5b23d7c367 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 @@ -1,10 +1,10 @@ package at.tuwien.gateway; -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 at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.AccountNotSetupException; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.CredentialsInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.NotAllowedException; import org.springframework.security.authentication.BadCredentialsException; public interface KeycloakGateway { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java index 38b28ebcac..7d5571da9a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java @@ -1,18 +1,18 @@ package at.tuwien.gateway; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.UUID; - +// todo ? public interface MetadataServiceGateway { /** 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 1e14a4b4ce..d0f874cb9c 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 @@ -1,6 +1,6 @@ package at.tuwien.gateway.impl; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; import at.tuwien.config.KeycloakConfig; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.mapper.MetadataMapper; 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 ab0ab9dea5..959ad34e5d 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 @@ -1,14 +1,14 @@ package at.tuwien.gateway.impl; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.MetadataMapper; import jakarta.validation.constraints.NotNull; @@ -157,7 +157,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { ViewNotFoundException, MetadataServiceException { final ResponseEntity<ViewDto> response; final String url = "/api/database/" + databaseId + "/view/" + id; - log.debug("get view info from metadata service: {}", url); + log.debug("get view info from metadata service: {}", url); try { response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ViewDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { @@ -185,7 +185,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { MetadataServiceException { final ResponseEntity<UserDto> response; final String url = "/api/user/" + userId; - log.debug("get user info from metadata service: {}", url); + log.debug("get user info from metadata service: {}", url); try { response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { 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 929ede0a8f..aad70d3f37 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,11 +1,11 @@ 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.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MetadataServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.RemoteUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; import at.tuwien.service.CacheService; import at.tuwien.service.QueueService; import com.fasterxml.jackson.core.type.TypeReference; 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 9692b48b9e..904d867643 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 @@ -1,26 +1,24 @@ package at.tuwien.mapper; -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.table.*; -import at.tuwien.api.database.table.columns.*; -import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyBriefDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; -import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.exception.TableNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.ConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyReferenceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ReferenceTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary.PrimaryKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; import org.apache.hadoop.shaded.com.google.common.hash.Hashing; import org.apache.hadoop.shaded.org.apache.commons.io.FileUtils; import org.jetbrains.annotations.NotNull; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import java.io.File; import java.io.IOException; @@ -104,17 +102,19 @@ public interface DataMapper { default TableStatisticDto resultSetToTableStatistic(ResultSet data) throws SQLException { final TableStatisticDto statistic = TableStatisticDto.builder() - .columns(new LinkedHashMap<>()) + .columns(new LinkedList<>()) .build(); while (data.next()) { final ColumnStatisticDto columnStatistic = ColumnStatisticDto.builder() + .name(data.getString(1)) .min(data.getBigDecimal(2)) .max(data.getBigDecimal(3)) .median(data.getBigDecimal(4)) .mean(data.getBigDecimal(5)) .stdDev(data.getBigDecimal(6)) .build(); - statistic.getColumns().put(data.getString(1), columnStatistic); + statistic.getColumns() + .add(columnStatistic); } return statistic; } 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 a080dfb163..4861a7a1d7 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,22 +1,22 @@ 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.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; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.exception.QueryMalformedException; -import at.tuwien.exception.TableMalformedException; -import at.tuwien.exception.TableNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.OperatorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.FilterDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.FilterTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.OrderDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleDeleteDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TupleUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableNotFoundException; import at.tuwien.utils.MariaDbUtil; import org.jooq.Record; import org.jooq.*; @@ -317,7 +317,7 @@ public interface MariaDbMapper { } default String tableCreateDtoToCreateTableRawQuery(String databaseName, - at.tuwien.api.database.table.internal.TableCreateDto data) { + at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto data) { final StringBuilder stringBuilder = new StringBuilder("CREATE TABLE `") .append(databaseName) .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 8539b00432..ff979bd088 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 @@ -1,21 +1,20 @@ package at.tuwien.mapper; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.image.ImageDto; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewColumnDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.database.query.QueryDto; -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 at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; import org.keycloak.representations.AccessTokenResponse; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -37,6 +36,12 @@ public interface MetadataMapper { }) UserDto createDatabaseDtoToPrivilegedUserDto(CreateDatabaseDto data); + @Mappings({ + @Mapping(target = "username", source = "readonlyUsername"), + @Mapping(target = "password", source = "readonlyPassword"), + }) + UserDto createDatabaseDtoToReadonlyUserDto(CreateDatabaseDto data); + DatabaseBriefDto databaseDtoToDatabaseBriefDto(DatabaseDto data); ColumnDto viewColumnDtoToColumnDto(ViewColumnDto data); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java index c42fc28101..71899fc081 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/AccessService.java @@ -1,9 +1,9 @@ package at.tuwien.service; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; import java.sql.SQLException; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java index 208d6e755e..9424af16c2 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java @@ -1,18 +1,30 @@ package at.tuwien.service; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import java.sql.SQLException; import java.util.UUID; public interface CacheService { + /** + * Gets credentials for a database with given id either from the cache (if not expired) or retrieves them from the + * Metadata Service. + * + * @param id The id. + * @param forceReload If set to true, force a reload of the cached result. Otherwise, use the cached result if it is present. + * @return The credentials. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws RemoteUnavailableException The remote service is not available. + * @throws MetadataServiceException The remote service returned invalid data. + */ DatabaseDto getDatabase(UUID id, Boolean forceReload) throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException; @@ -29,6 +41,9 @@ public interface CacheService { DatabaseDto getDatabase(UUID id) throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException; + TableStatisticDto getStatistic(DatabaseDto database, ViewDto view) throws TableNotFoundException, + TableMalformedException, QueryMalformedException, SQLException; + /** * Gets credentials for a container with given id either from the cache (if not expired) or retrieves them from the * Metadata Service. diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ContainerService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ContainerService.java index 4f9e92ed78..f788a06eeb 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ContainerService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ContainerService.java @@ -1,10 +1,10 @@ package at.tuwien.service; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.exception.QueryStoreCreateException; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryStoreCreateException; import java.sql.SQLException; 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 b1c28cf170..bb9765c810 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 @@ -1,6 +1,6 @@ package at.tuwien.service; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; public interface CredentialService { 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 8f07b6bfb2..a12c8e0d4d 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,11 +1,11 @@ package at.tuwien.service; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.internal.TableCreateDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import java.sql.SQLException; import java.util.List; 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 1e8ba52923..e35f4029bb 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,7 +1,7 @@ package at.tuwien.service; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; import java.sql.SQLException; import java.util.Map; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/StorageService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/StorageService.java index 7ba3f93e71..65896d53e3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/StorageService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/StorageService.java @@ -1,10 +1,10 @@ package at.tuwien.service; -import at.tuwien.ExportResourceDto; -import at.tuwien.exception.MalformedException; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; -import at.tuwien.exception.TableMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; 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 30d4baca5c..30f6c2604f 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 @@ -1,9 +1,9 @@ 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 at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; 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 bb2b53432c..7ecc58bef8 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,9 +1,9 @@ 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.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import java.sql.SQLException; import java.time.Instant; @@ -14,14 +14,14 @@ public interface TableService { /** * Generate table statistic for a given table. Only numerical columns are calculated. * - * @param table The table. + * @param tableName The table name. * @return The table statistic, if successful. * @throws SQLException Failed to parse SQL query, contains invalid syntax. * @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(DatabaseDto database, TableDto table) throws SQLException, TableMalformedException, - TableNotFoundException; + TableStatisticDto getStatistics(DatabaseDto database, String tableName) throws SQLException, + TableMalformedException, TableNotFoundException; /** * Updating table description. @@ -58,13 +58,13 @@ public interface TableService { /** * Obtains the table data tuples count at time. * - * @param table The table object. + * @param tableName The table name. * @param timestamp The timestamp. * @return Number of tuples, if successful. * @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(DatabaseDto database, TableDto table, Instant timestamp) throws SQLException, + Long getCount(DatabaseDto database, String tableName, Instant timestamp) throws SQLException, QueryMalformedException; /** 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 7f64f72ebe..7fb1f0bdf8 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,9 +1,9 @@ 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; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ViewMalformedException; import java.sql.SQLException; import java.time.Instant; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java index be049663b7..fee072d633 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java @@ -1,9 +1,9 @@ package at.tuwien.service.impl; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.AccessService; import com.mchange.v2.c3p0.ComboPooledDataSource; @@ -66,8 +66,8 @@ public class AccessServiceMariaDbImpl extends DataConnector implements AccessSer } finally { dataSource.close(); } - log.info("Created access to database with internal name {} for user with id {}", database.getInternalName(), - user.getId()); + log.info("Created access to database with internal name {} for user: {}", database.getInternalName(), + user.getUsername()); } @Override diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java index 2346fe1071..65646d1ad4 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java @@ -1,25 +1,30 @@ package at.tuwien.service.impl; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.CacheService; +import at.tuwien.service.TableService; import com.github.benmanes.caffeine.cache.Cache; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.sql.SQLException; +import java.time.Instant; import java.util.UUID; @Log4j2 @Service public class CacheServiceImpl implements CacheService { + private final TableService tableService; private final MetadataServiceGateway gateway; private final Cache<UUID, UserDto> userCache; private final Cache<UUID, ViewDto> viewCache; @@ -27,12 +32,14 @@ public class CacheServiceImpl implements CacheService { private final Cache<UUID, DatabaseDto> databaseCache; private final Cache<UUID, ContainerDto> containerCache; private final Cache<UUID, DatabaseAccessDto> accessCache; + private final Cache<UUID, TableStatisticDto> statisticCache; @Autowired - public CacheServiceImpl(MetadataServiceGateway gateway, Cache<UUID, UserDto> userCache, + public CacheServiceImpl(TableService tableService, 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) { + Cache<UUID, ContainerDto> containerCache, Cache<UUID, TableStatisticDto> statisticCache) { + this.tableService = tableService; this.gateway = gateway; this.userCache = userCache; this.viewCache = viewCache; @@ -40,6 +47,7 @@ public class CacheServiceImpl implements CacheService { this.accessCache = accessCache; this.databaseCache = databaseCache; this.containerCache = containerCache; + this.statisticCache = statisticCache; } @Override @@ -78,6 +86,21 @@ public class CacheServiceImpl implements CacheService { return table; } + @Override + public TableStatisticDto getStatistic(DatabaseDto database, ViewDto view) throws TableNotFoundException, + TableMalformedException, QueryMalformedException, SQLException { + final TableStatisticDto cacheStatistic = statisticCache.getIfPresent(view.getId()); + if (cacheStatistic != null) { + log.trace("found view statistic with id {} in cache", view.getId()); + return cacheStatistic; + } + log.debug("view statistic with id {} not it cache (anymore): reload", view.getId()); + final TableStatisticDto statistic = tableService.getStatistics(database, view.getInternalName()); + statistic.setTotalRows(tableService.getCount(database, view.getInternalName(), Instant.now())); + statisticCache.put(view.getId(), statistic); + return statistic; + } + @Override public ContainerDto getContainer(UUID id) throws RemoteUnavailableException, MetadataServiceException, ContainerNotFoundException { @@ -144,6 +167,7 @@ public class CacheServiceImpl implements CacheService { tableCache.invalidateAll(); databaseCache.invalidateAll(); containerCache.invalidateAll(); + statisticCache.invalidateAll(); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceMariaDbImpl.java index 9e35574d8d..ff14b7329d 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceMariaDbImpl.java @@ -1,12 +1,12 @@ package at.tuwien.service.impl; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import at.tuwien.config.RabbitConfig; -import at.tuwien.exception.DatabaseMalformedException; -import at.tuwien.exception.QueryStoreCreateException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryStoreCreateException; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.ContainerService; import com.mchange.v2.c3p0.ComboPooledDataSource; 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 7cf7d1eff4..cbe1912b3a 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 @@ -1,6 +1,6 @@ package at.tuwien.service.impl; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.service.CredentialService; import com.github.benmanes.caffeine.cache.Cache; @@ -8,6 +8,8 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.Instant; + @Log4j2 @Service public class CredentialServiceImpl implements CredentialService { @@ -25,10 +27,16 @@ public class CredentialServiceImpl implements CredentialService { public TokenDto getAccessToken(String username, String password) { final TokenDto cacheAccessToken = tokenCache.getIfPresent(username); if (cacheAccessToken != null) { - log.trace("found access token for user with username {} in cache", username); - return cacheAccessToken; + final Instant expiry = Instant.ofEpochSecond(cacheAccessToken.getExpiresIn()); + if (!expiry.isBefore(Instant.now())) { + log.trace("found access token for user with username {} in cache", username); + return cacheAccessToken; + } else { + log.debug("access token for user with username {} expired in cache: request new", username); + } + } else { + log.debug("access token for user with username {} not it cache (anymore): request new", username); } - log.debug("access token for user with username {} not it cache (anymore): request new", username); final TokenDto token = keycloakGateway.obtainUserToken(username, password); tokenCache.put(username, token); return token; 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 6e6e316b5a..366afd92a3 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 @@ -1,7 +1,7 @@ package at.tuwien.service.impl; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; 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 846fa86a4c..c6a0d61595 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,12 +1,12 @@ package at.tuwien.service.impl; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.database.table.internal.TableCreateDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.mapper.DataMapper; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.mapper.MetadataMapper; @@ -48,7 +48,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas try { /* obtain only view metadata */ long start = System.currentTimeMillis(); - final PreparedStatement statement1 = connection.prepareStatement(mariaDbMapper.databaseViewSelectRawQuery()); + final PreparedStatement statement1 = connection.prepareStatement(mariaDbMapper.databaseTableSelectRawQuery()); statement1.setString(1, database.getInternalName()); statement1.setString(2, viewName); log.trace("1={}, 2={}", database.getInternalName(), viewName); 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 07b889d536..541f68e951 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,8 +1,8 @@ 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.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; import at.tuwien.mapper.DataMapper; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.QueueService; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java index 2d421ed0f3..76bfb60c4d 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java @@ -1,11 +1,11 @@ package at.tuwien.service.impl; -import at.tuwien.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; import at.tuwien.config.S3Config; -import at.tuwien.exception.MalformedException; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; -import at.tuwien.exception.TableMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException; import at.tuwien.service.StorageService; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; 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 274654db63..7ace8e4a05 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 @@ -1,11 +1,11 @@ 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.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.DataMapper; import at.tuwien.mapper.MariaDbMapper; 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 4ca226ffde..8e6e6acab3 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,12 +1,12 @@ 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; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.ImportDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import at.tuwien.mapper.DataMapper; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.DatabaseService; @@ -51,7 +51,7 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } @Override - public TableStatisticDto getStatistics(DatabaseDto database, TableDto table) throws SQLException, TableMalformedException, + public TableStatisticDto getStatistics(DatabaseDto database, String tableName) throws SQLException, TableMalformedException, TableNotFoundException { final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); @@ -59,27 +59,30 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi try { /* obtain statistic */ final long start = System.currentTimeMillis(); - final String query = mariaDbMapper.tableColumnStatisticsSelectRawQuery(table.getColumns(), table.getInternalName()); + final TableDto tmpTable = databaseService.inspectTable(database, tableName); + final String query = mariaDbMapper.tableColumnStatisticsSelectRawQuery(tmpTable.getColumns(), tableName); if (query == null) { - 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(database, table.getInternalName()); - statistic.setAvgRowLength(tmpTable.getAvgRowLength()); - statistic.setDataLength(tmpTable.getDataLength()); - statistic.setMaxDataLength(tmpTable.getMaxDataLength()); - statistic.setRows(tmpTable.getNumRows()); - /* add to statistic dto */ - table.getColumns() - .stream() - .filter(column -> !MariaDbUtil.numericDataTypes.contains(column.getColumnType())) - .forEach(column -> statistic.getColumns().put(column.getInternalName(), new ColumnStatisticDto())); - log.info("Obtained statistics for the table and {} column(s)", statistic.getColumns().size()); + log.debug("table {}.{} does not have columns that can be analysed for statistical properties", database.getInternalName(), tableName); + return null; } + final ResultSet resultSet = connection.prepareStatement(query) + .executeQuery(); + statistic = dataMapper.resultSetToTableStatistic(resultSet); + statistic.setTotalColumns(Long.parseLong("" + tmpTable.getColumns() + .size())); + log.trace("executed statement in {} ms", System.currentTimeMillis() - start); + statistic.setAvgRowLength(tmpTable.getAvgRowLength()); + statistic.setDataLength(tmpTable.getDataLength()); + statistic.setMaxDataLength(tmpTable.getMaxDataLength()); + statistic.setTotalRows(tmpTable.getNumRows()); + /* add to statistic dto */ + tmpTable.getColumns() + .stream() + .filter(column -> !MariaDbUtil.numericDataTypes.contains(column.getColumnType())) + .forEach(column -> ColumnStatisticDto.builder() + .name(column.getInternalName()) + .build()); + log.info("Obtained statistics for the table and {} column(s)", statistic.getColumns().size()); } catch (SQLException e) { connection.rollback(); log.error("Failed to obtain column statistics: {}", e.getMessage()); @@ -168,7 +171,7 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } @Override - public Long getCount(DatabaseDto database, TableDto table, Instant timestamp) throws SQLException, + public Long getCount(DatabaseDto database, String tableName, Instant timestamp) throws SQLException, QueryMalformedException { final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); @@ -177,19 +180,19 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi /* find table data */ final long start = System.currentTimeMillis(); final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectCountRawQuery( - database.getInternalName(), table.getInternalName(), timestamp)) + database.getInternalName(), tableName, 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 {}.{}: {}", database, table.getInternalName(), e.getMessage()); - throw new QueryMalformedException("Failed to find row count from table " + database + "." + table.getInternalName() + ": " + e.getMessage(), e); + log.error("Failed to find row count from table {}.{}: {}", database, tableName, e.getMessage()); + throw new QueryMalformedException("Failed to find row count from table " + database + "." + tableName + ": " + e.getMessage(), e); } finally { dataSource.close(); } - log.info("Find row count from table {}.{}", database.getInternalName(), table.getInternalName()); + log.info("Find row count from table {}.{}", database.getInternalName(), tableName); return queryResult; } 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 c1ba33ae4a..0ef62bb025 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,9 +1,9 @@ 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; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.QueryMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ViewMalformedException; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.service.ViewService; import com.mchange.v2.c3p0.ComboPooledDataSource; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java b/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java index a917be6d46..6d831d8d11 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/utils/MariaDbUtil.java @@ -1,6 +1,6 @@ package at.tuwien.utils; -import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; import java.util.List; diff --git a/dbrepo-gateway-service/data.json b/dbrepo-gateway-service/data.json new file mode 100644 index 0000000000..f75a07bba8 --- /dev/null +++ b/dbrepo-gateway-service/data.json @@ -0,0 +1,14 @@ +[ + { + "id": "1", + "value": "235", + "site": "LAA", + "timestamp": "2025-03-09T11:00:00Z" + }, + { + "id": "2", + "value": "44", + "site": "Vienna", + "timestamp": "2025-03-08T12:34:34Z" + } +] diff --git a/dbrepo-gateway-service/dbrepo.conf b/dbrepo-gateway-service/dbrepo.conf index f181fdf7a7..fe98534bd8 100644 --- a/dbrepo-gateway-service/dbrepo.conf +++ b/dbrepo-gateway-service/dbrepo.conf @@ -12,62 +12,31 @@ proxy_busy_buffers_size 256k; resolver 127.0.0.11 valid=30s; # docker dns -upstream broker { - server broker-service:15672; -} - -upstream analyse { - server analyse-service:8080; -} - -upstream data { - server data-service:8080; -} - -upstream metadata { - server metadata-service:8080; -} - -upstream search { - server search-service:8080; -} - -upstream ui { - server ui:3000; -} - -upstream dashboard-service { - server dashboard-service:3000; -} - -upstream auth-service { - server auth-service:8080; -} - server { listen 8080 default_server; server_name _; - location /dashboard { + location /dashboard/ { rewrite ^/dashboard/(.*) /$1 break; - proxy_set_header Host $host; + proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://dashboard-service; + proxy_pass http://dashboard-ui:3000; proxy_read_timeout 90; } # Proxy Grafana Live WebSocket connections. - location /dashboard/api/live { - proxy_set_header Host $host; + location /dashboard/api/live/ { + rewrite ^/dashboard/(.*) /$1 break; + proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_http_version 1.1; - proxy_pass http://dashboard-service; + proxy_pass http://dashboard-ui:3000; proxy_read_timeout 90; } @@ -77,7 +46,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://auth-service; + proxy_pass http://auth-service:8080; proxy_read_timeout 90; } @@ -87,7 +56,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://auth-service; + proxy_pass http://auth-service:8080; proxy_read_timeout 90; } @@ -96,7 +65,25 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://search; + proxy_pass http://search-service:8080; + proxy_read_timeout 90; + } + + location /api/datasource { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://dashboard-service:8080; + proxy_read_timeout 90; + } + + location /api/dashboard { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://dashboard-service:8080; proxy_read_timeout 90; } @@ -106,7 +93,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; - proxy_pass http://data; + proxy_pass http://data-service:8080; proxy_read_timeout 90; # Disable request and response buffering proxy_request_buffering off; @@ -119,25 +106,25 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://analyse; + proxy_pass http://analyse-service:8080; proxy_read_timeout 90; } - location ~ "/api/database/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/table/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/(data|history)" { + location ~ "/api/database/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/table/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/(data|statistic|history)" { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://data; + proxy_pass http://data-service:8080; proxy_read_timeout 90; } - location ~ "/api/database/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/view/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/data" { + location ~ "/api/database/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/view/([0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/(data|statistic)" { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://data; + proxy_pass http://data-service:8080; proxy_read_timeout 90; } @@ -146,7 +133,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://metadata; + proxy_pass http://metadata-service:8080; proxy_read_timeout 90; } @@ -155,7 +142,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://data; + proxy_pass http://data-service:8080; proxy_read_timeout 600; } @@ -164,7 +151,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://metadata; + proxy_pass http://metadata-service:8080; proxy_read_timeout 90; } @@ -173,7 +160,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://metadata; + proxy_pass http://metadata-service:8080; proxy_read_timeout 90; } @@ -183,7 +170,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://metadata; + proxy_pass http://metadata-service:8080; proxy_read_timeout 90; } @@ -192,7 +179,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://ui; + proxy_pass http://ui:3000; proxy_read_timeout 90; } } diff --git a/dbrepo-grafana-service/.dockerignore b/dbrepo-grafana-service/.dockerignore new file mode 100644 index 0000000000..fcdfe8de55 --- /dev/null +++ b/dbrepo-grafana-service/.dockerignore @@ -0,0 +1 @@ +rest-service/src/main/resources/*.csv \ No newline at end of file diff --git a/dbrepo-grafana-service/.gitignore b/dbrepo-grafana-service/.gitignore new file mode 100644 index 0000000000..d39a47ee0f --- /dev/null +++ b/dbrepo-grafana-service/.gitignore @@ -0,0 +1,43 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### Environment ### +.env + +### Generated ### +ready +mapping.xml +schema.xsd +*.versionsBackup +metrics.txt + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/dbrepo-grafana-service/.mvn/wrapper/MavenWrapperDownloader.java b/dbrepo-grafana-service/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..a45eb6ba26 --- /dev/null +++ b/dbrepo-grafana-service/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.jar b/dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 GIT binary patch literal 50710 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 literal 0 HcmV?d00001 diff --git a/dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.properties b/dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..642d572ce9 --- /dev/null +++ b/dbrepo-grafana-service/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/dbrepo-grafana-service/Dockerfile b/dbrepo-grafana-service/Dockerfile new file mode 100644 index 0000000000..b01544827f --- /dev/null +++ b/dbrepo-grafana-service/Dockerfile @@ -0,0 +1,31 @@ +###### FIRST STAGE ###### +FROM dbrepo-metadata-service:build AS dependency +MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> + +FROM maven:3-openjdk-17 AS build +MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> + +COPY ./pom.xml ./ + +RUN mvn -fn -B dependency:go-offline + +COPY ./rest-service ./rest-service +COPY --from=dependency /root/.m2/repository/at/tuwien /root/.m2/repository/at/tuwien + +# Make sure it compiles +RUN mvn clean package -DskipTests + +###### SECOND STAGE ###### +FROM eclipse-temurin:17-jdk AS runtime +MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> + +WORKDIR /app + +USER 65534 + +COPY --from=build --chown=65534 ./rest-service/target/dbrepo-grafana-service-rest-service-*.jar ./grafana-service.jar + +# non-root port +EXPOSE 8080 + +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./grafana-service.jar"] \ No newline at end of file diff --git a/dbrepo-grafana-service/README.md b/dbrepo-grafana-service/README.md new file mode 100644 index 0000000000..7160f7bbbc --- /dev/null +++ b/dbrepo-grafana-service/README.md @@ -0,0 +1,38 @@ +# Metadata Service + +## Test + +Run all unit and integration tests and create an HTML+TXT coverage report located in the `report` module: + +```bash +mvn -pl rest-service clean test verify +``` + +Or run only unit tests +in [`KeycloakGatewayUnitTest.java`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/blob/master/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayTest.java): + +```bash +mvn -pl rest-service -Dtest="KeycloakGatewayUnitTest" clean test +``` + +## Run + +Start the Metadata Database before and then run the Metadata Service: + +```bash +mvn -pl rest-service clean spring-boot:run -Dspring-boot.run.profiles=local +``` + +### Endpoints + +#### Actuator + +- Info: http://localhost:9099/actuator/info +- Health: http://localhost:9099/actuator/health + - Readiness: http://localhost:9099/actuator/health/readiness + - Liveness: http://localhost:9099/actuator/health/liveness +- Prometheus: http://localhost:9099/actuator/prometheus + +#### OpenAPI + +- OpenAPI v3 as .yaml: http://localhost:9099/v3/api-docs.yaml \ No newline at end of file diff --git a/dbrepo-grafana-service/mvnw b/dbrepo-grafana-service/mvnw new file mode 100755 index 0000000000..a16b5431b4 --- /dev/null +++ b/dbrepo-grafana-service/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/dbrepo-grafana-service/mvnw.cmd b/dbrepo-grafana-service/mvnw.cmd new file mode 100644 index 0000000000..c8d43372c9 --- /dev/null +++ b/dbrepo-grafana-service/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/dbrepo-grafana-service/pom.xml b/dbrepo-grafana-service/pom.xml new file mode 100644 index 0000000000..763aa408f0 --- /dev/null +++ b/dbrepo-grafana-service/pom.xml @@ -0,0 +1,299 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>3.0.13</version> + </parent> + + <groupId>at.tuwien</groupId> + <artifactId>dbrepo-grafana-service</artifactId> + <name>dbrepo-grafana-service</name> + <version>1.4.4</version> + + <description>Service that creates automated grafana dashboards</description> + + <packaging>pom</packaging> + <modules> + <module>rest-service</module> + </modules> + + <properties> + <java.version>17</java.version> + <spring-cloud.version>4.0.2</spring-cloud.version> + <mapstruct.version>1.5.5.Final</mapstruct.version> + <rabbitmq.version>5.20.0</rabbitmq.version> + <jackson-datatype.version>2.15.0</jackson-datatype.version> + <commons-io.version>2.15.0</commons-io.version> + <commons-validator.version>1.8.0</commons-validator.version> + <jacoco.version>0.8.11</jacoco.version> + <jwt.version>4.3.0</jwt.version> + <opencsv.version>5.7.1</opencsv.version> + <super-csv.version>2.4.0</super-csv.version> + <jsql.version>4.6</jsql.version> + <springdoc-openapi.version>2.3.0</springdoc-openapi.version> + <hsqldb.version>2.7.2</hsqldb.version> + <testcontainers.version>1.19.1</testcontainers.version> + <jackson.version>2.15.2</jackson.version> + <c3p0.version>0.9.5.5</c3p0.version> + <c3p0-hibernate.version>6.2.2.Final</c3p0-hibernate.version> + <aws-s3.version>2.25.23</aws-s3.version> + <minio.version>8.5.7</minio.version> + <apache-commons.version>1.10.0</apache-commons.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-bootstrap</artifactId> + <version>${spring-cloud.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-text</artifactId> + <version>${apache-commons.version}</version> + + </dependency> + <!-- Caching --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-redis</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-cache</artifactId> + </dependency> + <dependency> + <groupId>redis.clients</groupId> + <artifactId>jedis</artifactId> + </dependency> + <!-- Open API --> + <dependency> + <groupId>org.springdoc</groupId> + <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> + <version>${springdoc-openapi.version}</version> + </dependency> + <!-- Data Source --> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + </dependency> + <dependency> + <groupId>com.mchange</groupId> + <artifactId>c3p0</artifactId> + <version>${c3p0.version}</version> + </dependency> + <dependency> + <groupId>org.hibernate.orm</groupId> + <artifactId>hibernate-c3p0</artifactId> + <version>${c3p0-hibernate.version}</version> + </dependency> + <!-- Monitoring --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-aop</artifactId> + </dependency> + <dependency> + <groupId>io.micrometer</groupId> + <artifactId>micrometer-registry-prometheus</artifactId> + <version>${micrometer.version}</version> + </dependency> + <dependency> + <groupId>io.micrometer</groupId> + <artifactId>micrometer-observation-test</artifactId> + <version>${micrometer.version}</version> + <scope>test</scope> + </dependency> + <!-- IDE --> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <scope>compile</scope> + </dependency> + <!-- Mapping --> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>${mapstruct.version}</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + <version>${mapstruct.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>${jackson-datatype.version}</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>${commons-io.version}</version> + </dependency> + <dependency> + <groupId>commons-validator</groupId> + <artifactId>commons-validator</artifactId> + <version>${commons-validator.version}</version> + </dependency> + <!-- Authentication --> + <dependency> + <groupId>com.auth0</groupId> + <artifactId>java-jwt</artifactId> + <version>${jwt.version}</version> + </dependency> + <!-- DTOs --> + <dependency> + <groupId>at.tuwien</groupId> + <artifactId>dbrepo-metadata-service-api</artifactId> + <version>${project.version}</version> + </dependency> + <!-- AMPQ --> + <dependency> + <groupId>org.springframework.amqp</groupId> + <artifactId>spring-rabbit</artifactId> + </dependency> + <dependency> + <groupId>com.rabbitmq</groupId> + <artifactId>amqp-client</artifactId> + <version>${rabbitmq.version}</version> + </dependency> + <!-- Storage --> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <version>${aws-s3.version}</version> + </dependency> + <!-- Testing --> + <dependency> + <groupId>com.github.jsqlparser</groupId> + <artifactId>jsqlparser</artifactId> + <version>${jsql.version}</version> + </dependency> + <dependency> + <groupId>at.tuwien</groupId> + <artifactId>dbrepo-metadata-service-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>rabbitmq</artifactId> + <version>${testcontainers.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>junit-jupiter</artifactId> + <version>${testcontainers.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>mariadb</artifactId> + <version>${testcontainers.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>minio</artifactId> + <version>${testcontainers.version}</version> + </dependency> + <dependency> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>${jacoco.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>${basedir}/src/main/resources</directory> + <filtering>true</filtering> + <includes> + <include>**/application*.yml</include> + <include>**/rdf/*</include> + <include>**/templates/*.txt</include> + <include>**/templates/*.xml</include> + </includes> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>${jacoco.version}</version> + <configuration> + <excludes> + <exclude>at/tuwien/utils/**/*</exclude> + <exclude>at/tuwien/seeder/**/*</exclude> + <exclude>at/tuwien/mapper/**/*</exclude> + <exclude>at/tuwien/handlers/**/*</exclude> + <exclude>at/tuwien/exception/**/*</exclude> + <exclude>at/tuwien/converters/**/*</exclude> + <exclude>at/tuwien/utils/**/*</exclude> + <exclude>at/tuwien/config/**/*</exclude> + <exclude>at/tuwien/auth/**/*</exclude> + <exclude>at/tuwien/gateway/impl/ApiTemplateInterceptorImpl.class</exclude> + <exclude>**/testcontainers.properties</exclude> + <exclude>**/HibernateConnector.class</exclude> + <exclude>**/DbrepoMetadataServiceApplication.class</exclude> + </excludes> + </configuration> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>verify</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> diff --git a/dbrepo-grafana-service/rest-service/pom.xml b/dbrepo-grafana-service/rest-service/pom.xml new file mode 100644 index 0000000000..ace7de5a1c --- /dev/null +++ b/dbrepo-grafana-service/rest-service/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>dbrepo-grafana-service</artifactId> + <groupId>at.tuwien</groupId> + <version>1.4.4</version> + </parent> + + <artifactId>dbrepo-grafana-service-rest-service</artifactId> + <name>dbrepo-grafana-service-rest</name> + <version>1.4.4</version> + + <dependencies> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>repackage</goal><!-- to make it exuteable with $ java -jar ./app.jar --> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/DbrepoGrafanaServiceApplication.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/DbrepoGrafanaServiceApplication.java new file mode 100644 index 0000000000..79c50fa5ef --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/DbrepoGrafanaServiceApplication.java @@ -0,0 +1,13 @@ +package at.tuwien; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; + +@SpringBootApplication +@EnableCaching +public class DbrepoGrafanaServiceApplication { + public static void main(String[] args) { + SpringApplication.run(DbrepoGrafanaServiceApplication.class, args); + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/AuthTokenFilter.java new file mode 100644 index 0000000000..46ec0e6a24 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/AuthTokenFilter.java @@ -0,0 +1,96 @@ +package at.tuwien.auth; + +import at.tuwien.api.auth.RealmAccessDto; +import at.tuwien.api.user.UserDetailsDto; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.Verification; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +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.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; +import java.util.Base64; +import java.util.stream.Collectors; + +@Slf4j +public class AuthTokenFilter extends OncePerRequestFilter { + + @Value("${dbrepo.jwt.public_key}") + private String publicKey; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + final String jwt = parseJwt(request); + if (jwt != null) { + final UserDetails userDetails = verifyJwt(jwt); + final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + + SecurityContextHolder.getContext().setAuthentication(authentication); + } + filterChain.doFilter(request, response); + } + + public UserDetails verifyJwt(String token) throws ServletException { + 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); + } + final X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)); + final RSAPublicKey pubKey; + try { + pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509); + } catch (InvalidKeySpecException e) { + log.error("Provided public key is invalid"); + throw new ServletException("Provided public key is invalid", e); + } + final Algorithm algorithm = Algorithm.RSA256(pubKey, null); + final Verification verification = JWT.require(algorithm); + final JWTVerifier verifier = verification.build(); + final DecodedJWT jwt = verifier.verify(token); + final RealmAccessDto realmAccess = jwt.getClaim("realm_access").as(RealmAccessDto.class); + return UserDetailsDto.builder() + .id(jwt.getSubject()) + .username(jwt.getClaim("client_id").asString()) + .authorities(Arrays.stream(realmAccess.getRoles()).map(SimpleGrantedAuthority::new).collect(Collectors.toList())) + .build(); + } + + /** + * Parses the token from the HTTP header of the request + * + * @param request The request. + * @return The token. + */ + public String parseJwt(HttpServletRequest request) { + String headerAuth = request.getHeader("Authorization"); + if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { + return headerAuth.substring(7, headerAuth.length()); + } + return null; + } +} \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java new file mode 100644 index 0000000000..6cd55e9ef7 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -0,0 +1,60 @@ +package at.tuwien.auth; + +import at.tuwien.api.keycloak.TokenDto; +import at.tuwien.api.user.UserDetailsDto; +import at.tuwien.config.GatewayConfig; +import at.tuwien.exception.ServiceConnectionException; +import at.tuwien.exception.ServiceException; +import at.tuwien.gateway.KeycloakGateway; +import jakarta.servlet.ServletException; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Log4j2 +@Component +public class BasicAuthenticationProvider implements AuthenticationManager { + + private final GatewayConfig gatewayConfig; + private final AuthTokenFilter authTokenFilter; + private final KeycloakGateway keycloakGateway; + + @Autowired + public BasicAuthenticationProvider(GatewayConfig gatewayConfig, AuthTokenFilter authTokenFilter, + KeycloakGateway keycloakGateway) { + this.gatewayConfig = gatewayConfig; + this.authTokenFilter = authTokenFilter; + this.keycloakGateway = keycloakGateway; + } + + @Override + public Authentication authenticate(Authentication auth) throws AuthenticationException { + if (auth.getName().equals(gatewayConfig.getAdminUsername()) + && auth.getCredentials().toString().equals(gatewayConfig.getAdminPassword())) { + log.trace("current user is {}: skip authentication", gatewayConfig.getAdminUsername()); + final UserDetails userDetails = UserDetailsDto.builder() + .username(auth.getName()) + .authorities(List.of(new SimpleGrantedAuthority("admin"))) + .build(); + return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + } + log.trace("current user is {}: begin authentication", auth.getName()); + 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 | ServiceConnectionException | ServiceException e) { + throw new BadCredentialsException("Failed to authenticate with authentication service", e); + } + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/CacheConfig.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/CacheConfig.java new file mode 100644 index 0000000000..dafb08dafc --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/CacheConfig.java @@ -0,0 +1,40 @@ +package at.tuwien.config; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + return RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(connectionFactory) + .withCacheConfiguration("myCache", + RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofSeconds(30)) + ) + .build(); + } + + @Bean + public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + return redisTemplate; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java new file mode 100644 index 0000000000..1692f53b29 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/GatewayConfig.java @@ -0,0 +1,104 @@ +package at.tuwien.config; + +import at.tuwien.interceptor.KeycloakInterceptor; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +@Log4j2 +@Getter +@Configuration +public class GatewayConfig { + + @Value("${dbrepo.endpoints.gatewayService}") + private String gatewayEndpoint; + + @Value("${dbrepo.endpoints.grafana}") + private String grafanaEndpoint; + + @Value("${dbrepo.admin.username}") + private String adminUsername; + + @Value("${dbrepo.admin.password}") + private String adminPassword; + + @Value("${dbrepo.endpoints.dataService}") + private String dataEndpoint; + + @Value("${dbrepo.endpoints.metadataService}") + private String metaDataEndpoint; + + @Value("${dbrepo.grafana.username}") + private String grafanaUsername; + + @Value("${dbrepo.grafana.password}") + private String grafanaPassword; + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Bean("grafanaTemplate") + public RestTemplate grafanaTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(grafanaEndpoint)); + restTemplate.getInterceptors().add(grafanaHttpRequestInterceptor()); + return restTemplate; + } + + @Bean + public ClientHttpRequestInterceptor clientHttpRequestInterceptor() { + return (request, body, execution) -> { + final HttpHeaders headers = request.getHeaders(); + headers.add("Accept", MediaType.APPLICATION_JSON_VALUE); + return execution.execute(request, body); + }; + } + + @Bean + public ClientHttpRequestInterceptor grafanaHttpRequestInterceptor() { + return (request, body, execution) -> { + final HttpHeaders headers = request.getHeaders(); + headers.add("Accept", MediaType.APPLICATION_JSON_VALUE); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setBasicAuth(grafanaUsername, grafanaPassword); + return execution.execute(request, body); + }; + } + + @Bean("dataServiceRestTemplate") + public RestTemplate dataServiceRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(dataEndpoint)); + log.debug("add basic authentication for internal data service: username={}, password=(hidden)", adminUsername); + + restTemplate.getInterceptors() + .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), + clientHttpRequestInterceptor())); + + return restTemplate; + } + + @Bean("metaDataServiceRestTemplate") + public RestTemplate metaDataServiceRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(metaDataEndpoint)); + restTemplate.getInterceptors().add(clientHttpRequestInterceptor()); + return restTemplate; + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/KeycloakConfig.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/KeycloakConfig.java new file mode 100644 index 0000000000..4d258d496a --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/KeycloakConfig.java @@ -0,0 +1,50 @@ +package at.tuwien.config; + +import at.tuwien.interceptor.KeycloakInterceptor; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +import java.util.List; + +@Getter +@Configuration +public class KeycloakConfig { + + @Value("${dbrepo.endpoints.authService}") + private String keycloakEndpoint; + + @Value("${dbrepo.keycloak.username}") + private String keycloakUsername; + + @Value("${dbrepo.keycloak.password}") + private String keycloakPassword; + + @Value("${dbrepo.keycloak.client}") + private String keycloakClient; + + @Value("${dbrepo.keycloak.clientSecret}") + private String keycloakClientSecret; + + private final ClientHttpRequestInterceptor clientHttpRequestInterceptor; + + @Autowired + public KeycloakConfig(ClientHttpRequestInterceptor clientHttpRequestInterceptor) { + this.clientHttpRequestInterceptor = clientHttpRequestInterceptor; + } + + @Bean("keycloakRestTemplate") + public RestTemplate brokerRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(keycloakEndpoint)); + restTemplate.getInterceptors() + .addAll(List.of(new KeycloakInterceptor(keycloakUsername, keycloakPassword, keycloakEndpoint), + clientHttpRequestInterceptor)); + return restTemplate; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/WebSecurityConfig.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/WebSecurityConfig.java new file mode 100644 index 0000000000..5bb4b2e970 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/config/WebSecurityConfig.java @@ -0,0 +1,107 @@ +package at.tuwien.config; + +import at.tuwien.auth.AuthTokenFilter; +import at.tuwien.auth.BasicAuthenticationProvider; +import at.tuwien.gateway.KeycloakGateway; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.OrRequestMatcher; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +@SecurityScheme( + name = "bearerAuth", + type = SecuritySchemeType.HTTP, + bearerFormat = "JWT", + scheme = "bearer" +) +@SecurityScheme( + name = "basicAuth", + type = SecuritySchemeType.HTTP, + scheme = "basic" +) +public class WebSecurityConfig { + + @Bean + public AuthTokenFilter authTokenFilter() { + return new AuthTokenFilter(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http, KeycloakGateway keycloakGateway, + GatewayConfig gatewayConfig) throws Exception { + final OrRequestMatcher internalEndpoints = new OrRequestMatcher( + new AntPathRequestMatcher("/actuator/**", "GET"), + new AntPathRequestMatcher("/v3/api-docs.yaml"), + new AntPathRequestMatcher("/v3/api-docs/**"), + new AntPathRequestMatcher("/swagger-ui/**"), + new AntPathRequestMatcher("/swagger-ui.html") + ); + final OrRequestMatcher publicEndpoints = new OrRequestMatcher( + new AntPathRequestMatcher("/api/**", "GET"), + new AntPathRequestMatcher("/api/**", "HEAD") + ); + /* enable CORS and disable CSRF */ + http = http.cors().and().csrf().disable(); + /* set session management to stateless */ + http = http + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and(); + /* set unauthorized requests exception handler */ + http = http + .exceptionHandling() + .authenticationEntryPoint( + (request, response, ex) -> { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, + ex.getMessage() + ); + } + ).and(); + /* set permissions on endpoints */ + http.authorizeHttpRequests() + /* our internal endpoints */ + .requestMatchers(internalEndpoints).permitAll() + /* our public endpoints */ + .requestMatchers(publicEndpoints).permitAll() + /* our private endpoints */ + .anyRequest().authenticated(); + /* add JWT token filter */ + http.addFilterBefore(authTokenFilter(), + UsernamePasswordAuthenticationFilter.class + ); + http.addFilterBefore(new BasicAuthenticationFilter(new BasicAuthenticationProvider(gatewayConfig, + authTokenFilter(), keycloakGateway)), + UsernamePasswordAuthenticationFilter.class + ); + return http.build(); + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + config.addAllowedOriginPattern("*"); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/DashboardConfigDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/DashboardConfigDto.java new file mode 100644 index 0000000000..e93c50362c --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/DashboardConfigDto.java @@ -0,0 +1,46 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DashboardConfigDto { + /** + * Map containing information to create time series data. + * <p> + * The key of the map represents the table id. + * The value is a list of {@link TimeSeriesDto} objects in this table. + */ + private Map<Long, List<TimeSeriesDto>> timeSeriesDto; + + /** + * Map containing information about params for the PieChartPanel. + * <p> + * The key of the map represents the table id. + * The value is a Map with key = column id and value = {@link PieChartConfigDto}. + */ + private Map<Long, Map<Long, PieChartConfigDto>> pieChartConfigDto; + + /** + * Map containing information about params for the Histogram. + * <p> + * The key of the map represents the table id. + * The value is a Map with key = column id and value = {@link HistogramConfigDto}. + */ + private Map<Long, Map<Long, HistogramConfigDto>> histogramConfigDto; + + /** + * Map containing information about params for the tables. + * <p> + * The key of the map represents the table id. + * The value is a dto {@link TableConfigDto} holding the properties. + */ + private Map<Long, TableConfigDto> tableConfigDto; + private Integer refreshRate; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/HistogramConfigDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/HistogramConfigDto.java new file mode 100644 index 0000000000..be6f3b21e8 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/HistogramConfigDto.java @@ -0,0 +1,14 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HistogramConfigDto { + private Integer min; + private Integer max; + private Long size; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/PieChartConfigDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/PieChartConfigDto.java new file mode 100644 index 0000000000..487d7042bf --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/PieChartConfigDto.java @@ -0,0 +1,14 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PieChartConfigDto { + private String limit; + private String decimalPlace; + private Long size; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TableConfigDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TableConfigDto.java new file mode 100644 index 0000000000..0b21d8571d --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TableConfigDto.java @@ -0,0 +1,12 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TableConfigDto { + private Long size; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeDto.java new file mode 100644 index 0000000000..f78cb3d1c5 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeDto.java @@ -0,0 +1,17 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TimeDto { + private Long yearColId; + private Long monthColId; + private Long dayColId; + private Long hourColId; + private Long minuteColId; + private Long secondColId; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeSeriesDto.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeSeriesDto.java new file mode 100644 index 0000000000..dd4356d70b --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/dto/TimeSeriesDto.java @@ -0,0 +1,14 @@ +package at.tuwien.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TimeSeriesDto { + private TimeDto timeDto; + private Long valueColId; + private Long size; +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DashboardEndpoint.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DashboardEndpoint.java new file mode 100644 index 0000000000..bd9cc68b24 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DashboardEndpoint.java @@ -0,0 +1,92 @@ +package at.tuwien.endpoints; + +import at.tuwien.api.error.ApiErrorDto; +import at.tuwien.dto.DashboardConfigDto; +import at.tuwien.service.DashboardService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.validation.constraints.NotBlank; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@Log4j2 +@RestController +@CrossOrigin(origins = "*") +@RequestMapping(path = "/api/dashboard") +public class DashboardEndpoint { + private final DashboardService dashboardService; + + @Autowired + public DashboardEndpoint(DashboardService dashboardService) { + this.dashboardService = dashboardService; + } + + @PostMapping("/generate/{dbId}") + @Operation(summary = "Generate dashboard", + description = "Generates dashboard for a provided database id.", + security = {@SecurityRequirement(name = "bearerAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", + description = "Created a new dashboard", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = String.class))}), + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public ResponseEntity<String> generateDashboard(@RequestHeader("Authorization") String token, + @NotBlank @PathVariable("dbId") Long dbId, + @RequestBody(required = false) DashboardConfigDto configDto) { + + return ResponseEntity.status(HttpStatus.CREATED) + .body(this.dashboardService.generateDashboard(dbId, token, configDto)); + } + + @RequestMapping(value = "/exists/{dbId}", method = {RequestMethod.GET, RequestMethod.HEAD}) + @Operation(summary = "Check if dashboard exists", + description = "Checks if a dashboard for a provided database id exists.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Returns Boolean if dashboard exsists", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = Boolean.class))}), + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public ResponseEntity<Boolean> checkIfDashboardExists(@NotBlank @PathVariable("dbId") Long dbId) { + return ResponseEntity.status(HttpStatus.OK) + .body(this.dashboardService.checkIfDashboardExists(dbId)); + } + + @DeleteMapping("/{dbId}") + @Operation(summary = "Delete dashboard in Grafana", + description = "Deletes a dashboard in Grafana for a provided id.", + security = {@SecurityRequirement(name = "bearerAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "202", + description = "Deleted grafana dashbaord"), + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<Void> removeDashboard(@NotBlank @PathVariable("dbId") Long dbId) { + this.dashboardService.removeDashboard(dbId); + return ResponseEntity.status(HttpStatus.ACCEPTED).build(); + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DataEndpoint.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DataEndpoint.java new file mode 100644 index 0000000000..6e698347df --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/endpoints/DataEndpoint.java @@ -0,0 +1,157 @@ +package at.tuwien.endpoints; + +import at.tuwien.api.error.ApiErrorDto; +import at.tuwien.panels.*; +import at.tuwien.service.DataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.constraints.NotBlank; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping(path = DataEndpoint.API_PREFIX) +public class DataEndpoint { + public static final String API_PREFIX = "/api/dashboard/data"; + private final DataService dataService; + private static final Long DEFAULT_RESPONSE_SIZE = 100L; + + @Autowired + public DataEndpoint(DataService dataService) { + this.dataService = dataService; + } + + @GetMapping(PieChartPanel.RELATIVE_PATH + "/{dbId}/{viewId}") + @Operation(summary = "Returns data for Pie Chart", + description = "Returns data for Pie Chart for a specific database and view") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public Map<String, Object> getPieChart(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long viewId, + @RequestParam(required = false) Long size) { + if (size == null) { + size = DEFAULT_RESPONSE_SIZE; + } + + return dataService.getPieChartData(dbId, viewId, size); + } + + @GetMapping(CntAllPanel.RELATIVE_PATH + "/{dbId}/{viewId}") + @Operation(summary = "Returns data for the Count All Stats Visualization", + description = "Returns data for the Count All Stats Visualization for a specific database and view") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public Map<String, Object> getCntAll(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long viewId) { + + return dataService.getCntAllData(dbId, viewId); + } + + @GetMapping(TablePanel.RELATIVE_PATH + "/{dbId}/{tableId}") + @Operation(summary = "Returns data for the Table Visualization", + description = "Returns data for the Table Visualization for a specific database and table") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public List<Map<String, Object>> getTable(@NotBlank @PathVariable Long dbId, + @NotBlank @PathVariable Long tableId, + @RequestParam(required = false) Long size) { + if (size == null) { + size = DEFAULT_RESPONSE_SIZE; + } + + return dataService.getTableData(dbId, tableId, size); + } + + @GetMapping(HistogramPanel.RELATIVE_PATH + "/{dbId}/{viewId}") + @Operation(summary = "Returns data for the Histogram Visualization", + description = "Returns data for the Histogram Visualization for a specific database and view") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public Map<String, List<Object>> getHistogram(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long viewId, + @RequestParam(required = false) Long size) { + if (size == null) { + size = DEFAULT_RESPONSE_SIZE; + } + + return dataService.getHistogramData(dbId, viewId, size); + } + + @GetMapping(StatsPanel.RELATIVE_PATH + "/{dbId}/{tableId}") + @Operation(summary = "Returns data for the Stats Visualization", + description = "Returns data for the Stats Visualization for a specific database and table") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public List<Map<String, Object>> getStats(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long tableId) { + return dataService.getStatsData(dbId, tableId); + } + + @GetMapping(TimeSeriesPanel.RELATIVE_PATH + "/{dbId}/{viewId}") + @Operation(summary = "Returns data for the Time Visualization", + description = "Returns data for the Time Visualization for a specific database and view") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public Map<String, List<Map<String, Object>>> getTimeSeries(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long viewId, + @RequestParam(required = false) Long size) { + if (size == null) { + size = DEFAULT_RESPONSE_SIZE; + } + return dataService.getTimeSeriesData(dbId, viewId, size); + } + + @GetMapping(MultiTimeSeriesPanel.RELATIVE_PATH + "/{dbId}/{viewId}") + @Operation(summary = "Returns data for the Multi Time Visualization", + description = "Returns data for the MUlti Time Visualization for a specific database and view") + @ApiResponses(value = { + @ApiResponse(responseCode = "500", + description = "Internal error", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public Map<String, List<Map<String, Object>>> getMultiTimeSeries(@NotBlank @PathVariable Long dbId, @NotBlank @PathVariable Long viewId, + @RequestParam(required = false) Long size) { + if (size == null) { + size = DEFAULT_RESPONSE_SIZE; + } + return dataService.getMultiTimeSeriesData(dbId, viewId, size); + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ContainerNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ContainerNotFoundException.java new file mode 100644 index 0000000000..a15fcfb8a9 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ContainerNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class ContainerNotFoundException extends Exception { + + public ContainerNotFoundException(String message) { + super(message); + } + + public ContainerNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public ContainerNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseMalformedException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseMalformedException.java new file mode 100644 index 0000000000..1ead17c389 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseMalformedException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class DatabaseMalformedException extends Exception { + + public DatabaseMalformedException(String message) { + super(message); + } + + public DatabaseMalformedException(String message, Throwable thr) { + super(message, thr); + } + + public DatabaseMalformedException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java new file mode 100644 index 0000000000..cb9075c80a --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class DatabaseNotFoundException extends Exception { + + public DatabaseNotFoundException(String message) { + super(message); + } + + public DatabaseNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public DatabaseNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java new file mode 100644 index 0000000000..e584390ec9 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class DatabaseUnavailableException extends Exception { + + public DatabaseUnavailableException(String message) { + super(message); + } + + public DatabaseUnavailableException(String message, Throwable thr) { + super(message, thr); + } + + public DatabaseUnavailableException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/FormatNotAvailableException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/FormatNotAvailableException.java new file mode 100644 index 0000000000..4ca41e346d --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/FormatNotAvailableException.java @@ -0,0 +1,23 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +import java.io.IOException; + +@ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE) +public class FormatNotAvailableException extends IOException { + + public FormatNotAvailableException(String msg) { + super(msg); + } + + public FormatNotAvailableException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public FormatNotAvailableException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/JsonProcessingException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/JsonProcessingException.java new file mode 100644 index 0000000000..66f414018f --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/JsonProcessingException.java @@ -0,0 +1,17 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class JsonProcessingException extends RuntimeException { + + public JsonProcessingException(String message) { + super(message); + } + + public JsonProcessingException(String message, Throwable thr) { + super(message, thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/NotAllowedException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/NotAllowedException.java new file mode 100644 index 0000000000..341b93a644 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/NotAllowedException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.FORBIDDEN) +public class NotAllowedException extends Exception { + + public NotAllowedException(String message) { + super(message); + } + + public NotAllowedException(String message, Throwable thr) { + super(message, thr); + } + + public NotAllowedException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/PaginationException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/PaginationException.java new file mode 100644 index 0000000000..b47c66c5b3 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/PaginationException.java @@ -0,0 +1,22 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class PaginationException extends Exception { + + public PaginationException(String msg) { + super(msg); + } + + public PaginationException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public PaginationException(Throwable thr) { + super(thr); + } + +} + diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryMalformedException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryMalformedException.java new file mode 100644 index 0000000000..4d89f64f94 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryMalformedException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class QueryMalformedException extends Exception { + + public QueryMalformedException(String message) { + super(message); + } + + public QueryMalformedException(String message, Throwable thr) { + super(message, thr); + } + + public QueryMalformedException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryNotFoundException.java new file mode 100644 index 0000000000..44fcbf4cee --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class QueryNotFoundException extends Exception { + + public QueryNotFoundException(String message) { + super(message); + } + + public QueryNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public QueryNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreCreateException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreCreateException.java new file mode 100644 index 0000000000..e7166363e0 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreCreateException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class QueryStoreCreateException extends Exception { + + public QueryStoreCreateException(String message) { + super(message); + } + + public QueryStoreCreateException(String message, Throwable thr) { + super(message, thr); + } + + public QueryStoreCreateException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreGCException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreGCException.java new file mode 100644 index 0000000000..d1d25bbde1 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreGCException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class QueryStoreGCException extends Exception { + + public QueryStoreGCException(String message) { + super(message); + } + + public QueryStoreGCException(String message, Throwable thr) { + super(message, thr); + } + + public QueryStoreGCException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreInsertException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreInsertException.java new file mode 100644 index 0000000000..95c621493e --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStoreInsertException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class QueryStoreInsertException extends Exception { + + public QueryStoreInsertException(String message) { + super(message); + } + + public QueryStoreInsertException(String message, Throwable thr) { + super(message, thr); + } + + public QueryStoreInsertException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStorePersistException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStorePersistException.java new file mode 100644 index 0000000000..b9250ffefc --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/QueryStorePersistException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class QueryStorePersistException extends Exception { + + public QueryStorePersistException(String message) { + super(message); + } + + public QueryStorePersistException(String message, Throwable thr) { + super(message, thr); + } + + public QueryStorePersistException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RemoteUnavailableException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RemoteUnavailableException.java new file mode 100644 index 0000000000..d007a65c02 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RemoteUnavailableException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class RemoteUnavailableException extends Exception { + + public RemoteUnavailableException(String message) { + super(message); + } + + public RemoteUnavailableException(String message, Throwable thr) { + super(message, thr); + } + + public RemoteUnavailableException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RestTemplateExchangeException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RestTemplateExchangeException.java new file mode 100644 index 0000000000..6724c3f260 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/RestTemplateExchangeException.java @@ -0,0 +1,17 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class RestTemplateExchangeException extends RuntimeException { + + public RestTemplateExchangeException(String message) { + super(message); + } + + public RestTemplateExchangeException(String message, Throwable thr) { + super(message, thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceConnectionException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceConnectionException.java new file mode 100644 index 0000000000..ec36c03e3a --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceConnectionException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_GATEWAY) +public class ServiceConnectionException extends Exception { + + public ServiceConnectionException(String msg) { + super(msg); + } + + public ServiceConnectionException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public ServiceConnectionException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceException.java new file mode 100644 index 0000000000..56004d6a47 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/ServiceException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class ServiceException extends Exception { + + public ServiceException(String message) { + super(message); + } + + public ServiceException(String message, Throwable thr) { + super(message, thr); + } + + public ServiceException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarExportException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarExportException.java new file mode 100644 index 0000000000..88ac95e2e9 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarExportException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class SidecarExportException extends Exception { + + public SidecarExportException(String message) { + super(message); + } + + public SidecarExportException(String message, Throwable thr) { + super(message, thr); + } + + public SidecarExportException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarImportException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarImportException.java new file mode 100644 index 0000000000..8dd9a832be --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SidecarImportException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class SidecarImportException extends Exception { + + public SidecarImportException(String message) { + super(message); + } + + public SidecarImportException(String message, Throwable thr) { + super(message, thr); + } + + public SidecarImportException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageNotFoundException.java new file mode 100644 index 0000000000..79c3608adc --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class StorageNotFoundException extends Exception { + + public StorageNotFoundException(String message) { + super(message); + } + + public StorageNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public StorageNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageUnavailableException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageUnavailableException.java new file mode 100644 index 0000000000..96a33f1175 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/StorageUnavailableException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) +public class StorageUnavailableException extends Exception { + + public StorageUnavailableException(String message) { + super(message); + } + + public StorageUnavailableException(String message, Throwable thr) { + super(message, thr); + } + + public StorageUnavailableException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SyncDatabaseNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SyncDatabaseNotFoundException.java new file mode 100644 index 0000000000..f0bedd46ec --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/SyncDatabaseNotFoundException.java @@ -0,0 +1,17 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class SyncDatabaseNotFoundException extends RuntimeException { + + public SyncDatabaseNotFoundException(String message) { + super(message); + } + + public SyncDatabaseNotFoundException(String message, Throwable thr) { + super(message, thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableExistsException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableExistsException.java new file mode 100644 index 0000000000..dbbe0b86e1 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableExistsException.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) +public class TableExistsException extends Exception { + + public TableExistsException(String message) { + super(message); + } + + public TableExistsException(String message, Throwable thr) { + super(message, thr); + } + + public TableExistsException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableMalformedException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableMalformedException.java new file mode 100644 index 0000000000..6c959fc55b --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableMalformedException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST) +public class TableMalformedException extends Exception { + + public TableMalformedException(String message) { + super(message); + } + + public TableMalformedException(String message, Throwable thr) { + super(message, thr); + } + + public TableMalformedException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableNotFoundException.java new file mode 100644 index 0000000000..05547bdfe2 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/TableNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class TableNotFoundException extends Exception { + + public TableNotFoundException(String message) { + super(message); + } + + public TableNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public TableNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/UserNotFoundException.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/UserNotFoundException.java new file mode 100644 index 0000000000..f3bece1e14 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/exception/UserNotFoundException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND) +public class UserNotFoundException extends Exception { + + public UserNotFoundException(String message) { + super(message); + } + + public UserNotFoundException(String message, Throwable thr) { + super(message, thr); + } + + public UserNotFoundException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/KeycloakGateway.java new file mode 100644 index 0000000000..a05a75a6ff --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -0,0 +1,11 @@ +package at.tuwien.gateway; + +import at.tuwien.api.keycloak.TokenDto; +import at.tuwien.exception.ServiceConnectionException; +import at.tuwien.exception.ServiceException; + +public interface KeycloakGateway { + + TokenDto obtainUserToken(String username, String password) throws ServiceConnectionException, ServiceException; + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java new file mode 100644 index 0000000000..76f3e83cef --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -0,0 +1,81 @@ +package at.tuwien.gateway.impl; + +import at.tuwien.api.keycloak.TokenDto; +import at.tuwien.config.KeycloakConfig; +import at.tuwien.exception.ServiceConnectionException; +import at.tuwien.exception.ServiceException; +import at.tuwien.gateway.KeycloakGateway; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +@Log4j2 +@Service +public class KeycloakGatewayImpl implements KeycloakGateway { + + private final RestTemplate restTemplate; + private final KeycloakConfig keycloakConfig; + + public KeycloakGatewayImpl(@Qualifier("keycloakRestTemplate") RestTemplate restTemplate, + KeycloakConfig keycloakConfig) { + this.restTemplate = restTemplate; + this.keycloakConfig = keycloakConfig; + } + + public TokenDto obtainToken() throws ServiceConnectionException, ServiceException { + final HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); + payload.add("username", keycloakConfig.getKeycloakUsername()); + payload.add("password", keycloakConfig.getKeycloakPassword()); + payload.add("grant_type", "password"); + payload.add("client_id", "admin-cli"); + final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/master/protocol/openid-connect/token"; + log.debug("request admin token from url {}", url); + final ResponseEntity<TokenDto> response; + try { + response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to obtain admin token: {}", e.getMessage()); + throw new ServiceConnectionException("Failed to obtain admin token: " + e.getMessage(), e); + } catch (Exception e) { + log.error("Failed to obtain admin token: remote host answered unexpected: {}", e.getMessage(), e); + throw new ServiceException("Failed to obtain admin token: remote host answered unexpected: " + e.getMessage(), e); + } + return response.getBody(); + } + + @Override + public TokenDto obtainUserToken(String username, String password) throws ServiceConnectionException, ServiceException { + 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 attributes"); + payload.add("client_id", keycloakConfig.getKeycloakClient()); + payload.add("client_secret", keycloakConfig.getKeycloakClientSecret()); + final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/dbrepo/protocol/openid-connect/token"; + log.debug("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 (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to obtain user token: {}", e.getMessage()); + throw new ServiceConnectionException("Failed to obtain user token: " + e.getMessage(), e); + } catch (Exception e) { + log.error("Failed to obtain user token: unexpected response: {}", e.getMessage(), e); + throw new ServiceException("Failed to obtain user token: unexpected response: " + e.getMessage(), e); + } + return response.getBody(); + } + +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/handlers/DashboardApiExceptionHandler.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/handlers/DashboardApiExceptionHandler.java new file mode 100644 index 0000000000..80c834f77c --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/handlers/DashboardApiExceptionHandler.java @@ -0,0 +1,52 @@ +package at.tuwien.handlers; + +import at.tuwien.api.error.ApiErrorDto; +import at.tuwien.exception.RestTemplateExchangeException; +import at.tuwien.exception.JsonProcessingException; +import at.tuwien.exception.SyncDatabaseNotFoundException; +import io.swagger.v3.oas.annotations.Hidden; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; + +@Log4j2 +@ControllerAdvice +public class DashboardApiExceptionHandler { + + @Hidden + @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(JsonProcessingException.class) + public ResponseEntity<ApiErrorDto> handle(JsonProcessingException e) { + return genericHandle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(RestTemplateExchangeException.class) + public ResponseEntity<ApiErrorDto> handle(RestTemplateExchangeException e) { + return genericHandle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(SyncDatabaseNotFoundException.class) + public ResponseEntity<ApiErrorDto> handle(SyncDatabaseNotFoundException e) { + return genericHandle(e.getClass(), e.getLocalizedMessage()); + } + + private ResponseEntity<ApiErrorDto> genericHandle(Class<?> exceptionClass, String message) { + final HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/problem+json"); + final ResponseStatus annotation = exceptionClass.getAnnotation(ResponseStatus.class); + final ApiErrorDto response = ApiErrorDto.builder() + .status(annotation.code()) + .message(message) + .code(annotation.reason()) + .build(); + return new ResponseEntity<>(response, headers, response.getStatus()); + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java new file mode 100644 index 0000000000..78fb5adc61 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java @@ -0,0 +1,55 @@ +package at.tuwien.interceptor; + +import at.tuwien.api.keycloak.TokenDto; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.*; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; + +@Log4j2 +public class KeycloakInterceptor implements ClientHttpRequestInterceptor { + + private final String adminUsername; + private final String adminPassword; + private final String keycloakEndpoint; + + public KeycloakInterceptor(String adminUsername, String adminPassword, String keycloakEndpoint) { + this.adminUsername = adminUsername; + this.adminPassword = adminPassword; + this.keycloakEndpoint = keycloakEndpoint; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + final RestTemplate restTemplate = new RestTemplate(); + final HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); + payload.add("username", adminUsername); + payload.add("password", adminPassword); + payload.add("grant_type", "password"); + payload.add("client_id", "admin-cli"); + final ResponseEntity<TokenDto> response; + try { + response = restTemplate.exchange(keycloakEndpoint + "/realms/master/protocol/openid-connect/token", + HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + log.error("Failed to obtain admin token: {}", e.getMessage()); + return execution.execute(request, body); + } + if (response.getBody() == null) { + return execution.execute(request, body); + } + request.getHeaders().set("Authorization", "Bearer " + response.getBody().getAccessToken()); + return execution.execute(request, body); + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/AbstractPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/AbstractPanel.java new file mode 100644 index 0000000000..7d45e43922 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/AbstractPanel.java @@ -0,0 +1,47 @@ +package at.tuwien.panels; + +import lombok.Setter; + +public abstract class AbstractPanel { + @Setter + protected static String dataEndpoint; + public static final String DATASRC_UID = "infinityDataSrc"; + + protected static int x; + protected static int y; + private static int prevHeight = -1; + + public static void resetCoordinates() { + x = 0; + y = 0; + } + + public static void addRowPlaceHolder() { + y += 1; + } + + public static void markNewRow() { + x = 0; + } + + + public static void handleOverflow(int height, int width) { + if ( (x + width) > 24) { + x = 0; + y += prevHeight == -1 ? height : prevHeight; + prevHeight = height; + } + } + + public static void updateCoords(int height, int width) { + x += width; + + if (x > 24) { + x = 0; + y += prevHeight == -1 ? height : prevHeight; + } + prevHeight = height; + } + + public abstract String getConstructedPanel(); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/CntAllPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/CntAllPanel.java new file mode 100644 index 0000000000..f5af7d56e4 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/CntAllPanel.java @@ -0,0 +1,69 @@ +package at.tuwien.panels; + +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class CntAllPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/cntAll"; + private static final int HEIGHT = 8; + private static final int WIDTH = 5; + private final String dataAPI; + + public CntAllPanel(Long dbId, Long vId) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, vId); + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = "{\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"fieldConfig\": {\n" + + " \"defaults\": {\n" + + " \"color\": {\n" + + " \"fixedColor\": \"#FFFFFF\",\n" + + " \"mode\": \"fixed\"\n" + + " },\n" + + " \"mappings\": []\n" + + " },\n" + + " \"overrides\": []\n" + + " },\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"columns\": [],\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"filters\": [],\n" + + " \"format\": \"table\",\n" + + " \"global_query_id\": \"\",\n" + + " \"refId\": \"A\",\n" + + " \"root_selector\": \"\",\n" + + " \"source\": \"url\",\n" + + " \"type\": \"json\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"data\": \"\",\n" + + " \"method\": \"GET\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"title\": \"Total elements\",\n" + + " \"type\": \"stat\"\n" + + " }"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/Dashboard.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/Dashboard.java new file mode 100644 index 0000000000..322485b909 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/Dashboard.java @@ -0,0 +1,29 @@ +package at.tuwien.panels; + +import java.util.List; + +public class Dashboard { + + public String getDashboard(List<String> panels, Long dbId, int refreshrate) { + + return "{\n" + + " \"dashboard\": {\n" + + " \"id\": null,\n" + + " \"uid\": \"" + dbId + "\",\n" + + " \"title\": \"automated dashboard_" + dbId + "\",\n" + + " \"tags\": [\n" + + " \"templated\"\n" + + " ],\n" + + " \"timezone\": \"browser\",\n" + + " \"schemaVersion\": 16,\n" + + " \"refresh\": \"" + (refreshrate == 0 ? "" : refreshrate + "s") + "\",\n" + + " \"panels\": [" + + String.join(", ", panels) + + " ]" + + " \n" + + " },\n" + + " \"message\": \"automated creation of dashboard\",\n" + + " \"overwrite\": false\n" + + "}"; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/HistogramPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/HistogramPanel.java new file mode 100644 index 0000000000..e021f0ab6b --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/HistogramPanel.java @@ -0,0 +1,110 @@ +package at.tuwien.panels; + +import at.tuwien.dto.HistogramConfigDto; +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class HistogramPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/histogram"; + private static final int HEIGHT = 8; + private static final int WIDTH = 5; + private String dataAPI; + private final String colName; + private Integer min; + private Integer max; + + public HistogramPanel(Long dbId, Long vId, String colName, HistogramConfigDto configDto) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, vId); + this.colName = colName; + + if (configDto != null) { + if (configDto.getMin() != null) { + this.min = configDto.getMin(); + } + + if (configDto.getMax() != null) { + this.max = configDto.getMax(); + } + + if (configDto.getSize() != null) { + dataAPI += String.format("?size=%d", configDto.getSize()); + } + } + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = "{\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"fieldConfig\": {\n" + + " \"defaults\": {\n" + + " \"color\": {\n" + + " \"mode\": \"palette-classic\"\n" + + " },\n" + + " \"custom\": {\n" + + " \"fillOpacity\": 80,\n" + + " \"gradientMode\": \"none\",\n" + + " \"hideFrom\": {\n" + + " \"legend\": false,\n" + + " \"tooltip\": true,\n" + + " \"viz\": false\n" + + " },\n" + + " \"lineWidth\": 1\n" + + " },\n" + + " \"mappings\": [],\n" + + " \"max\": " + ((max == null) ? "null" : max) + ",\n" + + " \"min\": " + ((min == null) ? "null" : min) + "\n" + + " },\n" + + " \"overrides\": []\n" + + " },\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + " \"id\": null,\n" + + " \"description\": \"" + "Each bar represents a bucket, and the bar height represents " + + "the frequency of the values from the column " + this.colName + " that fell into that bucket's interval.\",\n" + + " \"options\": {\n" + + " \"legend\": {\n" + + " \"calcs\": [],\n" + + " \"displayMode\": \"list\",\n" + + " \"placement\": \"bottom\",\n" + + " \"showLegend\": false\n" + + " }\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"columns\": [],\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"filters\": [],\n" + + " \"format\": \"table\",\n" + + " \"global_query_id\": \"\",\n" + + " \"refId\": \"A\",\n" + + " \"root_selector\": \"values\",\n" + + " \"source\": \"url\",\n" + + " \"type\": \"json\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"data\": \"\",\n" + + " \"method\": \"GET\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"title\": \"" + "Distribution of " + this.colName + " \",\n" + + " \"type\": \"histogram\"\n" + + " }"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/MultiTimeSeriesPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/MultiTimeSeriesPanel.java new file mode 100644 index 0000000000..70be0650ee --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/MultiTimeSeriesPanel.java @@ -0,0 +1,90 @@ +package at.tuwien.panels; + +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class MultiTimeSeriesPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/multitimeseries"; + public static final String VIEW_MULTI_TIMECOL = "timecol"; + public static final String VIEW_MULTI_SELECTOR_TIME = "time"; + public static final String VIEW_MULTI_SELECTOR_VALUE = "value"; + public static final String VIEW_MULTI_SELECTOR_NAME = "name"; + + + private static final int HEIGHT = 8; + private static final int WIDTH = 5; + private String dataAPI; + + public MultiTimeSeriesPanel(Long dbId, Long vId) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, vId); + dataAPI += String.format("?size=%d", 100); + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = " {\n" + + "\"datasource\": {\n" + + " \"uid\": \"" + DATASRC_UID + "\",\n" + + " \"type\": \"yesoreyeram-infinity-datasource\"\n" + + " },\n" + + " \"type\": \"timeseries\",\n" + + " \"title\": \"Time Series\",\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + "\"options\": {\n" + + " \"legend\": {\n" + + " \"calcs\": [],\n" + + " \"displayMode\": \"list\",\n" + + " \"placement\": \"bottom\",\n" + + " \"showLegend\": true\n" + + " },\n" + + " \"tooltip\": {\n" + + " \"mode\": \"single\",\n" + + " \"sort\": \"none\"\n" + + " }\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"refId\": \"A\",\n" + + " \"type\": \"json\",\n" + + " \"source\": \"url\",\n" + + " \"format\": \"timeseries\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"method\": \"GET\",\n" + + " \"data\": \"\"\n" + + " },\n" + + " \"root_selector\": \"time_series\",\n" + + " \"columns\": [\n" + + " {\n" + + " \"selector\": \"" + VIEW_MULTI_SELECTOR_TIME + "\",\n" + + " \"type\": \"timestamp\"\n" + + " },\n" + + " {\n" + + " \"selector\": \"" + VIEW_MULTI_SELECTOR_VALUE + "\",\n" + + " \"type\": \"number\"\n" + + " },\n" + + " {\n" + + " \"selector\": \"" + VIEW_MULTI_SELECTOR_NAME + "\",\n" + + " \"type\": \"string\"\n" + + " }\n" + + " ],\n" + + " \"filters\": [],\n" + + " \"global_query_id\": \"\"\n" + + " }\n" + + " ]}"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/PieChartPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/PieChartPanel.java new file mode 100644 index 0000000000..3b98dec4d0 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/PieChartPanel.java @@ -0,0 +1,110 @@ +package at.tuwien.panels; + +import at.tuwien.dto.PieChartConfigDto; +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class PieChartPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/piechart"; + public static final String VIEW_PIE_PERCENTAGE_COL = "percentage"; + + private static final int HEIGHT = 8; + private static final int WIDTH = 7; + private String dataAPI; + private final String colName; + + public PieChartPanel(Long dbId, Long vId, String colName, PieChartConfigDto config) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, vId); + this.colName = colName; + + if (config != null && config.getSize() != null) { + dataAPI += String.format("?size=%d", config.getSize()); + } + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = "{\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"fieldConfig\": {\n" + + " \"defaults\": {\n" + + " \"color\": {\n" + + " \"mode\": \"palette-classic\"\n" + + " },\n" + + " \"custom\": {\n" + + " \"hideFrom\": {\n" + + " \"legend\": false,\n" + + " \"tooltip\": false,\n" + + " \"viz\": false\n" + + " }\n" + + " },\n" + + " \"mappings\": []\n" + + " },\n" + + " \"overrides\": []\n" + + " },\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + " \"options\": {\n" + + " \"displayLabels\": [\n" + + " \"percent\"\n" + + " ],\n" + + " \"legend\": {\n" + + " \"calcs\": [],\n" + + " \"displayMode\": \"list\",\n" + + " \"placement\": \"right\",\n" + + " \"showLegend\": true,\n" + + " \"values\": [\n" + + " \"value\"\n" + + " ]\n" + + " },\n" + + " \"pieType\": \"pie\",\n" + + " \"reduceOptions\": {\n" + + " \"calcs\": [\n" + + " \"lastNotNull\"\n" + + " ],\n" + + " \"fields\": \"\",\n" + + " \"values\": false\n" + + " },\n" + + " \"tooltip\": {\n" + + " \"mode\": \"single\",\n" + + " \"sort\": \"none\"\n" + + " }\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"columns\": [],\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"filters\": [],\n" + + " \"format\": \"table\",\n" + + " \"global_query_id\": \"\",\n" + + " \"refId\": \"A\",\n" + + " \"root_selector\": \"\",\n" + + " \"source\": \"url\",\n" + + " \"type\": \"json\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"data\": \"\",\n" + + " \"method\": \"GET\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"title\": \"Distribution of Most Frequent " + this.colName + "\",\n" + + " \"type\": \"piechart\"\n" + + " }"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/RowPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/RowPanel.java new file mode 100644 index 0000000000..94ae55b74b --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/RowPanel.java @@ -0,0 +1,52 @@ +package at.tuwien.panels; + +import at.tuwien.exception.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.log4j.Log4j2; + +import java.util.List; + +@Log4j2 +public class RowPanel extends AbstractPanel { + private static final int HEIGHT = 1; + private static final int WIDTH = 24; + private final String name; + private final List<String> tablePanels; + private final ObjectMapper mapper; + + public RowPanel(String name, List<String> tablePanels) { + this.name = name; + this.tablePanels = tablePanels; + this.mapper = new ObjectMapper(); + } + + @Override + public String getConstructedPanel() { + + int rowY = -1; + try{ + JsonNode rootNode = mapper.readTree(tablePanels.get(0)); + rowY = rootNode.path("gridPos").path("y").asInt() - 1; + } catch (Exception e) { + log.debug("failed to read json of table panel"); + throw new JsonProcessingException("Failed to parse table panel"); + } + + return "{\n" + + " \"collapsed\": true,\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + 0 + ",\n" + + " \"y\": " + rowY + "\n" + + " },\n" + + " \"id\": null,\n" + + " \"panels\": [" + + String.join(", ", tablePanels) + + "],\n" + + " \"title\": \"" + name + "\",\n" + + " \"type\": \"row\"\n" + + " }"; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/StatsPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/StatsPanel.java new file mode 100644 index 0000000000..81e9204336 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/StatsPanel.java @@ -0,0 +1,183 @@ +package at.tuwien.panels; + +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class StatsPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/stats"; + public static final String HEADER_COL = "column"; + public static final String HEADER_MIN = "min"; + public static final String HEADER_MAX = "max"; + public static final String HEADER_STDDEV = "stddev"; + public static final String HEADER_AVG = "median"; + + private static final int HEIGHT = 8; + private static final int WIDTH = 9; + private final String dataAPI; + private final String name; + + public StatsPanel(Long dbId, Long tId, String name) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, tId); + this.name = name; + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = " {\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"fieldConfig\": {\n" + + " \"defaults\": {\n" + + " \"custom\": {\n" + + " \"align\": \"auto\",\n" + + " \"filterable\": \"true\",\n" + + " \"cellOptions\": {\n" + + " \"type\": \"auto\"\n" + + " },\n" + + " \"inspect\": false\n" + + " },\n" + + " \"mappings\": [],\n" + + " \"thresholds\": {\n" + + " \"mode\": \"absolute\",\n" + + " \"steps\": [\n" + + " {\n" + + " \"color\": \"green\",\n" + + " \"value\": null\n" + + " },\n" + + " {\n" + + " \"color\": \"red\",\n" + + " \"value\": 80\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"overrides\": [\n" + + " {\n" + + " \"matcher\": {\n" + + " \"id\": \"byName\",\n" + + " \"options\": \"" + HEADER_COL + "\"\n" + + " },\n" + + " \"properties\": [\n" + + " {\n" + + " \"id\": \"custom.align\",\n" + + " \"value\": \"center\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"matcher\": {\n" + + " \"id\": \"byName\",\n" + + " \"options\": \"" + HEADER_MIN + "\"\n" + + " },\n" + + " \"properties\": [\n" + + " {\n" + + " \"id\": \"custom.width\",\n" + + " \"value\": 115\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"matcher\": {\n" + + " \"id\": \"byName\",\n" + + " \"options\": \"" + HEADER_MAX + "\"\n" + + " },\n" + + " \"properties\": [\n" + + " {\n" + + " \"id\": \"custom.width\",\n" + + " \"value\": 115\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"matcher\": {\n" + + " \"id\": \"byName\",\n" + + " \"options\": \"" + HEADER_AVG + "\"\n" + + " },\n" + + " \"properties\": [\n" + + " {\n" + + " \"id\": \"custom.width\",\n" + + " \"value\": 115\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"matcher\": {\n" + + " \"id\": \"byName\",\n" + + " \"options\": \"" + HEADER_STDDEV + "\"\n" + + " },\n" + + " \"properties\": [\n" + + " {\n" + + " \"id\": \"custom.width\",\n" + + " \"value\": 115\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + " \"options\": {\n" + + " \"cellHeight\": \"sm\",\n" + + " \"footer\": {\n" + + " \"countRows\": false,\n" + + " \"fields\": \"\",\n" + + " \"reducer\": [\n" + + " \"sum\"\n" + + " ],\n" + + " \"show\": false\n" + + " },\n" + + " \"showHeader\": true\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"columns\": [],\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"filters\": [],\n" + + " \"format\": \"table\",\n" + + " \"global_query_id\": \"\",\n" + + " \"refId\": \"A\",\n" + + " \"root_selector\": \"\",\n" + + " \"source\": \"url\",\n" + + " \"type\": \"json\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"data\": \"\",\n" + + " \"method\": \"GET\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"title\": \"Stats for " + name + "\",\n" + + " \"transformations\": [\n" + + " {\n" + + " \"id\": \"organize\",\n" + + " \"options\": {\n" + + " \"excludeByName\": {},\n" + + " \"includeByName\": {},\n" + + " \"indexByName\": {\n" + + " \"" + HEADER_AVG + "\": 3,\n" + + " \"" + HEADER_COL + "\": 0,\n" + + " \"" + HEADER_STDDEV + "\": 4,\n" + + " \"" + HEADER_MAX + "\": 2,\n" + + " \"" + HEADER_MIN + "\": 1\n" + + " }\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"type\": \"table\"\n" + + " }"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TablePanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TablePanel.java new file mode 100644 index 0000000000..7295f1528d --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TablePanel.java @@ -0,0 +1,73 @@ +package at.tuwien.panels; + +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class TablePanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/tablepanel"; + private static final int HEIGHT = 8; + private static final int WIDTH = 16; + private final String name; + + private String dataAPI; + + public TablePanel(Long dbId, Long tId, String name, Long size) { + this.name = name; + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, tId); + if (size != null) { + dataAPI += String.format("?size=%d", size); + } + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = "{\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"fieldConfig\": {\n" + + " \"defaults\": {\n" + + " \"custom\": {\n" + + " \"filterable\": true\n" + + " }\n" + + " }\n" + + " }," + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + " \"id\": null,\n" + + " \"targets\": [\n" + + " {\n" + + " \"columns\": [],\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"filters\": [],\n" + + " \"format\": \"table\",\n" + + " \"global_query_id\": \"\",\n" + + " \"refId\": \"A\",\n" + + " \"root_selector\": \"\",\n" + + " \"source\": \"url\",\n" + + " \"type\": \"json\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"data\": \"\",\n" + + " \"method\": \"GET\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"title\": \"" + name + "\",\n" + + " \"type\": \"table\"\n" + + " }"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TimeSeriesPanel.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TimeSeriesPanel.java new file mode 100644 index 0000000000..e0f5b305ea --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/panels/TimeSeriesPanel.java @@ -0,0 +1,93 @@ +package at.tuwien.panels; + +import at.tuwien.endpoints.DataEndpoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class TimeSeriesPanel extends AbstractPanel { + public static final String RELATIVE_PATH = "/timeseries"; + public static final String TIME_VAL_COL = "value"; + public static final String TIME_YEAR_COL = "year"; + public static final String TIME_MONTH_COL = "month"; + public static final String TIME_DAY_COL = "day"; + public static final String TIME_HOUR_COL = "hour"; + public static final String TIME_MIN_COL = "min"; + public static final String TIME_SECOND_COL = "sec"; + private final String value; + + private static final int HEIGHT = 8; + private static final int WIDTH = 5; + private String dataAPI; + + public TimeSeriesPanel(Long dbId, Long vId, String value, Long size) { + this.dataAPI = String.format("%s%s%s/%d/%d", dataEndpoint, DataEndpoint.API_PREFIX, RELATIVE_PATH, dbId, vId); + this.value = value; + if (size != null) { + dataAPI += String.format("?size=%d", size); + } + } + + @Override + public String getConstructedPanel() { + handleOverflow(HEIGHT, WIDTH); + String panelJson = " {\n" + + "\"datasource\": {\n" + + " \"uid\": \"" + DATASRC_UID + "\",\n" + + " \"type\": \"yesoreyeram-infinity-datasource\"\n" + + " },\n" + + " \"type\": \"timeseries\",\n" + + " \"title\": \"Time Series\",\n" + + " \"gridPos\": {\n" + + " \"h\": " + HEIGHT + ",\n" + + " \"w\": " + WIDTH + ",\n" + + " \"x\": " + x + ",\n" + + " \"y\": " + y + "\n" + + " },\n" + + "\"options\": {\n" + + " \"legend\": {\n" + + " \"calcs\": [],\n" + + " \"displayMode\": \"list\",\n" + + " \"placement\": \"bottom\",\n" + + " \"showLegend\": true\n" + + " },\n" + + " \"tooltip\": {\n" + + " \"mode\": \"single\",\n" + + " \"sort\": \"none\"\n" + + " }\n" + + " },\n" + + " \"targets\": [\n" + + " {\n" + + " \"datasource\": {\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"uid\": \"" + DATASRC_UID + "\"" + + " },\n" + + " \"refId\": \"A\",\n" + + " \"type\": \"json\",\n" + + " \"source\": \"url\",\n" + + " \"format\": \"table\",\n" + + " \"url\": \"" + this.dataAPI + "\",\n" + + " \"url_options\": {\n" + + " \"method\": \"GET\",\n" + + " \"data\": \"\"\n" + + " },\n" + + " \"root_selector\": \"time_series\",\n" + + " \"columns\": [\n" + + " {\n" + + " \"selector\": \"time\",\n" + + " \"type\": \"timestamp\"\n" + + " },\n" + + " {\n" + + " \"text\": \"" + value + "\",\n" + + " \"selector\": \"value\",\n" + + " \"type\": \"number\"\n" + + " }\n" + + " ],\n" + + " \"filters\": [],\n" + + " \"global_query_id\": \"\"\n" + + " }\n" + + " ]}"; + + updateCoords(HEIGHT, WIDTH); + return panelJson; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DashboardService.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DashboardService.java new file mode 100644 index 0000000000..26c66d4efe --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DashboardService.java @@ -0,0 +1,9 @@ +package at.tuwien.service; + +import at.tuwien.dto.DashboardConfigDto; + +public interface DashboardService { + String generateDashboard(Long dbId, String token, DashboardConfigDto configDto); + Boolean checkIfDashboardExists(Long dbId); + void removeDashboard(Long dbId); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataService.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataService.java new file mode 100644 index 0000000000..253fde5ebb --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataService.java @@ -0,0 +1,14 @@ +package at.tuwien.service; + +import java.util.List; +import java.util.Map; + +public interface DataService { + Map<String, Object> getPieChartData(Long dbId, Long viewId, Long size); + Map<String, Object> getCntAllData(Long dbId, Long viewId); + List<Map<String, Object>> getTableData(Long dbId, Long tableId, Long size); + Map<String, List<Object>> getHistogramData(Long dbId, Long viewId, Long size); + List<Map<String, Object>> getStatsData(Long dbId, Long tableId); + Map<String, List<Map<String, Object>>> getTimeSeriesData(Long dbId, Long viewId, Long size); + Map<String, List<Map<String, Object>>> getMultiTimeSeriesData(Long dbId, Long viewId, Long size); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataSourceService.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataSourceService.java new file mode 100644 index 0000000000..070ba1f1d5 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/DataSourceService.java @@ -0,0 +1,7 @@ +package at.tuwien.service; + + +public interface DataSourceService { + String addDatasource(); + String getDatasource(); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/TableService.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/TableService.java new file mode 100644 index 0000000000..49a5b773de --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/TableService.java @@ -0,0 +1,16 @@ +package at.tuwien.service; + + +import at.tuwien.api.database.table.TableBriefDto; +import at.tuwien.api.database.table.TableDto; + +import java.util.List; +import java.util.Map; + + +public interface TableService { + + List<TableBriefDto> getAllTables(Long dbId); + TableDto getTableSchemas(Long dbId, Long tId); + List<Map<String, Object>> getTableData(Long dbId, Long tId, Long size); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/ViewGeneratorService.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/ViewGeneratorService.java new file mode 100644 index 0000000000..ef7def1323 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/ViewGeneratorService.java @@ -0,0 +1,15 @@ +package at.tuwien.service; + +import at.tuwien.dto.PieChartConfigDto; + +import java.util.List; +import java.util.Map; + +public interface ViewGeneratorService { + Long genCntAllView(Long dbId, String tableName, String token); + Long genPieChartView(Long dbId, String tableName, String colName, PieChartConfigDto config, String token); + Long genHistogramView(Long dbId, String tableName, String colName, String token); + Long genStatisticsView(Long dbId, String tableName, String colName, String token); + Long genTimeSeriesView(Long dbId, String tableName, Map<String, String> timeMap, String token); + Long genMultiTimeSeriesView(Long dbId, String tableName, String timeCol, List<String> numValues, String token); +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DashboardServiceImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DashboardServiceImpl.java new file mode 100644 index 0000000000..b373a8c0f8 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DashboardServiceImpl.java @@ -0,0 +1,408 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.query.QueryResultDto; +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.dto.*; +import at.tuwien.exception.JsonProcessingException; +import at.tuwien.panels.*; +import at.tuwien.service.*; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +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.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.*; + +import java.util.*; +import java.util.stream.Collectors; + +import static at.tuwien.panels.TimeSeriesPanel.*; + +@Log4j2 +@Service +public class DashboardServiceImpl implements DashboardService { + + @Value("${dbrepo.endpoints.grafanaService}") + private String grafanaServiceEndpoint; + + @Value("${application.baseurl}") + private String baseUrl; + + @Value("${dbrepo.endpoints.grafanaPort}") + private String grafanaPort; + + @Value("${dbrepo.grafana.default_refreshrate}") + private int defaultRefreshrate; + + private final RestTemplate grafanaRestTemplate; + private final TableService tableService; + private final DataSourceService dataSourceService; + private final ViewGeneratorService viewGeneratorService; + private String token = ""; + + @Autowired + public DashboardServiceImpl(@Qualifier("grafanaTemplate") RestTemplate grafanaRestTemplate, + DataSourceService dataSourceService, TableService tableService, + ViewGeneratorService viewGeneratorService) { + this.grafanaRestTemplate = grafanaRestTemplate; + this.dataSourceService = dataSourceService; + this.tableService = tableService; + this.viewGeneratorService = viewGeneratorService; + } + + @Override + public Boolean checkIfDashboardExists(Long dbId) { + return this.checkForSync(dbId) != null; + } + + @Override + public void removeDashboard(Long dbId) { + String path = String.format("/api/dashboards/uid/%d", dbId); + + try { + ResponseEntity<String> responseEntity = grafanaRestTemplate.exchange( + path, + HttpMethod.DELETE, + null, + String.class + ); + + log.warn(responseEntity.getBody()); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.DELETE, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.DELETE, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.DELETE, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public String generateDashboard(Long dbId, String token, DashboardConfigDto configDto) { + this.token = token; + addDatasourceIfNotPresent(); + + String url = this.checkForSync(dbId); + if (url != null) { + return String.format("%s:%s%s%n", baseUrl, grafanaPort, url); + } + + Map<Long, List<TimeSeriesDto>> timeSeriesParamMap = new HashMap<>(); + Map<Long, Map<Long, PieChartConfigDto>> pieChartParamMap = new HashMap<>(); + Map<Long, Map<Long, HistogramConfigDto>> histogramParamMap = new HashMap<>(); + Map<Long, TableConfigDto> tableParamMap = new HashMap<>(); + DashboardConfigDto dashboardConfigDto = new DashboardConfigDto(); + + if (configDto != null) { + dashboardConfigDto = configDto; + } + + if (dashboardConfigDto.getTimeSeriesDto() != null) { + timeSeriesParamMap = dashboardConfigDto.getTimeSeriesDto(); + } + + if (dashboardConfigDto.getPieChartConfigDto() != null) { + pieChartParamMap = dashboardConfigDto.getPieChartConfigDto(); + } + + if (dashboardConfigDto.getHistogramConfigDto() != null) { + histogramParamMap = dashboardConfigDto.getHistogramConfigDto(); + } + + if (dashboardConfigDto.getTableConfigDto() != null) { + tableParamMap = dashboardConfigDto.getTableConfigDto(); + } + + List<TableBriefDto> tableIds = this.tableService.getAllTables(dbId); + List<Long> idList = tableIds.stream() + .map(TableBriefDto::getId) + .toList(); + + AbstractPanel.setDataEndpoint(grafanaServiceEndpoint); + AbstractPanel.resetCoordinates(); + List<String> rowPanels = new ArrayList<>(); + List<String> tablePanels; + + for (var tId : idList) { + tablePanels = new ArrayList<>(); + TableDto tableSchema = this.tableService.getTableSchemas(dbId, tId); + String tableName = tableSchema.getInternalName(); + + List<ColumnDto> columns = tableSchema.getColumns(); + Set<Long> primaryKeys = tableSchema.getConstraints().getPrimaryKey().stream() + .map(pkDto -> pkDto.getColumn().getId()) + .collect(Collectors.toSet()); + + columns.removeIf(column -> primaryKeys.contains(column.getId())); + + AbstractPanel.addRowPlaceHolder(); + + if (tableParamMap.containsKey(tId)) { + tablePanels.add(generateTablePanel(dbId, tId, tableName, tableParamMap.get(tId).getSize())); + } else { + tablePanels.add(generateTablePanel(dbId, tId, tableName, null)); + } + + tablePanels.add(generateCntAllPanel(dbId, tableName)); + tablePanels.add(generateStatsPanel(dbId, tId, tableName)); + + if (timeSeriesParamMap.containsKey(tId)) { + addTimeSeriesPanel(dbId, tId, tableName, columns, timeSeriesParamMap, tablePanels); + } + + for (var col : columns) { + ColumnTypeDto columnType = col.getColumnType(); + + if (isNumericalColumn(columnType)) { + + if (histogramParamMap.containsKey(tId) && histogramParamMap.get(tId).containsKey(col.getId())) { + tablePanels.add(generateHistogramPanel(dbId, tableName, col.getInternalName(), histogramParamMap.get(tId).get(col.getId()))); + } else { + tablePanels.add(generateHistogramPanel(dbId, tableName, col.getInternalName(), null)); + } + } else if (isStringColumn(columnType)) { + + if (pieChartParamMap.containsKey(tId) && pieChartParamMap.get(tId).containsKey(col.getId())) { + tablePanels.add(generatePieChartPanel(dbId, tableName, col.getInternalName(), pieChartParamMap.get(tId).get(col.getId()))); + } else { + tablePanels.add(generatePieChartPanel(dbId, tableName, col.getInternalName(), null)); + } + } else if (isTimeStamp(columnType)) { + List<String> numColumns = new ArrayList<>(); + + for(var other : columns) { + if (isNumericalColumn(other.getColumnType())) { + numColumns.add(other.getInternalName()); + } + } + + tablePanels.add(generateMultiTimeSeriesPanel(dbId, tableName, col.getInternalName(), numColumns)); + } + } + + rowPanels.add(new RowPanel(tableName, tablePanels).getConstructedPanel()); + AbstractPanel.markNewRow(); + } + + int refreshRate = defaultRefreshrate; + if (dashboardConfigDto.getRefreshRate() != null) { + refreshRate = dashboardConfigDto.getRefreshRate(); + } + + Dashboard d = new Dashboard(); + String dashboardJson = d.getDashboard(rowPanels, dbId, refreshRate); + + String relativeUrl = createDashboard(dashboardJson); + + return String.format("%s:%s%s%n", baseUrl, grafanaPort, relativeUrl); + } + + private String generateCntAllPanel(Long dbId, String tableName) { + Long viewId = this.viewGeneratorService.genCntAllView(dbId, tableName, this.token); + + CntAllPanel panel = new CntAllPanel(dbId, viewId); + return panel.getConstructedPanel(); + } + + private String generatePieChartPanel(Long dbId, String tableName, String colName, PieChartConfigDto config) { + Long viewId = this.viewGeneratorService.genPieChartView(dbId, tableName, colName, config, this.token); + PieChartPanel panel = new PieChartPanel(dbId, viewId, colName, config); + return panel.getConstructedPanel(); + } + + private String generateTablePanel(Long dbId, Long tId, String tableName, Long size) { + TablePanel panel = new TablePanel(dbId, tId, tableName, size); + return panel.getConstructedPanel(); + } + + private String generateHistogramPanel(Long dbId, String tableName, String colName, HistogramConfigDto config) { + Long viewId = this.viewGeneratorService.genHistogramView(dbId, tableName, colName, this.token); + HistogramPanel panel = new HistogramPanel(dbId, viewId, colName, config); + return panel.getConstructedPanel(); + } + + private String generateStatsPanel(Long dbId, Long tId, String tableName) { + StatsPanel panel = new StatsPanel(dbId, tId, tableName); + return panel.getConstructedPanel(); + } + + private String generateTimeSeriesPanel(Long dbId, String tableName, String valueName, Map<String, String> timeMap, Long size) { + Long viewId = this.viewGeneratorService.genTimeSeriesView(dbId, tableName, timeMap, this.token); + TimeSeriesPanel panel = new TimeSeriesPanel(dbId, viewId, valueName, size); + return panel.getConstructedPanel(); + } + + private String generateMultiTimeSeriesPanel(Long dbId, String tableName, String timeCol, List<String> numValues) { + Long viewId = this.viewGeneratorService.genMultiTimeSeriesView(dbId, tableName, timeCol, numValues, this.token); + MultiTimeSeriesPanel panel = new MultiTimeSeriesPanel(dbId, viewId); + return panel.getConstructedPanel(); + } + + private boolean isNumericalColumn(ColumnTypeDto type) { + return switch (type) { + case TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, FLOAT, DOUBLE, DECIMAL -> true; + default -> false; + }; + } + + private boolean isStringColumn(ColumnTypeDto type) { + return switch (type) { + case CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT -> true; + default -> false; + }; + } + + private boolean isTimeStamp(ColumnTypeDto type) { + return switch (type) { + case TIMESTAMP -> true; + default -> false; + }; + } + + private void addDatasourceIfNotPresent() { + String jsonString = dataSourceService.getDatasource(); + ObjectMapper objectMapper = new ObjectMapper(); + try { + JsonNode rootNode = objectMapper.readTree(jsonString); + + if (rootNode.isArray()) { + for (JsonNode node : rootNode) { + if (node.has("uid") && node.get("uid").asText().equals(AbstractPanel.DATASRC_UID)) { + return; + } + } + } + + dataSourceService.addDatasource(); + } catch (Exception e) { + log.error("failed to read json of datasource"); + throw new JsonProcessingException("Failed to process datasource json"); + } + } + + private void addTimeSeriesPanel(Long dbId, Long tId, String tableName, List<ColumnDto> columns, + Map<Long, List<TimeSeriesDto>> timeSeriesMap, List<String> tablePanels) { + List<TimeSeriesDto> timeSeriesDtos = timeSeriesMap.get(tId); + + for (TimeSeriesDto timeSeriesDto : timeSeriesDtos) { + TimeDto timeDto = timeSeriesDto.getTimeDto(); + + Map<String, String> timeMap = new HashMap<>(); + String valueName = null; + if (timeDto != null) { + + for (var col : columns) { + Long colId = col.getId(); + String colName = col.getInternalName(); + + if (Objects.equals(timeDto.getYearColId(), colId)) { + timeMap.put(TIME_YEAR_COL, colName); + } else if (Objects.equals(timeDto.getMonthColId(), colId)) { + timeMap.put(TIME_MONTH_COL, colName); + } else if (Objects.equals(timeDto.getDayColId(), colId)) { + timeMap.put(TIME_DAY_COL, colName); + } else if (Objects.equals(timeDto.getHourColId(), colId)) { + timeMap.put(TIME_HOUR_COL, colName); + } else if (Objects.equals(timeDto.getMinuteColId(), colId)) { + timeMap.put(TIME_MIN_COL, colName); + } else if (Objects.equals(timeDto.getSecondColId(), colId)) { + timeMap.put(TIME_SECOND_COL, colName); + } else if (Objects.equals(timeSeriesDto.getValueColId(), colId)) { + valueName = colName; + timeMap.put(TIME_VAL_COL, valueName); + } + } + + if (!timeMap.isEmpty()) { + tablePanels.add(generateTimeSeriesPanel(dbId, tableName, valueName, timeMap, timeSeriesDto.getSize())); + } + } + } + } + + private String checkForSync(Long dbId) { + String path = String.format("/api/dashboards/uid/%d", dbId); + + ResponseEntity<String> responseEntity = null; + try { + responseEntity = grafanaRestTemplate.exchange( + path, + HttpMethod.GET, + null, + String.class + ); + + if (responseEntity.getStatusCode() == HttpStatus.OK) { + log.debug("dashboard with id {} already present", dbId); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = mapper.readTree(responseEntity.getBody()); + + return rootNode.get("meta").get("url").asText(); + } + } catch (RestClientException e) { + + if (e.getMessage().startsWith("404")) { + log.debug("dashboard with id {} not present", dbId); + return null; + } + + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.GET, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.GET, e); + throw new ResourceAccessException("Exception occurred"); + } + + return null; + } + + private String createDashboard(String dashboardJson) { + String path = "/api/dashboards/db"; + + HttpEntity<String> requestEntity = new HttpEntity<>(dashboardJson); + + try { + ResponseEntity<String> responseEntity = grafanaRestTemplate.exchange( + path, + HttpMethod.POST, + requestEntity, + String.class + ); + + ObjectMapper mapper = new ObjectMapper(); + String jsonString = responseEntity.getBody(); + JsonNode rootNode = mapper.readTree(jsonString); + + return rootNode.get("url").asText(); + + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + +} \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataServiceImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataServiceImpl.java new file mode 100644 index 0000000000..797483b042 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataServiceImpl.java @@ -0,0 +1,405 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.api.database.table.columns.ColumnStatisticDto; +import at.tuwien.panels.StatsPanel; +import at.tuwien.service.DataService; +import at.tuwien.service.TableService; +import lombok.extern.log4j.Log4j2; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static at.tuwien.panels.MultiTimeSeriesPanel.*; +import static at.tuwien.panels.PieChartPanel.VIEW_PIE_PERCENTAGE_COL; +import static at.tuwien.panels.TimeSeriesPanel.*; + +@Log4j2 +@Service +public class DataServiceImpl implements DataService { + private final RestTemplate dataRestTemplate; + private final TableService tableService; + private final RestTemplate grafanaRestTemplate; + + @Autowired + public DataServiceImpl(@Qualifier("dataServiceRestTemplate") RestTemplate dataRestTemplate, + @Qualifier("grafanaTemplate") RestTemplate grafanaRestTemplate, + TableService tableService) { + this.dataRestTemplate = dataRestTemplate; + this.grafanaRestTemplate = grafanaRestTemplate; + this.tableService = tableService; + } + + @Override + public Map<String, Object> getPieChartData(Long dbId, Long viewId, Long size) { + + Long page = 0L; + String path = String.format("/api/database/%d/view/%d/data?page=%d&size=%d", dbId, viewId, page, size); + + try { + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + QueryResultDto queryResultDto = responseEntity.getBody(); + assert queryResultDto != null; + + List<Map<String, Object>> res = queryResultDto.getResult(); + Map<String, Object> pieDataMap = new HashMap<>(); + double sum = 0; + + for (Map<String, Object> map : res) { + String key = null; + Object value = null; + + for (Map.Entry<String, Object> entry : map.entrySet()) { + if (!entry.getKey().equals(VIEW_PIE_PERCENTAGE_COL)) { // string column + key = (String) entry.getValue(); + } else { + value = entry.getValue(); + sum += (double) value; + } + } + + if (key != null && value != null) { + pieDataMap.put(key, value); + } + } + + pieDataMap.put("Others", 100 - sum); + return pieDataMap; + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public Map<String, Object> getCntAllData(Long dbId, Long viewId) { + + String path = String.format("/api/database/%d/view/%d/data", dbId, viewId); + + try { + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + QueryResultDto queryResultDto = responseEntity.getBody(); + assert queryResultDto != null; + return queryResultDto.getResult().get(0); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public List<Map<String, Object>> getTableData(Long dbId, Long tableId, Long size) { + return tableService.getTableData(dbId, tableId, size); + } + + @Override + public Map<String, List<Object>> getHistogramData(Long dbId, Long viewId, Long size) { + + Long page = 0L; + String path = String.format("/api/database/%d/view/%d/data?page=%d&size=%d", dbId, viewId, page, size); + + try { + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + QueryResultDto queryResultDto = responseEntity.getBody(); + assert queryResultDto != null; + + List<Map<String, Object>> resultMap = queryResultDto.getResult(); + List<Object> valueList = new ArrayList<>(); + + for (Map<String, Object> map : resultMap) { + if (!map.isEmpty()) { + valueList.add(map.entrySet().iterator().next().getValue()); + } + } + + return Map.of("values", valueList); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public List<Map<String, Object>> getStatsData(Long dbId, Long tableId) { + + String path = String.format("/api/database/%d/table/%d/statistic", dbId, tableId); + + try { + ResponseEntity<TableStatisticDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + TableStatisticDto.class + ); + TableStatisticDto columnStatisticDto = responseEntity.getBody(); + assert columnStatisticDto != null; + Map<String, ColumnStatisticDto> map = columnStatisticDto.getColumns(); + + map = map.entrySet().stream() + .filter(entry -> entry.getValue().getMin() != null) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + List<Map<String, Object>> res = new ArrayList<>(); + Map<String, Object> row; + for (Map.Entry<String, ColumnStatisticDto> entry : map.entrySet()) { + row = new HashMap<>(); + + row.put(StatsPanel.HEADER_COL, entry.getKey()); + row.put(StatsPanel.HEADER_MIN, entry.getValue().getMin()); + row.put(StatsPanel.HEADER_MAX, entry.getValue().getMax()); + row.put(StatsPanel.HEADER_AVG, entry.getValue().getMedian()); + row.put(StatsPanel.HEADER_STDDEV, entry.getValue().getStdDev()); + + res.add(row); + } + + return res; + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public Map<String, List<Map<String, Object>>> getTimeSeriesData(Long dbId, Long viewId, Long size) { + + Long page = 0L; + String path = String.format("/api/database/%d/view/%d/data?page=%d&size=%d", dbId, viewId, page, size); + + try { + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + QueryResultDto queryResultDto = responseEntity.getBody(); + assert queryResultDto != null; + + List<Map<String, Object>> resultMap = queryResultDto.getResult(); + + + Map<String, List<Map<String, Object>>> res = new HashMap<>(); + res.put("time_series", formatTimeData(resultMap)); + + return res; + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + public Map<String, List<Map<String, Object>>> getMultiTimeSeriesData(Long dbId, Long viewId, Long size) { + Long page = 0L; + String path = String.format("/api/database/%d/view/%d/data?page=%d&size=%d", dbId, viewId, page, size); + + try { + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + QueryResultDto queryResultDto = responseEntity.getBody(); + assert queryResultDto != null; + + List<Map<String, Object>> resultMap = queryResultDto.getResult(); + List<Map<String, Object>> timeMap = new ArrayList<>(); + + for (Map<String, Object> map : resultMap) { + Object time = map.get(VIEW_MULTI_TIMECOL); + + for (Map.Entry<String, Object> entry : map.entrySet()) { + Map<String, Object> multiTimeEntry = new HashMap<>(); + if (!entry.getKey().equals(VIEW_MULTI_TIMECOL)) { + multiTimeEntry.put(VIEW_MULTI_SELECTOR_NAME, entry.getKey()); + multiTimeEntry.put(VIEW_MULTI_SELECTOR_VALUE, entry.getValue()); + multiTimeEntry.put(VIEW_MULTI_SELECTOR_TIME, time); + + timeMap.add(multiTimeEntry); + } + } + } + Map<String, List<Map<String, Object>>> res = new HashMap<>(); + res.put("time_series", timeMap); + + return res; + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + private List<Map<String, Object>> formatTimeData(List<Map<String, Object>> resultMap) { + int year, month, day, hour, min, sec; + Object val; + + List<Map<String, Object>> timeValues = new ArrayList<>(); + Map<String, Object> timeValue; + + for (Map<String, Object> map : resultMap) { + year = 0; + month = 1; + day = 1; + hour = 0; + min = 0; + sec = 0; + val = null; + timeValue = new HashMap<>(); + + if(map.containsKey(TIME_YEAR_COL)) { + Object y = map.get(TIME_YEAR_COL); + if (y instanceof Integer) { + year = (int) y; + } + } + + if(map.containsKey(TIME_MONTH_COL)) { + Object m = map.get(TIME_MONTH_COL); + if (m instanceof String) { + month = getMonth(m.toString()); + } else if (m instanceof Integer) { + month = (int) m; + } + } + + if(map.containsKey(TIME_DAY_COL)) { + Object d = map.get(TIME_DAY_COL); + if (d instanceof Integer) { + day = (int) d; + } + } + + if(map.containsKey(TIME_HOUR_COL)) { + Object h = map.get(TIME_HOUR_COL); + if (h instanceof Integer) { + hour = (int) h; + } + } + + if(map.containsKey(TIME_MIN_COL)) { + Object m = map.get(TIME_MIN_COL); + if (m instanceof Integer) { + min = (int) m; + } + } + + if(map.containsKey(TIME_SECOND_COL)) { + Object s = map.get(TIME_SECOND_COL); + if (s instanceof Integer) { + sec = (int) s; + } + } + + if(map.containsKey(TIME_VAL_COL)) { + val = map.get(TIME_VAL_COL); + } + + timeValue.put("time", String.format("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec)); + timeValue.put("value", val); + timeValues.add(timeValue); + } + + return timeValues; + } + + private int getMonth(String month) { + return switch (month.toLowerCase()) { + case "february" -> 2; + case "march" -> 3; + case "april" -> 4; + case "may" -> 5; + case "june" -> 6; + case "july" -> 7; + case "august" -> 8; + case "september" -> 9; + case "october" -> 10; + case "november" -> 11; + case "december" -> 12; + default -> 1; + }; + } +} diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataSourceServiceImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataSourceServiceImpl.java new file mode 100644 index 0000000000..f4fde957b3 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/DataSourceServiceImpl.java @@ -0,0 +1,99 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.panels.AbstractPanel; +import at.tuwien.service.DataService; +import at.tuwien.service.DataSourceService; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.*; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; + +@Log4j2 +@Service +public class DataSourceServiceImpl implements DataSourceService { + + private final RestTemplate grafanaRestTemplate; + private String addDatasourceJSON = "{\n" + + " \"id\": null,\n" + + " \"uid\": \"" + AbstractPanel.DATASRC_UID + "\",\n" + + " \"name\": \"infinity datasource\",\n" + + " \"type\": \"yesoreyeram-infinity-datasource\",\n" + + " \"access\": \"proxy\"\n" + + "}"; + + @Autowired + public DataSourceServiceImpl(@Qualifier("grafanaTemplate") RestTemplate grafanaRestTemplate) { + this.grafanaRestTemplate = grafanaRestTemplate; + } + + @Override + public String addDatasource() { + String path = "/api/datasources"; + + HttpEntity<String> requestEntity = new HttpEntity<>(addDatasourceJSON); + + try { + ResponseEntity<String> responseEntity = grafanaRestTemplate.exchange( + path, + HttpMethod.POST, + requestEntity, + String.class + ); + return responseEntity.getBody(); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public String getDatasource() { + String path = "/api/datasources"; + + try { + ResponseEntity<String> responseEntity = grafanaRestTemplate.exchange( + path, + HttpMethod.GET, + null, + String.class + ); + + return responseEntity.getBody(); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + +} \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/TableServiceImpl.java new file mode 100644 index 0000000000..a3c8fc8622 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -0,0 +1,121 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.TableBriefDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.service.TableService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.*; +import org.springframework.web.util.UriComponentsBuilder; + +import java.util.*; + +@Log4j2 +@Service +public class TableServiceImpl implements TableService { + private final RestTemplate dataRestTemplate; + private final RestTemplate metaDataRestTemplate; + + @Autowired + public TableServiceImpl(@Qualifier("dataServiceRestTemplate") RestTemplate dataRestTemplate, + @Qualifier("metaDataServiceRestTemplate") RestTemplate metaDataRestTemplate) { + this.dataRestTemplate = dataRestTemplate; + this.metaDataRestTemplate = metaDataRestTemplate; + } + + @Override + public List<TableBriefDto> getAllTables(Long dbId) { + String path = String.format("/api/database/%d/table", dbId); + + try { + ResponseEntity<List<TableBriefDto>> responseEntity = metaDataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + new ParameterizedTypeReference<List<TableBriefDto>>() {} + ); + return responseEntity.getBody(); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + + @Override + public TableDto getTableSchemas(Long dbId, Long tId) { + String path = String.format("/api/database/%d/table/%d", dbId, tId); + try { + ResponseEntity<TableDto> responseEntity = metaDataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + TableDto.class + ); + + return responseEntity.getBody(); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + + @Override + public List<Map<String, Object>> getTableData(Long dbId, Long tId, Long size) { + Long page = 0L; + String path = String.format("/api/database/%d/table/%d/data?page=%d&size=%d", dbId, tId, page, size); + + try { + // Send GET request with query parameters + ResponseEntity<QueryResultDto> responseEntity = dataRestTemplate.exchange( + path, + HttpMethod.GET, + null, + QueryResultDto.class + ); + + QueryResultDto responseBody = responseEntity.getBody(); + + return responseBody.getResult(); + + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + +} \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/ViewGeneratorServiceImpl.java b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/ViewGeneratorServiceImpl.java new file mode 100644 index 0000000000..baa258460c --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/java/at/tuwien/service/impl/ViewGeneratorServiceImpl.java @@ -0,0 +1,225 @@ +package at.tuwien.service.impl; + +import at.tuwien.api.database.ViewBriefDto; +import at.tuwien.api.database.ViewCreateDto; +import at.tuwien.dto.PieChartConfigDto; +import at.tuwien.panels.StatsPanel; +import at.tuwien.service.ViewGeneratorService; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.text.StringSubstitutor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static at.tuwien.panels.MultiTimeSeriesPanel.VIEW_MULTI_TIMECOL; +import static at.tuwien.panels.PieChartPanel.VIEW_PIE_PERCENTAGE_COL; +import static at.tuwien.panels.TimeSeriesPanel.TIME_VAL_COL; + +@Log4j2 +@Service +public class ViewGeneratorServiceImpl implements ViewGeneratorService { + + private final RestTemplate metaDataRestTemplate; + private static final String PIE_DEFAULT_LIMIT = "10"; + private static final String PIE_DEFAULT_DEC_PLACE = "2"; + + @Autowired + public ViewGeneratorServiceImpl(@Qualifier("metaDataServiceRestTemplate") RestTemplate metaDataRestTemplate) { + this.metaDataRestTemplate = metaDataRestTemplate; + } + + @Override + public Long genCntAllView(Long dbId, String tableName, String token) { + final String query = String.format("select count(*) from %s", tableName); + + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_cntAll_%s", dbId, tableName)); + viewCreateDto.setQuery(query); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + @Override + public Long genPieChartView(Long dbId, String tableName, String colName, PieChartConfigDto config, String token) { + Map<String, String> valueMap = new HashMap<>(); + valueMap.put("col_name", colName); + valueMap.put("table_name", tableName); + valueMap.put("limit", (config != null && config.getLimit() != null) ? config.getLimit() : PIE_DEFAULT_LIMIT); + valueMap.put("dec_place", (config != null && config.getDecimalPlace() != null) ? config.getDecimalPlace() : PIE_DEFAULT_DEC_PLACE); + valueMap.put("percentage", VIEW_PIE_PERCENTAGE_COL); + + final String templateQuery = + "SELECT\n" + + " ${col_name},\n" + + " ROUND( (COUNT(*) / total_count) * 100, ${dec_place}) AS ${percentage}\n" + + " FROM\n" + + " ${table_name},\n" + + " (SELECT COUNT(*) AS total_count FROM ${table_name}) AS t\n" + + " GROUP BY\n" + + " ${col_name}\n" + + " ORDER BY\n" + + " ${percentage} DESC\n" + + " LIMIT ${limit}"; + + StringSubstitutor sub = new StringSubstitutor(valueMap); + + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_piechart_%s_%s", dbId, tableName, colName)); + viewCreateDto.setQuery(sub.replace(templateQuery)); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + @Override + public Long genHistogramView(Long dbId, String tableName, String colName, String token) { + final String query = String.format("select %s from %s", colName, tableName); + + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_histogram_%s_%s", dbId, tableName, colName)); + viewCreateDto.setQuery(query); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + @Override + public Long genStatisticsView(Long dbId, String tableName, String colName, String token) { + Map<String, String> valueMap = new HashMap<>(); + valueMap.put("col_name", colName); + valueMap.put("table_name", tableName); + valueMap.put("header_col", StatsPanel.HEADER_COL); + valueMap.put("header_min", StatsPanel.HEADER_MIN); + valueMap.put("header_max", StatsPanel.HEADER_MAX); + valueMap.put("header_avg", StatsPanel.HEADER_AVG); + valueMap.put("header_stddev", StatsPanel.HEADER_STDDEV); + + final String templateQuery = "select " + + "min(${col_name}) as ${header_min}, " + + "max(${col_name}) as ${header_max}, " + + "avg(${col_name}) as ${header_avg}, " + + "STDDEV(${col_name}) as ${header_stddev} " + + "from ${table_name}"; + + StringSubstitutor sub = new StringSubstitutor(valueMap); + + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_statschart_%s_%s", dbId, tableName, colName)); + viewCreateDto.setQuery(sub.replace(templateQuery)); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + @Override + public Long genTimeSeriesView(Long dbId, String tableName, Map<String, String> timeMap, String token) { + + List<String> colNames = new ArrayList<>(); + for (Map.Entry<String, String> entry : timeMap.entrySet()) { + colNames.add(String.format("%s AS %s", entry.getValue(), entry.getKey())); + } + + final String query = String.format("select %s from %s", String.join(",", colNames), tableName); + + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_timeseries_%s_%s", dbId, tableName, timeMap.get(TIME_VAL_COL))); + viewCreateDto.setQuery(query); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + @Override + public Long genMultiTimeSeriesView(Long dbId, String tableName, String timeCol, List<String> numValues, String token) { + + final String query = String.format("select %s AS %s, %s from %s", timeCol, VIEW_MULTI_TIMECOL, String.join(",", numValues), tableName); + ViewCreateDto viewCreateDto = new ViewCreateDto(); + viewCreateDto.setName(String.format("%d_multitimeseries_%s_%s", dbId, tableName, timeCol)); + viewCreateDto.setQuery(query); + viewCreateDto.setIsPublic(true); + + ViewBriefDto createdView = createView(dbId, viewCreateDto, token); + if (createdView == null) { + log.warn("failed to create view {}", viewCreateDto); + return -1L; + } + + return createdView.getId(); + } + + + private ViewBriefDto createView(Long dbId, ViewCreateDto viewCreateDto, String token) { + String path = String.format("/api/database/%d/view", dbId); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", token); + headers.set("Content-Type", "application/json"); + + HttpEntity<ViewCreateDto> requestEntity = new HttpEntity<>(viewCreateDto, headers); + + try { + ResponseEntity<ViewBriefDto> responseEntity = metaDataRestTemplate.exchange( + path, + HttpMethod.POST, + requestEntity, + ViewBriefDto.class + ); + + return responseEntity.getBody(); + } catch (ResourceAccessException e) { + log.error("Resource access error for accessing URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Resource access error occurred"); + } catch (RestClientException e) { + log.error("RestClient Exception occurred URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("RestClient Exception occurred"); + } catch (Exception e) { + log.error("Exception occurred, URL: {}, Exception message: {}, Request method: {}, Stack Trace: {}", + path, e.getMessage(), HttpMethod.POST, e); + throw new ResourceAccessException("Exception occurred"); + } + } + +} \ No newline at end of file diff --git a/dbrepo-grafana-service/rest-service/src/main/resources/application-local.yml b/dbrepo-grafana-service/rest-service/src/main/resources/application-local.yml new file mode 100644 index 0000000000..8e99c2d0a9 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/resources/application-local.yml @@ -0,0 +1,89 @@ +application: + title: DBRepo + version: '@project.version@' +spring: + datasource: + url: jdbc:h2:mem:fda;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS FDA;NON_KEYWORDS=value + driver-class-name: org.h2.Driver + username: sa + password: password + rabbitmq: + host: "${BROKER_HOST:broker-service}" + virtual-host: "${BROKER_VIRTUALHOST:dbrepo}" + password: "${BROKER_PASSWORD:fda}" + username: "${BROKER_USERNAME:fda}" + port: ${BROKER_PORT:5672} + jpa: + show-sql: false + database-platform: org.hibernate.dialect.H2Dialect + open-in-view: false + properties: + hibernate: + default_schema: fda + jdbc: + time_zone: UTC + application: + name: grafana-service + main: + banner-mode: off +management: + endpoints: + web: + exposure: + include: health,info,prometheus + endpoint: + health: + probes: + enabled: true + health: + readinessState: + enabled: true + livenessState: + enabled: true +server: + port: 1880 +logging: + pattern.console: "%d %highlight(%-5level) %msg%n" + level: + root: debug + at.tuwien.: "${LOG_LEVEL:info}" + org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug +dbrepo: + endpoints: + grafana: http://grafana:3000 + dataService: http://data-service:8080 + gatewayService: "${GATEWAY_SERVICE_ENDPOINT:http://gateway-service}" + storageService: "${S3_ENDPOINT:http://storage-service:9000}" + authService: "${AUTH_SERVICE_HOST:http://auth-service:8080}" + s3: + accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}" + secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}" + importBucket: "${S3_IMPORT_BUCKET:dbrepo-upload}" + exportBucket: "${S3_EXPORT_BUCKET:dbrepo-download}" + filePath: "${S3_FILE_PATH:/tmp}" + admin: + username: "${ADMIN_USERNAME:admin}" + password: "${ADMIN_PASSWORD:admin}" + jwt: + public_key: "${JWT_PUBKEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" + keycloak: + username: "${AUTH_SERVICE_ADMIN:fda}" + password: "${AUTH_SERVICE_ADMIN_PASSWORD:fda}" + client: "${AUTH_SERVICE_CLIENT:dbrepo-client}" + clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}" + sql: + forbidden: "${NOT_SUPPORTED_KEYWORDS:\\*,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,--}" + grant: + default: + read: "${GRANT_DEFAULT_READ:SELECT}" + write: "${GRANT_DEFAULT_WRITE:SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" + minConcurrent: "${MIN_CONCURRENT_CONSUMERS:2}" + maxConcurrent: "${MAX_CONCURRENT_CONSUMERS:6}" + requeueRejected: ${REQUEUE_REJECTED:false} + queueName: "${BROKER_QUEUE_NAME:dbrepo}" + exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}" + routingKey: "${BROKER_ROUTING_KEY:#}" + connectionTimeout: ${CONNECTION_TIMEOUT:10000} + defaultDateFormatId: "${DEFAULT_DATE_FORMAT_ID:3}" + defaultTimeFormatId: "${DEFAULT_TIME_FORMAT_ID:4}" + defaultTimestampFormatId: "${DEFAULT_TIMESTAMP_FORMAT_ID:1}" diff --git a/dbrepo-grafana-service/rest-service/src/main/resources/application.yml b/dbrepo-grafana-service/rest-service/src/main/resources/application.yml new file mode 100644 index 0000000000..b8fcf710c7 --- /dev/null +++ b/dbrepo-grafana-service/rest-service/src/main/resources/application.yml @@ -0,0 +1,107 @@ +application: + title: DBRepo + version: '@project.version@' + baseurl: ${BASE_URL:http://localhost} +spring: + datasource: + url: jdbc:h2:mem:fda;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS FDA;NON_KEYWORDS=value + driver-class-name: org.h2.Driver + username: sa + password: password + rabbitmq: + host: "${BROKER_HOST:broker-service}" + virtual-host: "${BROKER_VIRTUALHOST:dbrepo}" + password: "${BROKER_PASSWORD:fda}" + username: "${BROKER_USERNAME:fda}" + port: ${BROKER_PORT:5672} + jpa: + show-sql: false + database-platform: org.hibernate.dialect.H2Dialect + open-in-view: false + properties: + hibernate: + default_schema: fda + jdbc: + time_zone: UTC + application: + name: grafana-service + main: + banner-mode: off + data: + redis: + host: redis + port: 6379 +management: + endpoints: + web: + exposure: + include: health,info,prometheus + endpoint: + health: + probes: + enabled: true + health: + readinessState: + enabled: true + livenessState: + enabled: true +server: + port: 8080 +logging: + pattern.console: "%d %highlight(%-5level) %msg%n" + level: + root: warn + at.tuwien.: "${LOG_LEVEL:info}" + org: + springframework: + web: + client: + RestTemplate: DEBUG + org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug +dbrepo: + endpoints: + grafana: http://grafana:3000 + grafanaPort: 3000 + grafanaService: http://grafana-service:8080 + dataService: http://data-service:8080 + metadataService: http://metadata-service:8080 + gatewayService: "${GATEWAY_SERVICE_ENDPOINT:http://gateway-service}" + storageService: "${S3_ENDPOINT:http://storage-service:9000}" + authService: "${AUTH_SERVICE_HOST:http://auth-service:8080}" + s3: + accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}" + secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}" + importBucket: "${S3_IMPORT_BUCKET:dbrepo-upload}" + exportBucket: "${S3_EXPORT_BUCKET:dbrepo-download}" + filePath: "${S3_FILE_PATH:/tmp}" + admin: + username: "${ADMIN_USERNAME:kper}" + password: "${ADMIN_PASSWORD:k1a1r1l1o1}" + jwt: + public_key: "${JWT_PUBKEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" + keycloak: + username: "${AUTH_SERVICE_ADMIN:fda}" + password: "${AUTH_SERVICE_ADMIN_PASSWORD:fda}" + client: "${AUTH_SERVICE_CLIENT:dbrepo-client}" + clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}" + grafana: + username: "${GRAFANA_USERNAME:admin}" + password: "${GRAFANA_PASSWORD:admin}" + default_refreshrate: 0 + sql: + forbidden: "${NOT_SUPPORTED_KEYWORDS:\\*,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,--}" + grant: + default: + read: "${GRANT_DEFAULT_READ:SELECT}" + write: "${GRANT_DEFAULT_WRITE:SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" + minConcurrent: "${MIN_CONCURRENT_CONSUMERS:2}" + maxConcurrent: "${MAX_CONCURRENT_CONSUMERS:6}" + requeueRejected: ${REQUEUE_REJECTED:false} + queueName: "${BROKER_QUEUE_NAME:dbrepo}" + exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}" + routingKey: "${BROKER_ROUTING_KEY:#}" + connectionTimeout: ${CONNECTION_TIMEOUT:10000} + defaultDateFormatId: "${DEFAULT_DATE_FORMAT_ID:3}" + defaultTimeFormatId: "${DEFAULT_TIME_FORMAT_ID:4}" + defaultTimestampFormatId: "${DEFAULT_TIMESTAMP_FORMAT_ID:1}" + diff --git a/dbrepo-search-service/init/omlib/__init__.py b/dbrepo-grafana-service/rest-service/src/test/resources/application.properties similarity index 100% rename from dbrepo-search-service/init/omlib/__init__.py rename to dbrepo-grafana-service/rest-service/src/test/resources/application.properties diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 7e7978cad8..4ba9d70b17 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -52,6 +52,8 @@ CREATE TABLE IF NOT EXISTS `mdb_containers` privileged_username VARCHAR(255) NOT NULL, privileged_password VARCHAR(255) NOT NULL, quota INT, + readonly_username VARCHAR(255) NOT NULL, + readonly_password VARCHAR(255) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`image_id`) REFERENCES mdb_images (`id`) ) WITH SYSTEM VERSIONING; @@ -67,20 +69,22 @@ CREATE TABLE IF NOT EXISTS `mdb_licenses` CREATE TABLE IF NOT EXISTS `mdb_databases` ( - id VARCHAR(36) NOT NULL DEFAULT UUID(), - cid VARCHAR(36) NOT NULL, - name VARCHAR(255) NOT NULL, - internal_name VARCHAR(255) NOT NULL, - exchange_name VARCHAR(255) NOT NULL, - description TEXT, - engine VARCHAR(20), - is_public BOOLEAN NOT NULL DEFAULT TRUE, - is_schema_public BOOLEAN NOT NULL DEFAULT TRUE, - image LONGBLOB, - owned_by VARCHAR(36) NOT NULL, - contact_person VARCHAR(36) NOT NULL, - created TIMESTAMP NOT NULL DEFAULT NOW(), - last_modified TIMESTAMP, + id VARCHAR(36) NOT NULL DEFAULT UUID(), + cid VARCHAR(36) NOT NULL, + grafana_dashboard_uid character varying(255), + name VARCHAR(255) NOT NULL, + internal_name VARCHAR(255) NOT NULL, + exchange_name VARCHAR(255) NOT NULL, + description TEXT, + engine VARCHAR(20), + is_public BOOLEAN NOT NULL DEFAULT TRUE, + is_schema_public BOOLEAN NOT NULL DEFAULT TRUE, + is_dashboard_enabled BOOLEAN NOT NULL DEFAULT TRUE, + image LONGBLOB, + owned_by VARCHAR(36) NOT NULL, + contact_person VARCHAR(36) NOT NULL, + created TIMESTAMP NOT NULL DEFAULT NOW(), + last_modified TIMESTAMP, PRIMARY KEY (`id`), FOREIGN KEY (`cid`) REFERENCES mdb_containers (`id`), FOREIGN KEY (`owned_by`) REFERENCES mdb_users (`id`), @@ -291,7 +295,7 @@ CREATE TABLE IF NOT EXISTS `mdb_messages` type ENUM ('ERROR', 'WARNING', 'INFO') NOT NULL DEFAULT 'INFO', message TEXT NOT NULL, link TEXT NULL, - link_TEXT VARCHAR(255) NULL, + link_text VARCHAR(255) NULL, display_start TIMESTAMP NULL, display_end TIMESTAMP NULL, PRIMARY KEY (`id`) diff --git a/dbrepo-metadata-db/2_setup-data.sql b/dbrepo-metadata-db/2_setup-data.sql index dc4917cd8b..611efbbde1 100644 --- a/dbrepo-metadata-db/2_setup-data.sql +++ b/dbrepo-metadata-db/2_setup-data.sql @@ -1,8 +1,8 @@ BEGIN; INSERT INTO `mdb_containers` (id, name, internal_name, image_id, host, port, ui_host, ui_port, privileged_username, - privileged_password) + privileged_password, readonly_username, readonly_password) VALUES ('6cfb3b8e-1792-4e46-871a-f3d103527203', 'mariadb:11.1.3-debian-11-r6', 'mariadb_11_1_3', - 'd79cb089-363c-488b-9717-649e44d8fcc5', 'data-db', 3306, 'localhost', 3306, 'root', 'dbrepo'); + 'd79cb089-363c-488b-9717-649e44d8fcc5', 'data-db', 3306, 'localhost', 3306, 'root', 'dbrepo', 'user', 'user'); COMMIT; diff --git a/dbrepo-metadata-service/Dockerfile b/dbrepo-metadata-service/Dockerfile index fa92b799ee..8d01865d85 100644 --- a/dbrepo-metadata-service/Dockerfile +++ b/dbrepo-metadata-service/Dockerfile @@ -1,32 +1,27 @@ ###### FIRST STAGE ###### +FROM dbrepo-core:build AS dependency +LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" + +###### SECOND STAGE ###### FROM maven:3-amazoncorretto-17 AS build LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" COPY ./pom.xml ./ -COPY ./api/pom.xml ./api/ -COPY ./entities/pom.xml ./entities/ -COPY ./oai/pom.xml ./oai/ -COPY ./report/pom.xml ./report/ -COPY ./repositories/pom.xml ./repositories/ -COPY ./rest-service/pom.xml ./rest-service/ -COPY ./services/pom.xml ./services/ -COPY ./test/pom.xml ./test/ - -RUN mvn dependency:go-offline - -COPY ./api ./api -COPY ./entities ./entities + +RUN mvn -fn dependency:go-offline + +COPY --from=dependency /root/.m2/repository/at/ac/tuwien/ifs/dbrepo /root/.m2/repository/at/ac/tuwien/ifs/dbrepo + COPY ./oai ./oai COPY ./report ./report COPY ./repositories ./repositories COPY ./rest-service ./rest-service COPY ./services ./services -COPY ./test ./test # Make sure it compiles -RUN mvn clean install -DskipTests +RUN mvn -fn clean package -DskipTests -###### SECOND STAGE ###### +###### THIRD STAGE ###### FROM amazoncorretto:17-alpine3.19 AS runtime LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" @@ -34,6 +29,8 @@ RUN apk add --no-cache curl bash jq WORKDIR /app +RUN adduser -D dbrepo --uid 1001 + USER 1001 COPY --from=build --chown=1001 ./rest-service/target/dbrepo-metadata-service-rest-service-*.jar ./metadata-service.jar @@ -41,4 +38,6 @@ COPY --from=build --chown=1001 ./rest-service/target/dbrepo-metadata-service-res # non-root port EXPOSE 8080 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./metadata-service.jar"] +ENV JAVA_OPTS="-Dlog4j2.formatMsgNoLookups=true" + +ENTRYPOINT exec java $JAVA_OPTS -jar ./metadata-service.jar \ No newline at end of file diff --git a/dbrepo-metadata-service/api/pom.xml b/dbrepo-metadata-service/api/pom.xml deleted file mode 100644 index 96b717f3aa..0000000000 --- a/dbrepo-metadata-service/api/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service</artifactId> - <version>1.7.3</version> - </parent> - - <artifactId>dbrepo-metadata-service-api</artifactId> - <name>dbrepo-metadata-service-api</name> - <version>1.7.3</version> - - <dependencies> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>1.7.3</version> - <scope>compile</scope> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>${java.version}</source> - <target>${java.version}</target> - <annotationProcessorPaths> - <path> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </path> - </annotationProcessorPaths> - </configuration> - </plugin> - </plugins> - </build> - -</project> \ No newline at end of file diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java deleted file mode 100644 index f883a034f5..0000000000 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated; - -public enum OrcidDisambiguatedSourceTypeDto { - RINGGOLD, - ROR -} diff --git a/dbrepo-metadata-service/entities/pom.xml b/dbrepo-metadata-service/entities/pom.xml deleted file mode 100644 index 0140b73477..0000000000 --- a/dbrepo-metadata-service/entities/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service</artifactId> - <version>1.7.3</version> - </parent> - - <artifactId>dbrepo-metadata-service-entities</artifactId> - <name>dbrepo-metadata-service-entity</name> - <version>1.7.3</version> - - <dependencies/> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>${java.version}</source> - <target>${java.version}</target> - <annotationProcessorPaths> - <path> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </path> - </annotationProcessorPaths> - </configuration> - </plugin> - </plugins> - </build> - -</project> \ No newline at end of file diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameType.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameType.java deleted file mode 100644 index 5f0790fbab..0000000000 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameType.java +++ /dev/null @@ -1,9 +0,0 @@ -package at.tuwien.entities.identifier; - -import lombok.Getter; - -@Getter -public enum NameType { - PERSONAL, - ORGANIZATIONAL; -} diff --git a/dbrepo-metadata-service/oai/pom.xml b/dbrepo-metadata-service/oai/pom.xml index 3fcbaa59bd..d075e57506 100644 --- a/dbrepo-metadata-service/oai/pom.xml +++ b/dbrepo-metadata-service/oai/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-oai</artifactId> <name>dbrepo-metadata-service-oai</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies/> diff --git a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiErrorType.java b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiErrorType.java similarity index 91% rename from dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiErrorType.java rename to dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiErrorType.java index 2fe750a9ad..e2a13d7762 100644 --- a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiErrorType.java +++ b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiErrorType.java @@ -1,4 +1,4 @@ -package at.tuwien.oaipmh; +package at.ac.tuwien.ifs.dbrepo.oaipmh; import lombok.Getter; @@ -14,8 +14,8 @@ public enum OaiErrorType { BAD_RESUMPTION_TOKEN("badResumptionToken", "The value of the resumptionToken argument is invalid or expired."), BAD_ARGUMENT("badArgument", "The request includes illegal arguments, is missing required arguments, includes a repeated argument, or values for arguments have an illegal syntax."); - private String errorCode; - private String errorText; + private final String errorCode; + private final String errorText; OaiErrorType(String errorCode, String errorText) { this.errorCode = errorCode; diff --git a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListIdentifiersParameters.java b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListIdentifiersParameters.java similarity index 97% rename from dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListIdentifiersParameters.java rename to dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListIdentifiersParameters.java index 721175ed17..d55f1b994f 100644 --- a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListIdentifiersParameters.java +++ b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListIdentifiersParameters.java @@ -1,4 +1,4 @@ -package at.tuwien.oaipmh; +package at.ac.tuwien.ifs.dbrepo.oaipmh; import lombok.*; import org.apache.commons.lang3.StringUtils; diff --git a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListRecordsParameters.java b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListRecordsParameters.java similarity index 97% rename from dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListRecordsParameters.java rename to dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListRecordsParameters.java index a18f0b0aec..b7eb9ce37e 100644 --- a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiListRecordsParameters.java +++ b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiListRecordsParameters.java @@ -1,4 +1,4 @@ -package at.tuwien.oaipmh; +package at.ac.tuwien.ifs.dbrepo.oaipmh; import lombok.*; import org.apache.commons.lang3.StringUtils; diff --git a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiRecordParameters.java b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiRecordParameters.java similarity index 93% rename from dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiRecordParameters.java rename to dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiRecordParameters.java index da0433c0b6..3b24e111dd 100644 --- a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/OaiRecordParameters.java +++ b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/OaiRecordParameters.java @@ -1,4 +1,4 @@ -package at.tuwien.oaipmh; +package at.ac.tuwien.ifs.dbrepo.oaipmh; import lombok.*; diff --git a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/RequestParameters.java b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/RequestParameters.java similarity index 90% rename from dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/RequestParameters.java rename to dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/RequestParameters.java index 3f3d9f1a04..1af3449b1e 100644 --- a/dbrepo-metadata-service/oai/src/main/java/at/tuwien/oaipmh/RequestParameters.java +++ b/dbrepo-metadata-service/oai/src/main/java/at/ac/tuwien/ifs/dbrepo/oaipmh/RequestParameters.java @@ -1,4 +1,4 @@ -package at.tuwien.oaipmh; +package at.ac.tuwien.ifs.dbrepo.oaipmh; import org.apache.commons.lang3.StringUtils; diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index 65f8f7333b..df4596e8ea 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -16,23 +16,20 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> <name>dbrepo-metadata-service</name> - <version>1.7.3</version> + <version>1.8.0</version> <description>Service that manages the metadata</description> <packaging>pom</packaging> <modules> - <module>api</module> - <module>entities</module> <module>oai</module> - <module>test</module> <module>repositories</module> <module>services</module> <module>rest-service</module> <module>report</module> </modules> - <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/</url> + <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/</url> <developers> <developer> <name>Martin Weise</name> @@ -43,10 +40,8 @@ <properties> <java.version>17</java.version> - <spring-cloud.version>4.1.4</spring-cloud.version> - <mapstruct.version>1.5.5.Final</mapstruct.version> + <mapstruct.version>1.6.3</mapstruct.version> <rabbitmq.version>5.20.0</rabbitmq.version> - <jackson-datatype.version>2.15.0</jackson-datatype.version> <commons-io.version>2.17.0</commons-io.version> <commons-validator.version>1.8.0</commons-validator.version> <guava.version>33.0.0-jre</guava.version> @@ -57,8 +52,6 @@ <apache-jena.version>4.10.0</apache-jena.version> <opencsv.version>5.7.1</opencsv.version> <super-csv.version>2.4.0</super-csv.version> - <keycloak.version>26.0.4</keycloak.version> - <springdoc-openapi.version>2.3.0</springdoc-openapi.version> <testcontainers.version>1.19.1</testcontainers.version> <jackson.version>2.15.2</jackson.version> <keycloak-testcontainer.version>3.2.0</keycloak-testcontainer.version> @@ -73,44 +66,9 @@ <dependencies> <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-validation</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-security</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.security</groupId> - <artifactId>spring-security-test</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.springframework.cloud</groupId> - <artifactId>spring-cloud-starter-bootstrap</artifactId> - <version>${spring-cloud.version}</version> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-thymeleaf</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - </dependency> - <!-- Open API --> - <dependency> - <groupId>org.springdoc</groupId> - <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> - <version>${springdoc-openapi.version}</version> + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> + <version>1.8.0</version> </dependency> <!-- Data Source --> <dependency> @@ -150,12 +108,6 @@ <version>${micrometer.version}</version> <scope>test</scope> </dependency> - <!-- IDE --> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <scope>compile</scope> - </dependency> <!-- Mapping --> <dependency> <groupId>org.mapstruct</groupId> @@ -168,11 +120,6 @@ <artifactId>mapstruct</artifactId> <version>${mapstruct.version}</version> </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-jsr310</artifactId> - <version>${jackson-datatype.version}</version> - </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> @@ -183,22 +130,7 @@ <artifactId>commons-validator</artifactId> <version>${commons-validator.version}</version> </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-hibernate6</artifactId> - <version>${jackson-datatype.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.auth0</groupId> <artifactId>java-jwt</artifactId> @@ -236,6 +168,11 @@ <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> diff --git a/dbrepo-metadata-service/report/pom.xml b/dbrepo-metadata-service/report/pom.xml index ed1592ddaa..114d9d1cbd 100644 --- a/dbrepo-metadata-service/report/pom.xml +++ b/dbrepo-metadata-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-report</artifactId> <name>dbrepo-metadata-service-report</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/pom.xml b/dbrepo-metadata-service/repositories/pom.xml index b2e76ac0d7..3bc1da72f5 100644 --- a/dbrepo-metadata-service/repositories/pom.xml +++ b/dbrepo-metadata-service/repositories/pom.xml @@ -6,17 +6,17 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-repositories</artifactId> <name>dbrepo-metadata-service-repositories</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-api</artifactId> + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> <version>${project.version}</version> </dependency> <dependency> @@ -24,37 +24,7 @@ <artifactId>dbrepo-metadata-service-oai</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>${project.version}</version> - </dependency> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>${java.version}</source> - <target>${java.version}</target> - <annotationProcessorPaths> - <path> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </path> - <!-- keep this order https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together#answer-65021876 --> - <path> - <groupId>org.mapstruct</groupId> - <artifactId>mapstruct-processor</artifactId> - <version>${mapstruct.version}</version> - </path> - </annotationProcessorPaths> - </configuration> - </plugin> - </plugins> - </build> + </dependencies> </project> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/SparqlMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/SparqlMapper.java similarity index 97% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/SparqlMapper.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/SparqlMapper.java index dff867970f..2ca00f05db 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/SparqlMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/SparqlMapper.java @@ -1,6 +1,6 @@ -package at.tuwien.mapper; +package at.ac.tuwien.ifs.dbrepo.mapper; -import at.tuwien.entities.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; import org.mapstruct.Mapper; import java.util.List; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/BannerMessageRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/BannerMessageRepository.java similarity index 72% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/BannerMessageRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/BannerMessageRepository.java index c12dc7b83f..655b530bb6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/BannerMessageRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/BannerMessageRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ConceptRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ConceptRepository.java similarity index 71% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ConceptRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ConceptRepository.java index 1e70cfdfb2..546243b1ac 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ConceptRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ConceptRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ContainerRepository.java similarity index 81% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ContainerRepository.java index 536802cf41..9d258ed781 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ContainerRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/DatabaseRepository.java similarity index 87% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/DatabaseRepository.java index d984cb3337..2d61108679 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/DatabaseRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/IdentifierRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/IdentifierRepository.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/IdentifierRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/IdentifierRepository.java index 9e49f2aa1c..4011a8d168 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/IdentifierRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/IdentifierRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ImageRepository.java similarity index 77% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ImageRepository.java index 6282ed9040..55af367a63 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ImageRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ImageRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/LicenseRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/LicenseRepository.java similarity index 73% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/LicenseRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/LicenseRepository.java index f180cdf901..e04b1ffb7e 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/LicenseRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/LicenseRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.License; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/OntologyRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/OntologyRepository.java similarity index 78% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/OntologyRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/OntologyRepository.java index 69b4e204be..35460fc050 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/OntologyRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/OntologyRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/TableRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/TableRepository.java similarity index 69% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/TableRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/TableRepository.java index bc126eaa27..e6d3670101 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/TableRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/TableRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UnitRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UnitRepository.java similarity index 71% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UnitRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UnitRepository.java index 6676410730..ed4c6c778c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UnitRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UnitRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UserRepository.java similarity index 80% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UserRepository.java index 30f2f20c16..f270810ac1 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/UserRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.user.User; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ViewRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ViewRepository.java similarity index 71% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ViewRepository.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ViewRepository.java index 50544822e5..d35ed6e337 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ViewRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/ViewRepository.java @@ -1,6 +1,6 @@ -package at.tuwien.repository; +package at.ac.tuwien.ifs.dbrepo.repository; -import at.tuwien.entities.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/EnumToStringConverter.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/utils/EnumToStringConverter.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/EnumToStringConverter.java rename to dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/utils/EnumToStringConverter.java index 2e53ae6cdc..158d5be808 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/EnumToStringConverter.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/utils/EnumToStringConverter.java @@ -1,4 +1,4 @@ -package at.tuwien.utils; +package at.ac.tuwien.ifs.dbrepo.utils; import org.mapstruct.TargetType; diff --git a/dbrepo-metadata-service/rest-service/pom.xml b/dbrepo-metadata-service/rest-service/pom.xml index d8021b4c10..ed5cacbdeb 100644 --- a/dbrepo-metadata-service/rest-service/pom.xml +++ b/dbrepo-metadata-service/rest-service/pom.xml @@ -6,22 +6,17 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-rest-service</artifactId> <name>dbrepo-metadata-service-rest</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-api</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-entities</artifactId> + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> <version>${project.version}</version> </dependency> <dependency> @@ -29,11 +24,6 @@ <artifactId>dbrepo-metadata-service-services</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-test</artifactId> - <version>${project.version}</version> - </dependency> </dependencies> <build> diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/DbrepoMetadataServiceApplication.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/MetadataServiceApplication.java similarity index 64% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/DbrepoMetadataServiceApplication.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/MetadataServiceApplication.java index e931ce7509..de133ba720 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/DbrepoMetadataServiceApplication.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/MetadataServiceApplication.java @@ -1,4 +1,4 @@ -package at.tuwien; +package at.ac.tuwien.ifs.dbrepo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -9,13 +9,13 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableJpaAuditing @EnableTransactionManagement -@EntityScan(basePackages = {"at.tuwien.entities"}) -@EnableJpaRepositories(basePackages = {"at.tuwien.repository"}) +@EntityScan(basePackages = {"at.ac.tuwien.ifs.dbrepo.core.entity"}) +@EnableJpaRepositories(basePackages = {"at.ac.tuwien.ifs.dbrepo.repository"}) @SpringBootApplication -public class DbrepoMetadataServiceApplication { +public class MetadataServiceApplication { public static void main(String[] args) { - SpringApplication.run(DbrepoMetadataServiceApplication.class, args); + SpringApplication.run(MetadataServiceApplication.class, args); } } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/MvcConfig.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MvcConfig.java similarity index 71% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/MvcConfig.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MvcConfig.java index 6bdb809731..70ed7ea611 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/MvcConfig.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MvcConfig.java @@ -1,7 +1,7 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.converters.IdentifierStatusTypeDtoConverter; -import at.tuwien.converters.IdentifierTypeDtoConverter; +import at.ac.tuwien.ifs.dbrepo.converters.IdentifierStatusTypeDtoConverter; +import at.ac.tuwien.ifs.dbrepo.converters.IdentifierTypeDtoConverter; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SwaggerConfig.java similarity index 98% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SwaggerConfig.java index 7830213b8e..21881faa1f 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SwaggerConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.OpenAPI; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierStatusTypeDtoConverter.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverter.java similarity index 75% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierStatusTypeDtoConverter.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverter.java index 96e67f63d2..cb59169cfd 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierStatusTypeDtoConverter.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverter.java @@ -1,6 +1,6 @@ -package at.tuwien.converters; +package at.ac.tuwien.ifs.dbrepo.converters; -import at.tuwien.api.identifier.IdentifierStatusTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierStatusTypeDto; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierTypeDtoConverter.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverter.java similarity index 75% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierTypeDtoConverter.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverter.java index 61e169604f..6c0fc163bd 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/converters/IdentifierTypeDtoConverter.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverter.java @@ -1,6 +1,6 @@ -package at.tuwien.converters; +package at.ac.tuwien.ifs.dbrepo.converters; -import at.tuwien.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpoint.java new file mode 100644 index 0000000000..b6f5f65cf9 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpoint.java @@ -0,0 +1,136 @@ +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDetailsDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.exception.NotAllowedException; +import lombok.extern.log4j.Log4j2; +import org.springframework.security.core.Authentication; + +import java.security.Principal; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Log4j2 +public abstract class AbstractEndpoint { + + public boolean hasRole(Principal principal, String role) { + if (principal == null || role == null) { + return false; + } + final Authentication authentication = (Authentication) principal; + return authentication.getAuthorities() + .stream() + .anyMatch(a -> a.getAuthority().equals(role)); + } + + public boolean isSystem(Principal principal) { + if (principal == null) { + return false; + } + final Authentication authentication = (Authentication) principal; + return authentication.getAuthorities() + .stream() + .anyMatch(a -> a.getAuthority().equals("system")); + } + + public UUID getId(Principal principal) { + if (principal == null) { + return null; + } + final Authentication authentication = (Authentication) principal; + if (authentication.getPrincipal() instanceof UserDetailsDto user) { + if (user.getId() == null) { + throw new IllegalArgumentException("Principal has no id"); + } + return UUID.fromString(user.getId()); + } + throw new IllegalArgumentException("Unknown principal instance: " + authentication.getPrincipal().getClass()); + } + + public void removeInternalData(ContainerDto container) { + container.setPassword(null); + container.setUsername(null); + container.setHost(null); + container.setPort(null); + } + + public Database filterDatabase(Database database, Principal principal) throws NotAllowedException { + if (principal != null) { + if (isSystem(principal)) { + log.trace("filter database: system principal, skip"); + return database; + } + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getUser().getId().equals(getId(principal))) + .findFirst(); + if (!database.getIsPublic() && !database.getIsSchemaPublic() && optional.isEmpty()) { + log.error("Failed to find database: not public and no access found"); + throw new NotAllowedException("Failed to find database: not public and no access found"); + } + /* reduce metadata */ + if (!database.getOwner().getId().equals(getId(principal))) { + log.trace("authenticated user is not owner: remove access list"); + database.setAccesses(List.of()); + } + final int tables = database.getTables() + .size(); + database.setTables(database.getTables() + .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent()) + .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()) + .toList()); + log.trace("filtered database views from {} to {}", views, database.getViews().size()); + return database; + } + if (!database.getIsPublic() && !database.getIsSchemaPublic()) { + log.error("Failed to find database: not public and not authenticated"); + throw new NotAllowedException("Failed to find database: not public and not authenticated"); + } + /* reduce metadata */ + database.getTables() + .removeAll(database.getTables() + .stream() + .filter(t -> !t.getIsPublic() && !t.getIsSchemaPublic()) + .toList()); + database.getViews() + .removeAll(database.getViews() + .stream() + .filter(v -> !v.getIsPublic() && !v.getIsSchemaPublic()) + .toList()); + database.setAccesses(List.of()); + return database; + } + + public List<View> filterViews(Database database, Principal principal) { + final List<View> views = database.getViews(); + DatabaseAccess access = null; + if (principal != null) { + if (isSystem(principal)) { + return views; + } + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getHdbid().equals(getId(principal))) + .findFirst(); + if (optional.isPresent()) { + access = optional.get(); + } + } + final Boolean hasAccess = access != null; + return views.stream() + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || hasAccess) + .toList(); + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpoint.java similarity index 89% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpoint.java index 79dc5fd8e9..db425fe839 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpoint.java @@ -1,16 +1,17 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.CreateAccessDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.AccessService; +import at.ac.tuwien.ifs.dbrepo.service.DashboardService; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.service.UserService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -40,14 +41,16 @@ public class AccessEndpoint extends AbstractEndpoint { private final AccessService accessService; private final MetadataMapper metadataMapper; private final DatabaseService databaseService; + private final DashboardService dashboardService; @Autowired public AccessEndpoint(UserService userService, AccessService accessService, MetadataMapper metadataMapper, - DatabaseService databaseService) { + DatabaseService databaseService, DashboardService dashboardService) { this.userService = userService; this.accessService = accessService; this.metadataMapper = metadataMapper; this.databaseService = databaseService; + this.dashboardService = dashboardService; } @PostMapping("/{userId}") @@ -92,9 +95,10 @@ public class AccessEndpoint extends AbstractEndpoint { public ResponseEntity<DatabaseAccessDto> create(@NotNull @PathVariable("databaseId") UUID databaseId, @PathVariable("userId") UUID userId, @Valid @RequestBody CreateAccessDto data, - @NotNull Principal principal) throws NotAllowedException, DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, - SearchServiceException, SearchServiceConnectionException { + @NotNull Principal principal) throws NotAllowedException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, + AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { log.debug("endpoint give access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, data.getType()); final Database database = databaseService.findById(databaseId); @@ -111,6 +115,7 @@ public class AccessEndpoint extends AbstractEndpoint { /* ignore */ } accessService.create(database, user, data.getType()); + dashboardService.updateAccess(database, user, data.getType()); return ResponseEntity.accepted() .build(); } @@ -156,7 +161,8 @@ public class AccessEndpoint extends AbstractEndpoint { @Valid @RequestBody CreateAccessDto data, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, - AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { + AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { log.debug("endpoint modify database access, databaseId={}, userId={}, access.type={}, principal.name={}", databaseId, userId, data.getType(), principal.getName()); final Database database = databaseService.findById(databaseId); @@ -170,11 +176,12 @@ public class AccessEndpoint extends AbstractEndpoint { } final User user = userService.findById(userId); if (user.getIsInternal()) { - log.error("Failed to update access: the internal user must have write-all access"); - throw new NotAllowedException("Failed to update access: the internal user must have write-all access"); + log.error("Failed to update access: cannot modify access of internal users"); + throw new NotAllowedException("Failed to update access: cannot modify access of internal users"); } accessService.find(database, user); accessService.update(database, user, data.getType()); + dashboardService.updateAccess(database, user, data.getType()); return ResponseEntity.accepted() .build(); } @@ -262,7 +269,8 @@ public class AccessEndpoint extends AbstractEndpoint { @PathVariable("userId") UUID userId, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint revoke database access, databaseId={}, userId={}", databaseId, userId); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { @@ -280,6 +288,7 @@ public class AccessEndpoint extends AbstractEndpoint { } accessService.find(database, user); accessService.delete(database, user); + dashboardService.updateAccess(database, user, null); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpoint.java similarity index 90% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpoint.java index acf6a31ca2..11b2d8ea0c 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpoint.java @@ -1,8 +1,8 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.table.columns.concepts.ConceptDto; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.ConceptService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ConceptDto; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.ConceptService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpoint.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpoint.java index 266430372d..d98901f535 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpoint.java @@ -1,15 +1,15 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.container.ContainerBriefDto; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.entities.container.Container; -import at.tuwien.exception.ContainerAlreadyExistsException; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.ContainerService; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.ContainerService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; 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/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpoint.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpoint.java index 9eadffd0df..41d2801209 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/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpoint.java @@ -1,17 +1,14 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.*; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.ContainerService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.StorageService; -import at.tuwien.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.*; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.*; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -35,7 +32,6 @@ import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.util.List; -import java.util.Optional; import java.util.UUID; @Log4j2 @@ -49,15 +45,18 @@ public class DatabaseEndpoint extends AbstractEndpoint { private final StorageService storageService; private final DatabaseService databaseService; private final ContainerService containerService; + private final DashboardService dashboardService; @Autowired public DatabaseEndpoint(UserService userService, MetadataMapper metadataMapper, StorageService storageService, - DatabaseService databaseService, ContainerService containerService) { + DatabaseService databaseService, ContainerService containerService, + DashboardService dashboardService) { this.userService = userService; this.metadataMapper = metadataMapper; this.storageService = storageService; this.databaseService = databaseService; this.containerService = containerService; + this.dashboardService = dashboardService; } @RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}) @@ -167,7 +166,7 @@ public class DatabaseEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, - ContainerQuotaException { + ContainerQuotaException, DashboardServiceException, DashboardServiceConnectionException { log.debug("endpoint create database, data.name={}", data.getName()); final Container container = containerService.find(data.getCid()); if (container.getQuota() != null && container.getDatabases().size() + 1 > container.getQuota()) { @@ -175,9 +174,12 @@ public class DatabaseEndpoint extends AbstractEndpoint { throw new ContainerQuotaException("Failed to create database: quota of " + container.getQuota() + " exceeded"); } final User caller = userService.findById(getId(principal)); + final Database database = databaseService.create(container, data, caller, userService.findAllInternalUsers()); + /* find in dashboard service */ + final CreateDashboardResponseDto dashboard = dashboardService.create(database); + database.setDashboardUid(dashboard.getUid()); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.databaseDtoToDatabaseBriefDto(metadataMapper.databaseToDatabaseDto( - databaseService.create(container, data, caller, userService.findAllInternalUsers())))); + .body(metadataMapper.databaseToDatabaseBriefDto(database)); } @PutMapping("/{databaseId}/metadata/table") @@ -222,8 +224,7 @@ public class DatabaseEndpoint extends AbstractEndpoint { public ResponseEntity<DatabaseBriefDto> refreshTableMetadata(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull Principal principal) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, MalformedException, - TableNotFoundException { + SearchServiceConnectionException, NotAllowedException, MalformedException, TableNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { @@ -271,7 +272,7 @@ public class DatabaseEndpoint extends AbstractEndpoint { public ResponseEntity<DatabaseBriefDto> refreshViewMetadata(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull Principal principal) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, ViewNotFoundException { + SearchServiceConnectionException, NotAllowedException, ViewNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}, principal.name={}", databaseId, principal.getName()); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { @@ -324,13 +325,16 @@ public class DatabaseEndpoint extends AbstractEndpoint { public ResponseEntity<DatabaseBriefDto> visibility(@NotNull @PathVariable("databaseId") UUID databaseId, @Valid @RequestBody DatabaseModifyVisibilityDto data, @NotNull Principal principal) throws DatabaseNotFoundException, - NotAllowedException, SearchServiceException, SearchServiceConnectionException, UserNotFoundException { + NotAllowedException, SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint modify database visibility, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to modify database visibility: not owner"); throw new NotAllowedException("Failed to modify database visibility: not owner"); } + final Database database1 = databaseService.modifyVisibility(database, data); + dashboardService.update(database1); return ResponseEntity.accepted() .body(metadataMapper.databaseDtoToDatabaseBriefDto(metadataMapper.databaseToDatabaseDto( databaseService.modifyVisibility(database, data)))); @@ -451,6 +455,50 @@ public class DatabaseEndpoint extends AbstractEndpoint { databaseService.modifyImage(database, image)))); } + @PutMapping("/{databaseId}/dashboard") + @Transactional + @PreAuthorize("hasAuthority('system')") + @Observed(name = "dbrepo_database_dashboard") + @Operation(summary = "Update database dashboard uid", + description = "Updates the dashboard uid for a database with given id. Only the database owner can perform this operation. Requires role `system`.", + security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "202", + description = "Modify of dashboard uid was successful", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = DatabaseBriefDto.class))}), + @ApiResponse(responseCode = "400", + description = "Malformed payload", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Database could not be found", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}) + }) + public ResponseEntity<DatabaseBriefDto> modifyDashboard(@NotNull @PathVariable("databaseId") UUID databaseId, + @Valid @RequestBody DatabaseModifyDashboardDto data) + throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { + log.debug("endpoint modify database dashboard uid, databaseId={}, data.uid={}", databaseId, data.getUid()); + final Database database = databaseService.findById(databaseId); + return ResponseEntity.accepted() + .body(metadataMapper.databaseDtoToDatabaseBriefDto(metadataMapper.databaseToDatabaseDto( + databaseService.modifyDashboard(database, data.getUid())))); + } + @GetMapping("/{databaseId}/image") @Transactional @Observed(name = "dbrepo_database_image_view") @@ -504,54 +552,7 @@ public class DatabaseEndpoint extends AbstractEndpoint { Principal principal) throws DatabaseNotFoundException, NotAllowedException { log.debug("endpoint find database, databaseId={}", databaseId); - final Database database = databaseService.findById(databaseId); - if (principal != null) { - final Optional<DatabaseAccess> optional = database.getAccesses() - .stream() - .filter(a -> a.getUser().getId().equals(getId(principal))) - .findFirst(); - optional.ifPresentOrElse(access -> log.trace("user has access: {}", access), () -> log.trace("user has no access")); - if (!database.getIsPublic() && !database.getIsSchemaPublic() && optional.isEmpty() && !isSystem(principal)) { - log.error("Failed to find database: not public and no access found"); - throw new NotAllowedException("Failed to find database: not public and no access found"); - } - /* reduce metadata */ - final int tables = database.getTables() - .size(); - database.setTables(database.getTables() - .stream() - .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() || isSystem(principal)) - .toList()); - log.trace("filtered database views from {} to {}", views, database.getViews().size()); - if (!isSystem(principal) && !database.getOwner().getId().equals(getId(principal))) { - log.trace("authenticated user {} is not owner: remove access list", principal.getName()); - database.setAccesses(List.of()); - } - } else { - if (!database.getIsPublic() && !database.getIsSchemaPublic()) { - log.error("Failed to find database: not public and not authenticated"); - throw new NotAllowedException("Failed to find database: not public and not authenticated"); - } - /* reduce metadata */ - database.getTables() - .removeAll(database.getTables() - .stream() - .filter(t -> !t.getIsPublic() && !t.getIsSchemaPublic()) - .toList()); - database.getViews() - .removeAll(database.getViews() - .stream() - .filter(v -> !v.getIsPublic() && !v.getIsSchemaPublic()) - .toList()); - database.setAccesses(List.of()); - } + final Database database = filterDatabase(databaseService.findById(databaseId), principal); final DatabaseDto dto = metadataMapper.databaseToDatabaseDto(database); final HttpHeaders headers = new HttpHeaders(); if (isSystem(principal)) { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpoint.java similarity index 97% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpoint.java index 96deaea775..cf44837a27 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpoint.java @@ -1,19 +1,19 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.identifier.*; -import at.tuwien.api.identifier.ld.LdDatasetDto; -import at.tuwien.api.user.external.ExternalMetadataDto; -import at.tuwien.config.EndpointConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierStatusType; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.*; -import at.tuwien.validation.EndpointValidator; +import at.ac.tuwien.ifs.dbrepo.config.EndpointConfig; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld.LdDatasetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalMetadataDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierStatusType; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.*; +import at.ac.tuwien.ifs.dbrepo.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpoint.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpoint.java index 62c00d1ee8..cc2dbff7b8 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpoint.java @@ -1,16 +1,16 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.container.image.ImageBriefDto; -import at.tuwien.api.container.image.ImageChangeDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.api.container.image.ImageDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.ImageService; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageChangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.ImageService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpoint.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpoint.java index 18d5e93ca2..f82127b86a 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpoint.java @@ -1,8 +1,8 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.LicenseDto; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.LicenseService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LicenseDto; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.LicenseService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpoint.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpoint.java index 656279a86d..6d6f3c8591 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpoint.java @@ -1,14 +1,14 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.maintenance.BannerMessageBriefDto; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.exception.MessageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.BannerMessageService; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.exception.MessageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.BannerMessageService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpoint.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpoint.java index 8a36471816..4916ed8612 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpoint.java @@ -1,10 +1,10 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.exception.IdentifierNotFoundException; -import at.tuwien.oaipmh.OaiErrorType; -import at.tuwien.oaipmh.OaiListIdentifiersParameters; -import at.tuwien.oaipmh.OaiRecordParameters; -import at.tuwien.service.MetadataService; +import at.ac.tuwien.ifs.dbrepo.core.exception.IdentifierNotFoundException; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiErrorType; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiListIdentifiersParameters; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiRecordParameters; +import at.ac.tuwien.ifs.dbrepo.service.MetadataService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpoint.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpoint.java index c723568556..b69e723308 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpoint.java @@ -1,15 +1,15 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.semantics.*; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.FilterBadRequestException; -import at.tuwien.exception.MalformedException; -import at.tuwien.exception.OntologyNotFoundException; -import at.tuwien.exception.UriMalformedException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.EntityService; -import at.tuwien.service.OntologyService; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.exception.FilterBadRequestException; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.OntologyNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UriMalformedException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.EntityService; +import at.ac.tuwien.ifs.dbrepo.service.OntologyService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; 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/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java similarity index 89% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java index f04f66eb8e..67c23e9bc3 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/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java @@ -1,20 +1,21 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.database.table.columns.ColumnDto; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.*; -import at.tuwien.validation.EndpointValidator; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.TableColumnEntityDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.*; +import at.ac.tuwien.ifs.dbrepo.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -35,6 +36,7 @@ import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -47,21 +49,21 @@ public class TableEndpoint extends AbstractEndpoint { private final UserService userService; private final TableService tableService; private final EntityService entityService; - private final AccessService accessService; private final MetadataMapper metadataMapper; private final DatabaseService databaseService; + private final DashboardService dashboardService; private final EndpointValidator endpointValidator; @Autowired public TableEndpoint(UserService userService, TableService tableService, EntityService entityService, - AccessService accessService, MetadataMapper metadataMapper, DatabaseService databaseService, - EndpointValidator endpointValidator) { + MetadataMapper metadataMapper, DatabaseService databaseService, + DashboardService dashboardService, EndpointValidator endpointValidator) { this.userService = userService; this.tableService = tableService; this.entityService = entityService; - this.accessService = accessService; this.metadataMapper = metadataMapper; this.databaseService = databaseService; + this.dashboardService = dashboardService; this.endpointValidator = endpointValidator; } @@ -95,13 +97,33 @@ public class TableEndpoint extends AbstractEndpoint { final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); endpointValidator.validateOnlyPrivateSchemaHasRole(database, principal, "list-tables"); - return ResponseEntity.ok(database.getTables() + return ResponseEntity.ok(filterTables(database, principal) .stream() - .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || (principal != null && isSystem(principal))) .map(metadataMapper::tableToTableBriefDto) .collect(Collectors.toList())); } + public List<Table> filterTables(Database database, Principal principal) { + final List<Table> tables = database.getTables(); + DatabaseAccess access = null; + if (principal != null) { + if (isSystem(principal)) { + return tables; + } + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getHdbid().equals(getId(principal))) + .findFirst(); + if (optional.isPresent()) { + access = optional.get(); + } + } + final Boolean hasAccess = access != null; + return tables.stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || hasAccess) + .toList(); + } + @GetMapping("/{tableId}/suggest") @Transactional(readOnly = true) @PreAuthorize("hasAuthority('table-semantic-analyse')") @@ -362,15 +384,17 @@ public class TableEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws NotAllowedException, MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, - SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException, + DashboardServiceException, DashboardServiceConnectionException { log.debug("endpoint create table, databaseId={}, data.name={}, principal.name={}", databaseId, data.getName(), principal.getName()); final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyAccess(database, principal, true); endpointValidator.validateColumnCreateConstraints(data); + final Table table = tableService.createTable(database, data, principal); + dashboardService.update(table.getDatabase()); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.tableToTableBriefDto( - tableService.createTable(database, data, principal))); + .body(metadataMapper.tableToTableBriefDto(table)); } @PutMapping("/{tableId}") @@ -417,7 +441,8 @@ public class TableEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody TableUpdateDto data, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint update table, databaseId={}, data.is_public={}, data.is_schema_public={}, principal.name={}", databaseId, data.getIsPublic(), data.getIsSchemaPublic(), principal.getName()); final Database database = databaseService.findById(databaseId); @@ -426,9 +451,10 @@ public class TableEndpoint extends AbstractEndpoint { log.error("Failed to update table: not owner"); throw new NotAllowedException("Failed to update table: not owner"); } + final Table table1 = tableService.updateTable(table, data); + dashboardService.update(table1.getDatabase()); return ResponseEntity.accepted() - .body(metadataMapper.tableToTableBriefDto( - tableService.updateTable(table, data))); + .body(metadataMapper.tableToTableBriefDto(table1)); } @GetMapping("/{tableId}") @@ -461,28 +487,23 @@ public class TableEndpoint extends AbstractEndpoint { log.debug("endpoint find table, databaseId={}, tableId={}", databaseId, tableId); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - boolean isOwner = false; if (principal != null) { - isOwner = table.getOwner().getId().equals(getId(principal)); - if (!table.getIsSchemaPublic()) { - try { - accessService.find(table.getDatabase(), userService.findById(getId(principal))); - } catch (UserNotFoundException | AccessNotFoundException e) { - if (!isOwner && !isSystem(principal)) { - log.error("Failed to find table with id {}: private and no access permission", table); - throw new NotAllowedException("Failed to find table with id " + tableId + ": private and no access permission"); - } - } + if (isSystem(principal)) { + return ResponseEntity.ok(metadataMapper.tableToTableDto(table)); + } + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getHuserid().equals(getId(principal))) + .findFirst(); + if (table.getIsPublic() || table.getIsSchemaPublic() || optional.isPresent()) { + return ResponseEntity.ok(metadataMapper.tableToTableDto(table)); } } - if (!table.getIsSchemaPublic() && !isOwner && !isSystem(principal)) { - log.debug("remove schema from table: {}.{}", database.getInternalName(), table.getInternalName()); - table.setColumns(List.of()); - table.setConstraints(null); + if (!table.getIsPublic() && !table.getIsSchemaPublic()) { + log.error("Failed to find table: not public and no access found"); + throw new NotAllowedException("Failed to find table: not public and no access found"); } - final TableDto dto = metadataMapper.tableToTableDto(table); - return ResponseEntity.ok() - .body(dto); + return ResponseEntity.ok(metadataMapper.tableToTableDto(table)); } @DeleteMapping("/{tableId}") @@ -525,7 +546,8 @@ public class TableEndpoint extends AbstractEndpoint { @NotNull @PathVariable("tableId") UUID tableId, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint delete table, databaseId={}, tableId={}, principal.name={}", databaseId, tableId, principal.getName()); final Database database = databaseService.findById(databaseId); @@ -542,6 +564,7 @@ public class TableEndpoint extends AbstractEndpoint { } /* delete table */ tableService.deleteTable(table); + dashboardService.update(databaseService.findById(databaseId)); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpoint.java similarity index 90% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpoint.java index 45aef3645b..a0f5630c7a 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpoint.java @@ -1,8 +1,8 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.database.table.columns.concepts.UnitDto; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.UnitService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.UnitDto; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.UnitService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpoint.java similarity index 93% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpoint.java index 8f3e15529e..996ba610f0 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpoint.java @@ -1,16 +1,16 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.api.auth.CreateUserDto; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.NotAllowedException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.CreateUserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.NotAllowedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.UserService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; 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/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpoint.java similarity index 85% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpoint.java index 2cc187c884..99d7d2a12d 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/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpoint.java @@ -1,18 +1,19 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -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; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.UserService; -import at.tuwien.service.ViewService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.service.DashboardService; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.service.UserService; +import at.ac.tuwien.ifs.dbrepo.service.ViewService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -33,6 +34,7 @@ import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -46,14 +48,16 @@ public class ViewEndpoint extends AbstractEndpoint { private final ViewService viewService; private final MetadataMapper metadataMapper; private final DatabaseService databaseService; + private final DashboardService dashboardService; @Autowired public ViewEndpoint(UserService userService, ViewService viewService, MetadataMapper metadataMapper, - DatabaseService databaseService) { + DatabaseService databaseService, DashboardService dashboardService) { this.userService = userService; this.viewService = viewService; this.metadataMapper = metadataMapper; this.databaseService = databaseService; + this.dashboardService = dashboardService; } @GetMapping @@ -79,13 +83,7 @@ public class ViewEndpoint extends AbstractEndpoint { DatabaseNotFoundException { log.debug("endpoint find all views, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User caller; - if (principal != null) { - caller = userService.findById(getId(principal)); - } else { - caller = null; - } - return ResponseEntity.ok(viewService.findAll(database, caller) + return ResponseEntity.ok(filterViews(database, principal) .stream() .map(metadataMapper::viewToViewBriefDto) .collect(Collectors.toList())); @@ -145,7 +143,7 @@ public class ViewEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws NotAllowedException, MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, - ImageNotFoundException, ViewExistsException { + ImageNotFoundException, ViewExistsException, DashboardServiceException, DashboardServiceConnectionException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { @@ -156,9 +154,10 @@ public class ViewEndpoint extends AbstractEndpoint { log.error("Failed to create view: name exists"); throw new ViewExistsException("Failed to create view: name exists"); } + final View view = viewService.create(database, userService.findById(getId(principal)), data); + dashboardService.update(view.getDatabase()); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.viewToViewBriefDto( - viewService.create(database, userService.findById(getId(principal)), data))); + .body(metadataMapper.viewToViewBriefDto(view)); } @GetMapping("/{viewId}") @@ -187,12 +186,27 @@ public class ViewEndpoint extends AbstractEndpoint { public ResponseEntity<ViewDto> find(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull @PathVariable("viewId") UUID viewId, Principal principal) throws DatabaseNotFoundException, - ViewNotFoundException { + ViewNotFoundException, NotAllowedException { log.debug("endpoint find view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); - return ResponseEntity.status(HttpStatus.OK) - .body(metadataMapper.viewToViewDto(view)); + if (principal != null) { + if (isSystem(principal)) { + return ResponseEntity.ok(metadataMapper.viewToViewDto(view)); + } + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getHuserid().equals(getId(principal))) + .findFirst(); + if (view.getIsPublic() || view.getIsSchemaPublic() || optional.isPresent()) { + return ResponseEntity.ok(metadataMapper.viewToViewDto(view)); + } + } + if (!view.getIsPublic() && !view.getIsSchemaPublic()) { + log.error("Failed to find view: not public and no access found"); + throw new NotAllowedException("Failed to find view: not public and no access found"); + } + return ResponseEntity.ok(metadataMapper.viewToViewDto(view)); } @DeleteMapping("/{viewId}") @@ -240,7 +254,8 @@ public class ViewEndpoint extends AbstractEndpoint { @NotNull @PathVariable("viewId") UUID viewId, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException, UserNotFoundException { + SearchServiceConnectionException, UserNotFoundException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { @@ -249,6 +264,7 @@ public class ViewEndpoint extends AbstractEndpoint { } final View view = viewService.findById(database, viewId); viewService.delete(view); + dashboardService.update(databaseService.findById(databaseId)); return ResponseEntity.accepted() .build(); } @@ -294,7 +310,8 @@ public class ViewEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody ViewUpdateDto data, @NotNull Principal principal) throws NotAllowedException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException, UserNotFoundException { + SearchServiceConnectionException, UserNotFoundException, DashboardServiceException, + DashboardServiceConnectionException { log.debug("endpoint update view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); @@ -302,9 +319,10 @@ public class ViewEndpoint extends AbstractEndpoint { log.error("Failed to update view: not the database- or view owner"); throw new NotAllowedException("Failed to update view: not the database- or view owner"); } + final View view1 = viewService.update(view, data); + dashboardService.update(view1.getDatabase()); return ResponseEntity.accepted() - .body(metadataMapper.viewToViewBriefDto( - viewService.update(database, view, data))); + .body(metadataMapper.viewToViewBriefDto(view1)); } } 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/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandler.java similarity index 96% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandler.java index eadce489d9..0d4a617001 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/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandler.java @@ -1,7 +1,7 @@ -package at.tuwien.handlers; +package at.ac.tuwien.ifs.dbrepo.handlers; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import com.auth0.jwt.exceptions.TokenExpiredException; import io.swagger.v3.oas.annotations.Hidden; import jakarta.ws.rs.NotAuthorizedException; @@ -130,6 +130,20 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_GATEWAY) + @ExceptionHandler(DashboardServiceConnectionException.class) + public ResponseEntity<ApiErrorDto> handle(DashboardServiceConnectionException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(DashboardServiceException.class) + public ResponseEntity<ApiErrorDto> handle(DashboardServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(DatabaseMalformedException.class) diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/validation/EndpointValidator.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/validation/EndpointValidator.java index 6fe29c118b..8068a8d734 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/validation/EndpointValidator.java @@ -1,19 +1,19 @@ -package at.tuwien.validation; +package at.ac.tuwien.ifs.dbrepo.validation; -import at.tuwien.SortType; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.identifier.IdentifierSaveDto; -import at.tuwien.endpoints.AbstractEndpoint; -import at.tuwien.entities.database.AccessType; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.AccessService; -import at.tuwien.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.SortType; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto; +import at.ac.tuwien.ifs.dbrepo.endpoints.AbstractEndpoint; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.AccessType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.service.AccessService; +import at.ac.tuwien.ifs.dbrepo.service.UserService; import lombok.extern.log4j.Log4j2; import org.apache.commons.validator.GenericValidator; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java deleted file mode 100644 index 7ec1471f4d..0000000000 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java +++ /dev/null @@ -1,53 +0,0 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.user.UserDetailsDto; -import org.springframework.security.core.Authentication; - -import java.security.Principal; -import java.util.UUID; - -public abstract class AbstractEndpoint { - - public boolean hasRole(Principal principal, String role) { - if (principal == null || role == null) { - return false; - } - final Authentication authentication = (Authentication) principal; - return authentication.getAuthorities() - .stream() - .anyMatch(a -> a.getAuthority().equals(role)); - } - - public boolean isSystem(Principal principal) { - if (principal == null) { - return false; - } - final Authentication authentication = (Authentication) principal; - return authentication.getAuthorities() - .stream() - .anyMatch(a -> a.getAuthority().equals("system")); - } - - public UUID getId(Principal principal) { - if (principal == null) { - return null; - } - final Authentication authentication = (Authentication) principal; - if (authentication.getPrincipal() instanceof UserDetailsDto user) { - if (user.getId() == null) { - throw new IllegalArgumentException("Principal has no id"); - } - return UUID.fromString(user.getId()); - } - throw new IllegalArgumentException("Unknown principal instance: " + authentication.getPrincipal().getClass()); - } - - public void removeInternalData(ContainerDto container) { - container.setPassword(null); - container.setUsername(null); - container.setHost(null); - container.setPort(null); - } - -} diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml index 5bde7a292b..134ee20451 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml @@ -55,13 +55,14 @@ dbrepo: password: "${DATACITE_PASSWORD}" endpoints: analyseService: "${ANALYSE_SERVICE_ENDPOINT:http://analyse-service:8080}" - searchService: "${SEARCH_SERVICE_ENDPOINT:http://search-service:8080}" - dataService: "${DATA_SERVICE_ENDPOINT:http://data-service:8080}" - brokerService: "${BROKER_SERVICE_ENDPOINT:http://broker-service:15672}" authService: "${AUTH_SERVICE_ENDPOINT:http://auth-service:8080}" - storageService: "${S3_ENDPOINT:http://storage-service:9000}" - rorService: "${ROR_ENDPOINT:https://api.ror.org}" + brokerService: "${BROKER_SERVICE_ENDPOINT:http://broker-service:15672}" crossRefService: "${CROSSREF_ENDPOINT:http://data.crossref.org}" + dashboardService: "${DASHBOARD_SERVICE_ENDPOINT:http://dashboard-service:8080}" + dataService: "${DATA_SERVICE_ENDPOINT:http://data-service:8080}" + rorService: "${ROR_ENDPOINT:https://api.ror.org}" + searchService: "${SEARCH_SERVICE_ENDPOINT:http://search-service:8080}" + storageService: "${S3_ENDPOINT:http://storage-service:9000}" s3: accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}" secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}" diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/ApplicationIntegrationTest.java similarity index 86% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/ApplicationIntegrationTest.java index 33c7bc76c5..30b82efb1f 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/ApplicationIntegrationTest.java @@ -1,4 +1,4 @@ -package at.tuwien; +package at.ac.tuwien.ifs.dbrepo; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; @@ -17,7 +17,7 @@ public class ApplicationIntegrationTest { public void main_succeeds() { /* test */ - DbrepoMetadataServiceApplication.main(new String[]{}); + MetadataServiceApplication.main(new String[]{}); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/ObjectMapperConfig.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/ObjectMapperConfig.java similarity index 95% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/ObjectMapperConfig.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/ObjectMapperConfig.java index 6cbf682c8d..508540f52a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/ObjectMapperConfig.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/ObjectMapperConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java index f8a83baf85..3dddb8cf33 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java @@ -1,6 +1,6 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.Getter; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Value; @@ -11,6 +11,8 @@ import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; +import java.io.IOException; + @Getter @Log4j2 @Configuration diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierStatusTypeDtoConverterUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverterUnitTest.java similarity index 75% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierStatusTypeDtoConverterUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverterUnitTest.java index 8c7316b3d1..20f1f615eb 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierStatusTypeDtoConverterUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierStatusTypeDtoConverterUnitTest.java @@ -1,28 +1,24 @@ -package at.tuwien.converters; +package at.ac.tuwien.ifs.dbrepo.converters; -import at.tuwien.api.identifier.IdentifierStatusTypeDto; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierStatusTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @Log4j2 @SpringBootTest -public class IdentifierStatusTypeDtoConverterUnitTest extends AbstractUnitTest { +public class IdentifierStatusTypeDtoConverterUnitTest extends BaseTest { @Autowired private IdentifierStatusTypeDtoConverter identifierStatusTypeDtoConverter; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void identifierStatusTypeDtoConverter_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeDtoConverterUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverterUnitTest.java similarity index 75% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeDtoConverterUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverterUnitTest.java index 98abd668d8..1d73cc3445 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeDtoConverterUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/converters/IdentifierTypeDtoConverterUnitTest.java @@ -1,28 +1,24 @@ -package at.tuwien.converters; +package at.ac.tuwien.ifs.dbrepo.converters; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @Log4j2 @SpringBootTest -public class IdentifierTypeDtoConverterUnitTest extends AbstractUnitTest { +public class IdentifierTypeDtoConverterUnitTest extends BaseTest { @Autowired private IdentifierTypeDtoConverter identifierTypeDtoConverter; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void IdentifierTypeDtoConverter_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AbstractEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpointUnitTest.java similarity index 56% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AbstractEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpointUnitTest.java index dfa4924957..52ffe690fa 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AbstractEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AbstractEndpointUnitTest.java @@ -1,53 +1,27 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.user.UserDetailsDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.UserService; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDetailsDto; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.test.context.support.WithAnonymousUser; -import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.security.Principal; -import java.util.List; -import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class AbstractEndpointUnitTest extends AbstractUnitTest { +public class AbstractEndpointUnitTest extends BaseTest { @Autowired private AccessEndpoint accessEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void hasRole_noPrincipal_fails() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpointUnitTest.java similarity index 86% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpointUnitTest.java index 49b5d48de8..3c041352ea 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/AccessEndpointUnitTest.java @@ -1,18 +1,19 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.UserService; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.service.AccessService; +import at.ac.tuwien.ifs.dbrepo.service.DashboardService; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.service.UserService; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +38,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class AccessEndpointUnitTest extends AbstractUnitTest { +public class AccessEndpointUnitTest extends BaseTest { @MockBean private AccessService accessService; @@ -48,17 +49,15 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @MockBean private UserService userService; + @MockBean + private DashboardService dashboardService; + @Autowired private AccessEndpoint accessEndpoint; @Autowired private MetadataMapper metadataMapper; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void create_anonymous_fails() { @@ -113,7 +112,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-access"}) public void create_succeeds() throws DataServiceException, DataServiceConnectionException, NotAllowedException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(accessService.create(eq(DATABASE_1), eq(USER_2), any(AccessTypeDto.class))) @@ -208,7 +207,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"update-database-access"}) public void update_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, UserNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ doNothing() @@ -216,7 +215,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .update(eq(DATABASE_1), eq(USER_2), any(AccessTypeDto.class)); /* test */ - generic_update(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, DATABASE_1_USER_2_WRITE_OWN_ACCESS); + generic_update(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, DATABASE_1_USER_1_READ_ACCESS); } @Test @@ -293,7 +292,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-database-access"}) public void revoke_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ doNothing() @@ -311,7 +310,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { protected void generic_create(Principal principal, User principalUser, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) @@ -340,6 +339,10 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .when(userService) .findById(any(UUID.class)); } + when(dashboardService.create(DATABASE_1)) + .thenReturn(CreateDashboardResponseDto.builder() + .uid(DATABASE_1_DASHBOARD_UID) + .build()); /* test */ final ResponseEntity<?> response = accessEndpoint.create(DATABASE_1_ID, userId, UPDATE_DATABASE_ACCESS_READ_DTO, principal); @@ -384,7 +387,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { protected void generic_update(Principal principal, User principalUser, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, DataServiceException, DataServiceConnectionException, AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) @@ -415,6 +418,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .when(userService) .findByUsername(anyString()); } + doNothing() + .when(dashboardService) + .updateAccess(DATABASE_1, user, AccessTypeDto.READ); /* test */ final ResponseEntity<?> response = accessEndpoint.update(DATABASE_1_ID, userId, UPDATE_DATABASE_ACCESS_READ_DTO, principal); @@ -425,7 +431,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { protected void generic_revoke(Principal principal, User principalUser, UUID userId, User user) throws DataServiceConnectionException, NotAllowedException, DataServiceException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) @@ -436,6 +442,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } when(userService.findById(userId)) .thenReturn(user); + doNothing() + .when(dashboardService) + .updateAccess(DATABASE_1, user, null); /* test */ final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, userId, principal); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ActuatorComponentTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ActuatorComponentTest.java similarity index 85% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ActuatorComponentTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ActuatorComponentTest.java index 78b7f086c3..f86a8c4e8b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ActuatorComponentTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ActuatorComponentTest.java @@ -1,8 +1,7 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -11,6 +10,8 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; +import java.io.IOException; + import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -20,16 +21,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc @SpringBootTest -public class ActuatorComponentTest extends AbstractUnitTest { +public class ActuatorComponentTest extends BaseTest { @Autowired private MockMvc mockMvc; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void actuatorInfo_succeeds() throws Exception { this.mockMvc.perform(get("/actuator/info")) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ConceptEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpointUnitTest.java similarity index 77% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ConceptEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpointUnitTest.java index d48317f119..ba1d324299 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ConceptEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ConceptEndpointUnitTest.java @@ -1,10 +1,9 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.table.columns.concepts.ConceptDto; -import at.tuwien.service.ConceptService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ConceptDto; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.service.ConceptService; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -18,13 +17,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class ConceptEndpointUnitTest extends AbstractUnitTest { +public class ConceptEndpointUnitTest extends BaseTest { @MockBean private ConceptService conceptService; @@ -32,11 +32,6 @@ public class ConceptEndpointUnitTest extends AbstractUnitTest { @Autowired private ConceptEndpoint conceptEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAllConcepts_anonymous_succeeds() { @@ -46,7 +41,7 @@ public class ConceptEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_4_USERNAME, authorities = {}) + @WithMockUser(username = USER_4_USERNAME) public void findAllConcepts_noRole_succeeds() { /* test */ @@ -70,5 +65,5 @@ public class ConceptEndpointUnitTest extends AbstractUnitTest { assertNotNull(body); assertEquals(2, body.size()); } - + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpointUnitTest.java similarity index 85% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpointUnitTest.java index 67078ee409..0933ab65ef 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ContainerEndpointUnitTest.java @@ -1,16 +1,15 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.container.ContainerBriefDto; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.entities.container.Container; -import at.tuwien.exception.ContainerAlreadyExistsException; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.service.impl.ContainerServiceImpl; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.service.impl.ContainerServiceImpl; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +33,7 @@ import static org.mockito.Mockito.when; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest -public class ContainerEndpointUnitTest extends AbstractUnitTest { +public class ContainerEndpointUnitTest extends BaseTest { @MockBean private ContainerServiceImpl containerService; @@ -42,11 +41,6 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { @Autowired private ContainerEndpoint containerEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findById_anonymous_succeeds() throws ContainerNotFoundException { @@ -74,7 +68,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { assertEquals(List.of("" + CONTAINER_1_PORT), headers.get("X-Port")); 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(IMAGE_1_JDBC), headers.get("X-Jdbc-Method")); + assertEquals(List.of(IMAGE_1_JDBC_METHOD), headers.get("X-Jdbc-Method")); assertEquals(List.of("X-Username X-Password X-Jdbc-Method X-Host X-Port"), headers.get("Access-Control-Expose-Headers")); } @@ -135,7 +129,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void create_anonymous_fails() { final CreateContainerDto request = CreateContainerDto.builder() .name(CONTAINER_1_NAME) - .imageId(IMAGE_1_ID) + .imageId(CONTAINER_1_ID) .build(); /* test */ @@ -149,7 +143,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void create_hasRole_succeeds() throws ContainerAlreadyExistsException, ImageNotFoundException { final CreateContainerDto request = CreateContainerDto.builder() .name(CONTAINER_1_NAME) - .imageId(IMAGE_1_ID) + .imageId(CONTAINER_1_ID) .build(); /* test */ @@ -161,7 +155,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void create_noRole_fails() { final CreateContainerDto request = CreateContainerDto.builder() .name(CONTAINER_1_NAME) - .imageId(IMAGE_1_ID) + .imageId(CONTAINER_1_ID) .build(); /* test */ @@ -226,11 +220,11 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { final ContainerBriefDto container1 = body.get(0); assertEquals(CONTAINER_1_ID, container1.getId()); assertEquals(CONTAINER_1_NAME, container1.getName()); - assertEquals(CONTAINER_1_INTERNALNAME, container1.getInternalName()); + assertEquals(CONTAINER_1_INTERNAL_NAME, container1.getInternalName()); final ContainerBriefDto container2 = body.get(1); assertEquals(CONTAINER_2_ID, container2.getId()); assertEquals(CONTAINER_2_NAME, container2.getName()); - assertEquals(CONTAINER_2_INTERNALNAME, container2.getInternalName()); + assertEquals(CONTAINER_2_INTERNAL_NAME, container2.getInternalName()); } public void create_generic(CreateContainerDto data) throws ContainerAlreadyExistsException, ImageNotFoundException { 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/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpointUnitTest.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpointUnitTest.java index a52a0a8880..7f185fd989 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/ac/tuwien/ifs/dbrepo/endpoints/DatabaseEndpointUnitTest.java @@ -1,14 +1,14 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.database.*; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.*; -import at.tuwien.service.impl.DatabaseServiceImpl; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.*; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.service.*; +import at.ac.tuwien.ifs.dbrepo.service.impl.DatabaseServiceImpl; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +34,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class DatabaseEndpointUnitTest extends AbstractUnitTest { +public class DatabaseEndpointUnitTest extends BaseTest { @MockBean private BrokerService messageQueueService; @@ -54,21 +54,20 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @MockBean private StorageService storageService; + @MockBean + private DashboardService dashboardService; + @Autowired private DatabaseEndpoint databaseEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void create_anonymous_fails() { final CreateDatabaseDto request = CreateDatabaseDto.builder() .cid(CONTAINER_1_ID) - .name(DATABASE_1_NAME) - .isPublic(DATABASE_1_PUBLIC) + .name(DATABASE_1.getName()) + .isPublic(DATABASE_1.getIsPublic()) + .isSchemaPublic(DATABASE_1.getIsSchemaPublic()) .build(); /* test */ @@ -81,9 +80,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_4_USERNAME) public void create_noRole_fails() { final CreateDatabaseDto request = CreateDatabaseDto.builder() - .cid(CONTAINER_3_ID) - .name(DATABASE_3_NAME) - .isPublic(DATABASE_3_PUBLIC) + .cid(CONTAINER_1_ID) + .name(DATABASE_3.getName()) + .isPublic(DATABASE_3.getIsPublic()) + .isSchemaPublic(DATABASE_3.getIsSchemaPublic()) .build(); /* test */ @@ -97,11 +97,12 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void create_succeeds() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, AuthServiceException, AuthServiceConnectionException, - BrokerServiceException, BrokerServiceConnectionException, ContainerQuotaException { + BrokerServiceException, BrokerServiceConnectionException, ContainerQuotaException, + DashboardServiceException, DashboardServiceConnectionException { final CreateDatabaseDto request = CreateDatabaseDto.builder() .cid(CONTAINER_1_ID) - .name(DATABASE_1_NAME) - .isPublic(DATABASE_1_PUBLIC) + .name(DATABASE_1.getName()) + .isPublic(DATABASE_1.getIsPublic()) .build(); /* mock */ @@ -122,13 +123,13 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database"}) public void create_quotaExceeded_fails() throws UserNotFoundException, ContainerNotFoundException { final CreateDatabaseDto request = CreateDatabaseDto.builder() - .cid(CONTAINER_4_ID) - .name(DATABASE_1_NAME) - .isPublic(DATABASE_1_PUBLIC) + .cid(CONTAINER_4.getId()) + .name(DATABASE_1.getName()) + .isPublic(DATABASE_1.getIsPublic()) .build(); /* mock */ - when(containerService.find(CONTAINER_4_ID)) + when(containerService.find(CONTAINER_4.getId())) .thenReturn(CONTAINER_4); when(userService.findById(USER_1_ID)) .thenReturn(USER_1); @@ -203,8 +204,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void refreshViewMetadata_succeeds() throws UserNotFoundException, SearchServiceException, - NotAllowedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, - SearchServiceConnectionException, DataServiceConnectionException, ViewNotFoundException { + NotAllowedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException, ViewNotFoundException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) @@ -285,7 +286,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void list_hasRole_succeeds() { /* pre-condition */ - assertTrue(DATABASE_3_PUBLIC); + assertTrue(DATABASE_3.getIsPublic()); /* mock */ when(databaseService.findAllPublicOrSchemaPublicOrReadAccess(any(UUID.class))) @@ -300,7 +301,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void list_hasRoleForeign_succeeds() { /* pre-condition */ - assertTrue(DATABASE_3_PUBLIC); + assertTrue(DATABASE_3.getIsPublic()); /* mock */ when(databaseService.findAllPublicOrSchemaPublicOrReadAccess(USER_1_ID)) @@ -315,11 +316,11 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void list_hasRoleFilter_succeeds() { /* mock */ - when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, DATABASE_3_INTERNALNAME)) + when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, DATABASE_3.getInternalName())) .thenReturn(List.of(DATABASE_3)); /* test */ - list_generic(DATABASE_3_INTERNALNAME, USER_1_PRINCIPAL, 1); + list_generic(DATABASE_3.getInternalName(), USER_1_PRINCIPAL, 1); } @Test @@ -351,11 +352,11 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void list_hasSystemRoleFilterByName_succeeds() { /* mock */ - when(databaseService.findByInternalName(DATABASE_1_INTERNALNAME)) + when(databaseService.findByInternalName(DATABASE_1.getInternalName())) .thenReturn(List.of(DATABASE_1)); /* test */ - list_generic(DATABASE_1_INTERNALNAME, USER_LOCAL_ADMIN_PRINCIPAL, 1); + list_generic(DATABASE_1.getInternalName(), USER_LOCAL_ADMIN_PRINCIPAL, 1); } @Test @@ -386,7 +387,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-database-visibility"}) public void visibility_hasRole_succeeds() throws NotAllowedException, UserNotFoundException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { + DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { final DatabaseModifyVisibilityDto request = DatabaseModifyVisibilityDto.builder() .isPublic(true) .build(); @@ -654,7 +656,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(accessService.list(DATABASE_1)) - .thenReturn(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS, DATABASE_1_USER_2_READ_ACCESS)); + .thenReturn(List.of(DATABASE_1.getAccesses().get(0), DATABASE_1.getAccesses().get(1))); /* test */ final ResponseEntity<DatabaseDto> response = findById_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL); @@ -671,7 +673,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(accessService.list(DATABASE_1)) - .thenReturn(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS, DATABASE_1_USER_2_READ_ACCESS)); + .thenReturn(List.of(DATABASE_1.getAccesses().get(0), DATABASE_1.getAccesses().get(1))); /* test */ final ResponseEntity<DatabaseDto> response = findById_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL); @@ -688,7 +690,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(accessService.list(DATABASE_1)) - .thenReturn(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS, DATABASE_1_USER_2_READ_ACCESS)); + .thenReturn(List.of(DATABASE_1.getAccesses().get(0), DATABASE_1.getAccesses().get(1))); /* test */ final ResponseEntity<DatabaseDto> response = findById_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL); @@ -730,7 +732,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { assertEquals(List.of("" + CONTAINER_1_PORT), headers.get("X-Port")); 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(IMAGE_1_JDBC), headers.get("X-Jdbc-Method")); + assertEquals(List.of(IMAGE_1_JDBC_METHOD), headers.get("X-Jdbc-Method")); assertEquals(List.of("X-Username X-Password X-Jdbc-Method X-Host X-Port"), headers.get("Access-Control-Expose-Headers")); } @@ -795,9 +797,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } public void create_generic(CreateDatabaseDto data, Principal principal, User user) throws DataServiceException, - DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, BrokerServiceException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, - BrokerServiceException, BrokerServiceConnectionException, ContainerQuotaException { + BrokerServiceConnectionException, ContainerQuotaException, DashboardServiceException, + DashboardServiceConnectionException { /* mock */ doNothing() @@ -805,6 +808,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .setVirtualHostPermissions(user); when(databaseService.findById(any(UUID.class))) .thenReturn(DATABASE_1); + when(dashboardService.create(DATABASE_1)) + .thenReturn(CreateDashboardResponseDto.builder() + .uid(DATABASE_1_DASHBOARD_UID) + .build()); /* test */ final ResponseEntity<DatabaseBriefDto> response = databaseEndpoint.create(data, principal); @@ -814,7 +821,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public void visibility_generic(UUID databaseId, Database database, DatabaseModifyVisibilityDto data, Principal principal) throws NotAllowedException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException, UserNotFoundException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { /* mock */ if (database != null) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpointUnitTest.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpointUnitTest.java index 59aca6a405..38b8ee2217 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/IdentifierEndpointUnitTest.java @@ -1,22 +1,20 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.identifier.*; -import at.tuwien.api.identifier.ld.LdDatasetDto; -import at.tuwien.config.EndpointConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierType; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.service.*; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.config.EndpointConfig; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld.LdDatasetDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierType; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.service.*; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -37,7 +35,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.List; @@ -50,7 +47,7 @@ import static org.mockito.Mockito.*; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest -public class IdentifierEndpointUnitTest extends AbstractUnitTest { +public class IdentifierEndpointUnitTest extends BaseTest { @MockBean private IdentifierService identifierService; @@ -84,10 +81,10 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { public static Stream<Arguments> save_parameters() { return Stream.of( - Arguments.arguments("foreign_subset", DATABASE_2_ID, DATABASE_2, null, IDENTIFIER_5, IDENTIFIER_5_SAVE_DTO, USER_1_PRINCIPAL, USER_1), - Arguments.arguments("foreign_database", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_1, IDENTIFIER_1_SAVE_DTO, USER_1_PRINCIPAL, USER_1), - Arguments.arguments("foreign_view", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_3, IDENTIFIER_3_SAVE_DTO, USER_1_PRINCIPAL, USER_1), - Arguments.arguments("foreign_table", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_4, IDENTIFIER_4_SAVE_DTO, USER_1_PRINCIPAL, USER_1) + Arguments.arguments("foreign_subset", 2, 5, 1), + Arguments.arguments("foreign_database", 1, 1, 1), + Arguments.arguments("foreign_view", 1, 3, 1), + Arguments.arguments("foreign_table", 1, 4, 1) ); } @@ -143,22 +140,22 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { public static Stream<Arguments> findAll_filterDatabase_parameters() { return Stream.of( - Arguments.arguments("database_dbid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("database_qid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, QUERY_1_ID, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("database_vid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, USER_1_PRINCIPAL), - Arguments.arguments("database_tid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, USER_1_PRINCIPAL), - Arguments.arguments("subset_dbid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("subset_qid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, QUERY_1_ID, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("subset_vid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, USER_1_PRINCIPAL), - Arguments.arguments("subset_tid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, USER_1_PRINCIPAL), - Arguments.arguments("view_dbid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("view_qid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, QUERY_1_ID, null, null, 0, USER_1_PRINCIPAL), - Arguments.arguments("view_vid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, VIEW_1_ID, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("view_tid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, USER_1_PRINCIPAL), - Arguments.arguments("table_dbid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, null, null, 1, USER_1_PRINCIPAL), - Arguments.arguments("table_qid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, QUERY_1_ID, null, null, 0, USER_1_PRINCIPAL), - Arguments.arguments("table_vid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, USER_1_PRINCIPAL), - Arguments.arguments("table_tid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, null, TABLE_1_ID, 1, USER_1_PRINCIPAL), + Arguments.arguments("database_dbid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, null, null, 1, 1), + Arguments.arguments("database_qid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, QUERY_1_ID, null, null, 1, 1), + Arguments.arguments("database_vid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, 1), + Arguments.arguments("database_tid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, 1), + Arguments.arguments("subset_dbid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, null, null, 1, 1), + Arguments.arguments("subset_qid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, QUERY_1_ID, null, null, 1, 1), + Arguments.arguments("subset_vid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, 1), + Arguments.arguments("subset_tid", IdentifierTypeDto.SUBSET, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, 1), + Arguments.arguments("view_dbid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, null, null, 1, 1), + Arguments.arguments("view_qid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, QUERY_1_ID, null, null, 0, 1), + Arguments.arguments("view_vid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, VIEW_1_ID, null, 1, 1), + Arguments.arguments("view_tid", IdentifierTypeDto.VIEW, null, DATABASE_1_ID, null, null, TABLE_1_ID, 0, 1), + Arguments.arguments("table_dbid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, null, null, 1, 1), + Arguments.arguments("table_qid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, QUERY_1_ID, null, null, 0, 1), + Arguments.arguments("table_vid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, 1), + Arguments.arguments("table_tid", IdentifierTypeDto.TABLE, null, DATABASE_1_ID, null, null, TABLE_1_ID, 1, 1), Arguments.arguments("anon_database_dbid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, null, null, 1, null), Arguments.arguments("anon_database_qid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, QUERY_1_ID, null, null, 1, null), Arguments.arguments("anon_database_vid", IdentifierTypeDto.DATABASE, null, DATABASE_1_ID, null, VIEW_1_ID, null, 0, null), @@ -180,17 +177,12 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { public static Stream<Arguments> save_foreign_parameters() { return Stream.of( - Arguments.arguments("view", IDENTIFIER_3, IDENTIFIER_3_SAVE_DTO), - Arguments.arguments("table", IDENTIFIER_4, IDENTIFIER_4_SAVE_DTO), - Arguments.arguments("subset", IDENTIFIER_2, IDENTIFIER_2_SAVE_DTO) + Arguments.arguments("view", 3), + Arguments.arguments("table", 4), + Arguments.arguments("subset", 2) ); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAll_empty_succeeds() { @@ -290,7 +282,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @WithAnonymousUser public void findAll_filterDatabase_succeeds(String name, IdentifierTypeDto type, IdentifierStatusTypeDto status, UUID databaseId, UUID queryId, UUID viewId, UUID tableId, - Integer expectedSize, Principal principal) throws ViewNotFoundException, + Integer expectedSize, Integer idx) throws ViewNotFoundException, TableNotFoundException, DatabaseNotFoundException { /* mock */ @@ -304,6 +296,12 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); } + final Principal principal; + if (idx == null) { + principal = null; + } else { + principal = USER_1_PRINCIPAL; + } /* test */ final ResponseEntity<?> response = identifierEndpoint.findAll(type, status, databaseId, queryId, viewId, tableId, "application/json", principal); @@ -430,11 +428,11 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata0.json"), StandardCharsets.UTF_8), IdentifierDto.class); /* mock */ - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7_ID, accept, USER_4_PRINCIPAL); + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7.getId(), accept, USER_4_PRINCIPAL); assertEquals(HttpStatus.OK, response.getStatusCode()); final IdentifierDto body = (IdentifierDto) response.getBody(); assertNotNull(body); @@ -535,12 +533,12 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(identifierService.exportBibliography(IDENTIFIER_7, BibliographyTypeDto.APA)) .thenReturn(compare); - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ assertThrows(NotAllowedException.class, () -> { - identifierEndpoint.find(IDENTIFIER_7_ID, accept, null); + identifierEndpoint.find(IDENTIFIER_7.getId(), accept, null); }); } @@ -556,11 +554,11 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(identifierService.exportBibliography(IDENTIFIER_7, BibliographyTypeDto.APA)) .thenReturn(compare); - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7_ID, accept, USER_4_PRINCIPAL); + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7.getId(), accept, USER_4_PRINCIPAL); assertEquals(HttpStatus.OK, response.getStatusCode()); final String body = (String) response.getBody(); assertNotNull(body); @@ -649,7 +647,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { when(identifierService.exportBibliography(any(Identifier.class), eq(BibliographyTypeDto.APA))) .thenReturn(compare); when(identifierService.find(IDENTIFIER_1_ID)) - .thenReturn(IDENTIFIER_1_WITH_DOI); + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept, null); @@ -671,11 +669,11 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(identifierService.exportBibliography(IDENTIFIER_7, BibliographyTypeDto.IEEE)) .thenReturn(compare); - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7_ID, accept, USER_4_PRINCIPAL); + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7.getId(), accept, USER_4_PRINCIPAL); assertEquals(HttpStatus.OK, response.getStatusCode()); final String body = (String) response.getBody(); assertNotNull(body); @@ -741,7 +739,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { when(identifierService.exportBibliography(any(Identifier.class), eq(BibliographyTypeDto.IEEE))) .thenReturn(compare); when(identifierService.find(IDENTIFIER_1_ID)) - .thenReturn(IDENTIFIER_1_WITH_DOI); + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept, null); @@ -763,11 +761,11 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(identifierService.exportBibliography(IDENTIFIER_7, BibliographyTypeDto.BIBTEX)) .thenReturn(compare); - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7_ID, accept, USER_4_PRINCIPAL); + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_7.getId(), accept, USER_4_PRINCIPAL); assertEquals(HttpStatus.OK, response.getStatusCode()); final String body = (String) response.getBody(); assertNotNull(body); @@ -833,7 +831,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { when(identifierService.exportBibliography(any(Identifier.class), eq(BibliographyTypeDto.BIBTEX))) .thenReturn(compare); when(identifierService.find(IDENTIFIER_1_ID)) - .thenReturn(IDENTIFIER_1_WITH_DOI); + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept, null); @@ -867,12 +865,12 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { final String accept = "text/csv"; /* mock */ - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); /* test */ assertThrows(NotAllowedException.class, () -> { - identifierEndpoint.find(IDENTIFIER_7_ID, accept, null); + identifierEndpoint.find(IDENTIFIER_7.getId(), accept, null); }); } @@ -900,7 +898,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {}) + @WithMockUser(username = USER_1_USERNAME) public void delete_noRole_fails() { /* test */ @@ -919,9 +917,8 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-identifier"}) - public void delete_alreadyPublished_fails() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, - SearchServiceConnectionException { + public void delete_alreadyPublished_fails() throws DatabaseNotFoundException, IdentifierNotFoundException, + SearchServiceException, SearchServiceConnectionException { /* mock */ when(identifierService.find(IDENTIFIER_1_ID)) @@ -1270,16 +1267,35 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("save_foreign_parameters") @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_foreign_fails(String name, Identifier identifier, IdentifierSaveDto data) + public void save_foreign_fails(String name, Integer idx) throws UserNotFoundException { /* mock */ when(userService.findById(USER_1_ID)) .thenReturn(USER_1); + final Identifier identifier; + final IdentifierSaveDto identifierSave = switch (idx) { + case 2 -> { + identifier = IDENTIFIER_2; + yield IDENTIFIER_2_SAVE_DTO; + } + case 3 -> { + identifier = IDENTIFIER_3; + yield IDENTIFIER_3_SAVE_DTO; + } + case 4 -> { + identifier = IDENTIFIER_4; + yield IDENTIFIER_4_SAVE_DTO; + } + default -> { + identifier = null; + yield null; + } + }; /* test */ assertThrows(NotAllowedException.class, () -> { - generic_save(DATABASE_1_ID, DATABASE_1, null, identifier, data, USER_1_PRINCIPAL, USER_1); + generic_save(DATABASE_1_ID, DATABASE_1, null, identifier, identifierSave, USER_1_PRINCIPAL, USER_1); }); } @@ -1309,12 +1325,60 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("save_parameters") @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_noForeign_fails(String name, UUID databaseId, Database database, DatabaseAccess access, - Identifier identifier, IdentifierSaveDto data, Principal principal, User user) { + public void save_noForeign_fails(String name, Integer dbIdx, Integer idIdx, Integer uIdx) { + final UUID databaseId; + final Database database = switch (dbIdx) { + case 1 -> { + databaseId = DATABASE_1_ID; + yield DATABASE_1; + } + case 2 -> { + databaseId = DATABASE_2_ID; + yield DATABASE_2; + } + default -> { + databaseId = null; + yield null; + } + }; + final IdentifierSaveDto identifierSave; + final Identifier identifier = switch (idIdx) { + case 1 -> { + identifierSave = IDENTIFIER_1_SAVE_DTO; + yield IDENTIFIER_1; + } + case 3 -> { + identifierSave = IDENTIFIER_3_SAVE_DTO; + yield IDENTIFIER_3; + } + case 4 -> { + identifierSave = IDENTIFIER_4_SAVE_DTO; + yield IDENTIFIER_4; + } + case 5 -> { + identifierSave = IDENTIFIER_5_SAVE_DTO; + yield IDENTIFIER_5; + } + default -> { + identifierSave = null; + yield null; + } + }; + final Principal principal; + final User user = switch (uIdx) { + case 1 -> { + principal = USER_1_PRINCIPAL; + yield USER_1; + } + default -> { + principal = null; + yield null; + } + }; /* test */ assertThrows(NotAllowedException.class, () -> { - generic_save(databaseId, database, access, identifier, data, principal, user); + generic_save(databaseId, database, null, identifier, identifierSave, principal, user); }); } @@ -1356,7 +1420,8 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { .thenReturn(IDENTIFIER_1); /* test */ - final ResponseEntity<IdentifierDto> response = identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); + final ResponseEntity<IdentifierDto> response = identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, + USER_1_PRINCIPAL); assertEquals(HttpStatus.CREATED, response.getStatusCode()); final IdentifierDto body = response.getBody(); assertNotNull(body); @@ -1496,14 +1561,14 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { SearchServiceConnectionException { /* mock */ - when(identifierService.find(IDENTIFIER_7_ID)) + when(identifierService.find(IDENTIFIER_7.getId())) .thenReturn(IDENTIFIER_7); doNothing() .when(identifierService) .delete(IDENTIFIER_7); /* test */ - final ResponseEntity<?> response = identifierEndpoint.delete(IDENTIFIER_7_ID); + final ResponseEntity<?> response = identifierEndpoint.delete(IDENTIFIER_7.getId()); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertNull(response.getBody()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpointUnitTest.java similarity index 76% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpointUnitTest.java index b5be98cfb6..9a1289a86b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ImageEndpointUnitTest.java @@ -1,17 +1,17 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.container.image.ImageBriefDto; -import at.tuwien.api.container.image.ImageChangeDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.api.container.image.ImageDto; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.service.impl.ImageServiceImpl; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageChangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.service.impl.ImageServiceImpl; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +33,7 @@ import static org.mockito.Mockito.*; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest -public class ImageEndpointUnitTest extends AbstractUnitTest { +public class ImageEndpointUnitTest extends BaseTest { @MockBean private ImageServiceImpl imageService; @@ -41,10 +41,8 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { @Autowired private ImageEndpoint imageEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } + @Autowired + private MetadataMapper metadataMapper; @Test @WithAnonymousUser @@ -76,9 +74,9 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .build(); /* test */ @@ -93,9 +91,9 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .build(); /* test */ @@ -110,9 +108,9 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .build(); /* test */ @@ -126,14 +124,14 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { public void create_succeeds() throws ImageAlreadyExistsException, ImageInvalidException { /* test */ - create_generic(IMAGE_1_CREATE_DTO, USER_1_PRINCIPAL); + create_generic(metadataMapper.containerImageToImageCreateDto(IMAGE_1), USER_1_PRINCIPAL); } @Test public void findById_anonymous_succeeds() throws ImageNotFoundException { /* test */ - findById_generic(IMAGE_1_ID, IMAGE_1); + findById_generic(CONTAINER_1_ID, IMAGE_1); } @Test @@ -156,7 +154,7 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - delete_generic(IMAGE_1_ID, IMAGE_1); + delete_generic(CONTAINER_1_ID, IMAGE_1); }); } @@ -166,7 +164,7 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - delete_generic(IMAGE_1_ID, IMAGE_1); + delete_generic(CONTAINER_1_ID, IMAGE_1); }); } @@ -180,22 +178,22 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { .delete(IMAGE_1); /* test */ - delete_generic(IMAGE_1_ID, IMAGE_1); + delete_generic(CONTAINER_1_ID, IMAGE_1); } @Test @WithAnonymousUser public void modify_anonymous_fails() { final ImageChangeDto request = ImageChangeDto.builder() - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) - .driverClass(IMAGE_1_DRIVER) + .jdbcMethod(IMAGE_1_JDBC_METHOD) + .driverClass(IMAGE_1.getDriverClass()) .build(); /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - modify_generic(IMAGE_1_ID, IMAGE_1, request); + modify_generic(CONTAINER_1_ID, IMAGE_1, request); }); } @@ -203,15 +201,15 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_4_USERNAME) public void modify_noRole_fails() { final ImageChangeDto request = ImageChangeDto.builder() - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) - .driverClass(IMAGE_1_DRIVER) + .jdbcMethod(IMAGE_1_JDBC_METHOD) + .driverClass(IMAGE_1.getDriverClass()) .build(); /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - modify_generic(IMAGE_1_ID, IMAGE_1, request); + modify_generic(CONTAINER_1_ID, IMAGE_1, request); }); } @@ -219,15 +217,15 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-image"}) public void modify_hasRole_succeeds() throws ImageNotFoundException { final ImageChangeDto request = ImageChangeDto.builder() - .registry(IMAGE_1_REGISTRY) - .defaultPort(IMAGE_1_PORT) + .registry(IMAGE_1.getRegistry()) + .defaultPort(IMAGE_1_DEFAULT_PORT) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) - .driverClass(IMAGE_1_DRIVER) + .jdbcMethod(IMAGE_1_JDBC_METHOD) + .driverClass(IMAGE_1.getDriverClass()) .build(); /* test */ - modify_generic(IMAGE_1_ID, IMAGE_1, request); + modify_generic(CONTAINER_1_ID, IMAGE_1, request); } /* ################################################################################################### */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/LicenseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpointUnitTest.java similarity index 82% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/LicenseEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpointUnitTest.java index f45dd85fb4..765d16dc83 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/LicenseEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/LicenseEndpointUnitTest.java @@ -1,10 +1,9 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.LicenseDto; -import at.tuwien.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LicenseDto; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -23,7 +22,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class LicenseEndpointUnitTest extends AbstractUnitTest { +public class LicenseEndpointUnitTest extends BaseTest { @MockBean private LicenseRepository licenseRepository; @@ -31,11 +30,6 @@ public class LicenseEndpointUnitTest extends AbstractUnitTest { @Autowired private LicenseEndpoint licenseEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void list_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpointUnitTest.java similarity index 87% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpointUnitTest.java index 0fabc67c91..f31518e8e2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MessageEndpointUnitTest.java @@ -1,14 +1,13 @@ -package at.tuwien.endpoints; - -import at.tuwien.exception.MessageNotFoundException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.service.BannerMessageService; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.exception.MessageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.service.BannerMessageService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -29,7 +28,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class MessageEndpointUnitTest extends AbstractUnitTest { +public class MessageEndpointUnitTest extends BaseTest { @MockBean private BannerMessageService bannerMessageService; @@ -37,11 +36,6 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { @Autowired private MessageEndpoint messageEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void list_anonymous_succeeds() { @@ -127,7 +121,7 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"create-maintenance-message"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"create-maintenance-message"}) public void create_hasRole_succeeds() { /* test */ @@ -155,7 +149,7 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"update-maintenance-message"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"update-maintenance-message"}) public void update_hasRole_succeeds() throws MessageNotFoundException { /* test */ @@ -183,7 +177,7 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-maintenance-message"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"delete-maintenance-message"}) public void delete_hasRole_succeeds() throws MessageNotFoundException { /* test */ @@ -191,7 +185,7 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-maintenance-message"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"delete-maintenance-message"}) public void delete_hasRoleNotFound_fails() { /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpointUnitTest.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpointUnitTest.java index 98f756a1c0..012ca1f1c0 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MetadataEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/MetadataEndpointUnitTest.java @@ -1,12 +1,11 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.oaipmh.OaiListIdentifiersParameters; -import at.tuwien.oaipmh.OaiRecordParameters; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.XmlUtils; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiListIdentifiersParameters; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiRecordParameters; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.XmlUtils; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +26,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class MetadataEndpointUnitTest extends AbstractUnitTest { +public class MetadataEndpointUnitTest extends BaseTest { @MockBean private IdentifierRepository identifierRepository; @@ -35,11 +34,6 @@ public class MetadataEndpointUnitTest extends AbstractUnitTest { @Autowired private MetadataEndpoint metadataEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void identify_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpointUnitTest.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpointUnitTest.java index ab3d0775ad..3055de08cd 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/OntologyEndpointUnitTest.java @@ -1,18 +1,17 @@ -package at.tuwien.endpoints; - -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.semantics.*; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.EntityService; -import at.tuwien.service.OntologyService; -import at.tuwien.service.UserService; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.service.EntityService; +import at.ac.tuwien.ifs.dbrepo.service.OntologyService; +import at.ac.tuwien.ifs.dbrepo.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.apache.jena.sys.JenaSystem; import org.hibernate.HibernateException; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +33,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class OntologyEndpointUnitTest extends AbstractUnitTest { +public class OntologyEndpointUnitTest extends BaseTest { @MockBean private OntologyService ontologyService; @@ -53,11 +52,6 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { JenaSystem.init(); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAll_anonymous_succeeds() { @@ -142,11 +136,11 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-ontology"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-ontology"}) public void create_hasRole_succeeds() throws UserNotFoundException { /* test */ - create_generic(ONTOLOGY_1_CREATE_DTO, USER_3_PRINCIPAL, USER_3_USERNAME, USER_3, ONTOLOGY_1); + create_generic(ONTOLOGY_1_CREATE_DTO, USER_3_PRINCIPAL, USER_3.getUsername(), USER_3, ONTOLOGY_1); } @Test @@ -170,7 +164,7 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"update-ontology"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"update-ontology"}) public void update_hasRole_succeeds() throws OntologyNotFoundException { /* test */ @@ -198,7 +192,7 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-ontology"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"delete-ontology"}) public void delete_hasRole_succeeds() throws OntologyNotFoundException { /* test */ @@ -216,7 +210,7 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_4_USERNAME, authorities = {}) + @WithMockUser(username = USER_4_USERNAME) public void find_noRole_fails() { /* test */ 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/ac/tuwien/ifs/dbrepo/endpoints/TableEndpointUnitTest.java similarity index 78% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpointUnitTest.java index 12b6e0a247..9c756b8311 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/ac/tuwien/ifs/dbrepo/endpoints/TableEndpointUnitTest.java @@ -1,29 +1,28 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableUpdateDto; -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.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.*; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.validation.EndpointValidator; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.TableColumnEntityDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.service.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.validation.EndpointValidator; import lombok.extern.log4j.Log4j2; import org.apache.jena.sys.JenaSystem; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -49,7 +48,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class TableEndpointUnitTest extends AbstractUnitTest { +public class TableEndpointUnitTest extends BaseTest { @MockBean private DatabaseService databaseService; @@ -57,12 +56,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @MockBean private AccessService accessService; - @MockBean - private UnitService unitService; - - @MockBean - private ConceptService conceptService; - @MockBean private TableService tableService; @@ -101,11 +94,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { JenaSystem.init(); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void list_publicDataPrivateSchemaAnonymous_fails() { @@ -141,7 +129,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException { /* test */ - final ResponseEntity<List<TableBriefDto>> response = generic_list(DATABASE_3_ID, DATABASE_3, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + final ResponseEntity<List<TableBriefDto>> response = generic_list(DATABASE_3_ID, DATABASE_3, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); assertEquals(HttpStatus.OK, response.getStatusCode()); final List<TableBriefDto> body = response.getBody(); assertNotNull(body); @@ -208,7 +196,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicDecimalColumnSizeTooSmall_fails() { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -229,7 +217,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicDecimalColumnDTooSmall_fails() { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -251,9 +239,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("canHaveSize_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicOptionalSizeNone_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, - NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException { + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) + public void create_publicOptionalSizeNone_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, + SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, TableNotFoundException, + DataServiceConnectionException, MalformedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -282,9 +273,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("canHaveSize_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicOptionalSize_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, - NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException { + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) + public void create_publicOptionalSize_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, + SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, TableNotFoundException, + DataServiceConnectionException, MalformedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -307,9 +301,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("needNothing_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicNeedNothing_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, - NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException { + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) + public void create_publicNeedNothing_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, + SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, TableNotFoundException, + DataServiceConnectionException, MalformedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -333,9 +330,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("needSize_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicNeedSize_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, - NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException { + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) + public void create_publicNeedSize_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, + SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, TableNotFoundException, + DataServiceConnectionException, MalformedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, OntologyNotFoundException, TableExistsException, SearchServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -358,7 +358,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("needSize_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicNeedSizeNone_fails(ColumnTypeDto columnType) { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -378,145 +378,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }); } - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_sets_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name("sex") - .type(ColumnTypeDto.SET) - .sets(List.of("male", "female")) - .build())) - .build(); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_enum_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name("sex") - .type(ColumnTypeDto.ENUM) - .enums(List.of("male", "female")) - .build())) - .build(); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_hasUnit_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException, UnitNotFoundException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name(UNIT_1_NAME) - .type(ColumnTypeDto.INT) - .unitUri(UNIT_1_URI) - .build())) - .build(); - - /* mock */ - when(unitService.find(UNIT_1_URI)) - .thenReturn(UNIT_1); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_hasUnitNotFound_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name(UNIT_1_NAME) - .type(ColumnTypeDto.INT) - .unitUri(UNIT_1_URI) - .build())) - .build(); - - /* mock */ - when(unitService.create(UNIT_1)) - .thenReturn(UNIT_1); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_hasConcept_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException, ConceptNotFoundException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name(CONCEPT_1_NAME) - .type(ColumnTypeDto.INT) - .conceptUri(UNIT_1_URI) - .build())) - .build(); - - /* mock */ - when(conceptService.find(CONCEPT_1_URI)) - .thenReturn(CONCEPT_1); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_hasConceptNotFound_succeeds() throws UserNotFoundException, SearchServiceException, NotAllowedException, - SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, - DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, - TableExistsException, SearchServiceConnectionException { - final CreateTableDto request = CreateTableDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(CreateTableColumnDto.builder() - .name("precipitation") - .type(ColumnTypeDto.INT) - .conceptUri(UNIT_1_URI) - .build())) - .build(); - - /* mock */ - when(conceptService.create(CONCEPT_1)) - .thenReturn(CONCEPT_1); - - /* test */ - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - } - @ParameterizedTest @MethodSource("canHaveSizeAndD_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicCanHaveSizeAndDSizeNone_fails(ColumnTypeDto columnType) { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -538,7 +402,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("canHaveSizeAndD_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicCanHaveSizeAndDDNone_fails(ColumnTypeDto columnType) { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -560,12 +424,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("canHaveSizeAndD_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicCanHaveSizeAndDBothNone_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -587,7 +451,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicHasMultipleSerial_fails() { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -615,7 +479,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicSerialNullAllowed_fails() { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") @@ -638,12 +502,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("canHaveSizeAndD_parameters") - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"create-table"}) public void create_publicCanHaveSizeAndDBothNotNone_succeeds(ColumnTypeDto columnType) throws UserNotFoundException, SearchServiceException, NotAllowedException, SemanticEntityNotFoundException, DataServiceConnectionException, TableNotFoundException, MalformedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, OntologyNotFoundException, TableExistsException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { final CreateTableDto request = CreateTableDto.builder() .name("Some Table") .description("Some Description") @@ -679,7 +543,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -689,7 +553,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - generic_findById(DATABASE_3_ID, null, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_findById(DATABASE_3_ID, null, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -699,7 +563,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { 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); + final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); assertEquals(HttpStatus.OK, response.getStatusCode()); final TableDto body = response.getBody(); assertNotNull(body); @@ -840,7 +704,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) public void update_publicHasRoleForeignHasOwnWriteAccess_fails() { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() .unitUri(UNIT_1_URI) @@ -868,7 +732,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) public void update_publicHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, DataServiceException, NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, @@ -924,7 +788,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), - TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_1_USER_1_READ_ACCESS); + TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_1.getAccesses().get(0)); }); } @@ -944,7 +808,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) public void update_privateHasRoleForeignHasOwnWriteAccess_fails() { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() .unitUri(UNIT_1_URI) @@ -972,7 +836,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) public void update_privateHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, DataServiceException, NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, @@ -993,7 +857,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - generic_list(DATABASE_1_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_list(DATABASE_1_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -1003,7 +867,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException { /* test */ - final ResponseEntity<List<TableBriefDto>> response = generic_list(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + final ResponseEntity<List<TableBriefDto>> response = generic_list(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); assertEquals(HttpStatus.OK, response.getStatusCode()); final List<TableBriefDto> body = response.getBody(); assertNotNull(body); @@ -1055,7 +919,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_create(DATABASE_1_ID, DATABASE_1, TABLE_5_CREATE_DTO, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_create(DATABASE_1_ID, DATABASE_1, TABLE_5_CREATE_DTO, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -1086,7 +950,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, null, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -1096,7 +960,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - generic_findById(DATABASE_1_ID, null, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + generic_findById(DATABASE_1_ID, null, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); }); } @@ -1106,21 +970,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { 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); + USER_1_PRINCIPAL, USER_1, DATABASE_1.getAccesses().get(0)); assertEquals(HttpStatus.OK, response.getStatusCode()); final TableDto body = response.getBody(); assertNotNull(body); } - @Test - @WithMockUser(username = USER_4_USERNAME) - public void findById_privateDatabasePrivateDataPrivateSchemaNoRole_succeeds() throws UserNotFoundException, - 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); - } - @Test @WithMockUser(username = USER_4_USERNAME) public void delete_privateNoRole_fails() { @@ -1135,14 +990,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table"}) public void delete_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* test */ generic_delete(USER_1_PRINCIPAL, TABLE_1); } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"delete-table"}) public void delete_foreign_fails() { /* test */ @@ -1155,14 +1010,15 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_5_USERNAME, authorities = {"delete-foreign-table"}) public void delete_foreign_succeeds() throws NotAllowedException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, DataServiceException { + SearchServiceConnectionException, DataServiceException, DashboardServiceException, + DashboardServiceConnectionException { /* test */ generic_delete(USER_5_PRINCIPAL, TABLE_1); } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-table"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"delete-table"}) public void delete_hasIdentifiers_fails() { final Table response = Table.builder() .identifiers(List.of(IDENTIFIER_1)) @@ -1180,7 +1036,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"update-table"}) public void update_succeeds() throws TableNotFoundException, SearchServiceException, NotAllowedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, - DataServiceConnectionException { + DataServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { final TableUpdateDto request = TableUpdateDto.builder() .isPublic(true) .isSchemaPublic(true) @@ -1194,7 +1050,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"update-table"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"update-table"}) public void update_notOwner_fails() { final TableUpdateDto request = TableUpdateDto.builder() .isPublic(true) @@ -1209,7 +1065,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"update-table-statistic"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"update-table-statistic"}) public void updateStatistic_notOwner_fails() { /* test */ @@ -1311,7 +1167,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { throws MalformedException, NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, - SemanticEntityNotFoundException { + SemanticEntityNotFoundException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ if (principal != null) { @@ -1384,7 +1240,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<?> generic_delete(Principal principal, Table table) throws NotAllowedException, DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) @@ -1443,7 +1300,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<TableBriefDto> generic_update(TableUpdateDto data, Principal caller) throws TableNotFoundException, SearchServiceException, NotAllowedException, DataServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException { + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(databaseService.findById(DATABASE_1_ID)) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UnitEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpointUnitTest.java similarity index 77% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UnitEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpointUnitTest.java index 7d74e615be..77f8bebaa2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UnitEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UnitEndpointUnitTest.java @@ -1,10 +1,9 @@ -package at.tuwien.endpoints; +package at.ac.tuwien.ifs.dbrepo.endpoints; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.table.columns.concepts.UnitDto; -import at.tuwien.service.UnitService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.UnitDto; +import at.ac.tuwien.ifs.dbrepo.service.UnitService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -18,13 +17,14 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class UnitEndpointUnitTest extends AbstractUnitTest { +public class UnitEndpointUnitTest extends BaseTest { @MockBean private UnitService unitService; @@ -32,11 +32,6 @@ public class UnitEndpointUnitTest extends AbstractUnitTest { @Autowired private UnitEndpoint unitEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAllUnits_anonymous_succeeds() { @@ -46,7 +41,7 @@ public class UnitEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_4_USERNAME, authorities = {}) + @WithMockUser(username = USER_4_USERNAME) public void findAllUnits_noRole_succeeds() { /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpointUnitTest.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpointUnitTest.java index 5f0341fa7b..c24461a164 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/UserEndpointUnitTest.java @@ -1,17 +1,16 @@ -package at.tuwien.endpoints; - -import at.tuwien.api.auth.CreateUserDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.NotAllowedException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.service.UserService; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.auth.CreateUserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.NotAllowedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +36,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class UserEndpointUnitTest extends AbstractUnitTest { +public class UserEndpointUnitTest extends BaseTest { @MockBean private UserService userService; @@ -45,11 +44,6 @@ public class UserEndpointUnitTest extends AbstractUnitTest { @Autowired private UserEndpoint userEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAll_anonymous_succeeds() throws UserNotFoundException { @@ -123,7 +117,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"find-foreign-user"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"find-foreign-user"}) public void find_hasRoleForeign_succeeds() throws UserNotFoundException, NotAllowedException { final Principal principal = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, USER_3_PASSWORD, List.of( new SimpleGrantedAuthority("find-foreign-user"))); @@ -133,7 +127,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"system"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"system"}) public void find_system_succeeds() throws UserNotFoundException, NotAllowedException { final Principal principal = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, USER_3_PASSWORD, List.of( new SimpleGrantedAuthority("system"))); @@ -141,7 +135,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { /* test */ final ResponseEntity<UserDto> response = find_generic(USER_3_ID, USER_3, principal); assertNotNull(response.getHeaders().get("X-Username")); - assertEquals(USER_3_USERNAME, response.getHeaders().get("X-Username").get(0)); + assertEquals(USER_3.getUsername(), response.getHeaders().get("X-Username").get(0)); assertNotNull(response.getHeaders().get("X-Password")); assertNotEquals(USER_3_PASSWORD, response.getHeaders().get("X-Password").get(0)); assertEquals(USER_3_DATABASE_PASSWORD, response.getHeaders().get("X-Password").get(0)); @@ -192,7 +186,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-user-information"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-user-information"}) public void modify_hasRoleForeign_fails() { final UserUpdateDto request = UserUpdateDto.builder() .firstname(USER_1_FIRSTNAME) @@ -232,7 +226,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void create_notInternalUser_fails() { /* test */ 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/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpointUnitTest.java similarity index 77% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpointUnitTest.java index ac5a8ef524..d0cb350758 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/ac/tuwien/ifs/dbrepo/endpoints/ViewEndpointUnitTest.java @@ -1,27 +1,22 @@ -package at.tuwien.endpoints; - -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.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.database.View; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.UserService; -import at.tuwien.service.ViewService; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.endpoints; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.service.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; @@ -39,7 +34,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class ViewEndpointUnitTest extends AbstractUnitTest { +public class ViewEndpointUnitTest extends BaseTest { @MockBean private DatabaseService databaseService; @@ -50,17 +45,15 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @MockBean private ViewService viewService; + @MockBean + private DashboardService dashboardService; + @MockBean private UserService userService; @Autowired private ViewEndpoint viewEndpoint; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @WithAnonymousUser public void findAll_publicAnonymous_succeeds() throws UserNotFoundException, AccessNotFoundException, @@ -71,7 +64,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"list-views"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"list-views"}) public void findAll_publicHasRole_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -80,7 +73,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"list-views"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"list-views"}) public void findAll_publicHasRoleHasAccess_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -89,7 +82,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void findAll_publicNoRole_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -108,7 +101,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"create-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"create-database-view"}) public void create_publicHasRole_fails() { /* test */ @@ -118,17 +111,17 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"create-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"create-database-view"}) public void create_publicHasRoleHasAccess_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_3_ID, DATABASE_3, "View", 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.getAccesses().get(0)); }); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void create_publicNoRole_fails() { /* test */ @@ -141,8 +134,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, TableNotFoundException, - ImageNotFoundException, ViewExistsException { + SearchServiceConnectionException, DataServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException, TableNotFoundException, ViewExistsException, ImageNotFoundException { /* test */ create_generic(DATABASE_1_ID, DATABASE_1, "View", USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); @@ -161,37 +154,37 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void find_publicAnonymous_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ find_generic(DATABASE_3_ID, DATABASE_3, null, null, null, null); } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"find-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"find-database-view"}) public void find_publicHasRole_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void find_publicNoRole_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void find_publicHasRoleHasAccess_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test @@ -205,30 +198,31 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"delete-database-view"}) public void delete_publicHasRole_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); }); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void delete_publicNoRole_fails() { /* test */ assertThrows(AccessDeniedException.class, () -> { - delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); }); } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-database-view"}) + @WithMockUser(username =USER_3_USERNAME, authorities = {"delete-database-view"}) public void delete_publicOwner_succeeds() throws NotAllowedException, DataServiceException, UserNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, ViewNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { /* test */ delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_5_ID, VIEW_5, USER_3_PRINCIPAL, USER_3_ID, USER_3, DATABASE_3_USER_1_WRITE_ALL_ACCESS); @@ -248,7 +242,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"list-views"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"list-views"}) public void findAll_privateHasRole_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -257,7 +251,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"list-views"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"list-views"}) public void findAll_privateHasRoleHasAccess_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -266,7 +260,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void findAll_privateNoRole_succeeds() throws UserNotFoundException, AccessNotFoundException, DatabaseNotFoundException { @@ -285,7 +279,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"create-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"create-database-view"}) public void create_privateHasRole_fails() { /* test */ @@ -295,17 +289,17 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"create-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"create-database-view"}) public void create_privateHasRoleHasAccess_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_1_ID, DATABASE_1, "View", 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.getAccesses().get(0)); }); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void create_privateNoRole_fails() { /* test */ @@ -317,37 +311,37 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void find_privateAnonymous_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ find_generic(DATABASE_1_ID, DATABASE_1, null, null, null, null); } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"find-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"find-database-view"}) public void find_privateHasRole_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void find_privateNoRole_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void find_privateHasRoleHasAccess_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { + AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* test */ - find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + find_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); } @Test @@ -361,22 +355,22 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-database-view"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"delete-database-view"}) public void delete_privateHasRole_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); }); } @Test - @WithMockUser(username = USER_2_USERNAME) + @WithMockUser(username =USER_2_USERNAME) public void delete_privateNoRole_fails() { /* test */ assertThrows(AccessDeniedException.class, () -> { - delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2.getAccesses().get(0)); }); } @@ -384,7 +378,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-database-view"}) public void delete_privateOwner_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, - SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { + SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException, DashboardServiceException, + DashboardServiceConnectionException { /* test */ delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); @@ -411,7 +406,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-view-visibility"}) + @WithMockUser(username =USER_2_USERNAME, authorities = {"modify-view-visibility"}) public void update_notOwner_fails() { /* test */ @@ -423,7 +418,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-view-visibility"}) public void update_succeeds() throws NotAllowedException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { + SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException, + DashboardServiceException, DashboardServiceConnectionException { /* test */ update_generic(USER_1_PRINCIPAL); @@ -448,32 +444,24 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { log.trace("mock access of database with id {} and user id {}", databaseId, userId); when(accessService.find(database, user)) .thenReturn(access); - when(viewService.findAll(database, user)) - .thenReturn(List.of(VIEW_1, VIEW_2)); } else { log.trace("mock no access of database with id {} and user id {}", databaseId, userId); when(accessService.find(database, user)) .thenThrow(AccessNotFoundException.class); - when(viewService.findAll(database, user)) - .thenReturn(List.of(VIEW_1)); } /* test */ final ResponseEntity<List<ViewBriefDto>> response = viewEndpoint.findAll(databaseId, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); - if (access == null) { - assertEquals(1, response.getBody().size()); - } else { - assertEquals(2, response.getBody().size()); - } } 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 { + ImageNotFoundException, ViewExistsException, DashboardServiceException, + DashboardServiceConnectionException { final CreateViewDto request = CreateViewDto.builder() .name(viewName) .query(VIEW_1_SUBSET_DTO) @@ -509,7 +497,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<ViewDto> find_generic(UUID databaseId, Database database, Principal principal, UUID userId, User user, DatabaseAccess access) - throws DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, ViewNotFoundException { + throws DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, ViewNotFoundException, NotAllowedException { /* mock */ when(databaseService.findById(databaseId)) @@ -544,7 +532,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void delete_generic(UUID databaseId, Database database, UUID viewId, View view, Principal principal, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, - SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { + SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException, + DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(databaseService.findById(databaseId)) @@ -561,6 +550,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { doNothing() .when(viewService) .delete(view); + doNothing() + .when(dashboardService) + .update(database); /* test */ final ResponseEntity<?> response = viewEndpoint.delete(databaseId, viewId, principal); @@ -569,7 +561,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void update_generic(Principal principal) throws SearchServiceException, NotAllowedException, DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, - ViewNotFoundException, UserNotFoundException { + ViewNotFoundException, UserNotFoundException, DashboardServiceException, + DashboardServiceConnectionException { final ViewUpdateDto request = ViewUpdateDto.builder() .isPublic(true) .isSchemaPublic(true) @@ -580,7 +573,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1); when(viewService.findById(DATABASE_1, VIEW_1_ID)) .thenReturn(VIEW_1); - when(viewService.update(DATABASE_1, VIEW_1, request)) + when(viewService.update(VIEW_1, request)) .thenReturn(VIEW_1); /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/entities/EntitiesUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/entity/EntitiesUnitTest.java similarity index 64% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/entities/EntitiesUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/entity/EntitiesUnitTest.java index 4fdb83bcd7..32f5b79f66 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/entities/EntitiesUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/entity/EntitiesUnitTest.java @@ -1,6 +1,6 @@ -package at.tuwien.entities; +package at.ac.tuwien.ifs.dbrepo.core.entity; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; @@ -9,7 +9,7 @@ import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; @Log4j2 -public class EntitiesUnitTest extends AbstractUnitTest { +public class EntitiesUnitTest extends BaseTest { @Test public void uuidVersion_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGatewayUnitTest.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGatewayUnitTest.java index 32a8c8b190..e8d2b01923 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGatewayUnitTest.java @@ -1,8 +1,9 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.amqp.GrantExchangePermissionsDto; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantExchangePermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.BrokerServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.BrokerServiceException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,7 +26,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { +public class BrokerServiceGatewayUnitTest extends BaseTest { @MockBean @Qualifier("brokerRestTemplate") @@ -36,8 +37,8 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { private final GrantExchangePermissionsDto WRITE_ALL_PERMISSIONS = GrantExchangePermissionsDto.builder() .exchange("dbrepo") - .read("^(dbrepo\\.1\\..*)$") /* WRITE_ALL */ - .write("^(dbrepo\\.1\\..*)$") + .read("^(dbrepo\\." + DATABASE_1_ID + "\\..*)$") /* WRITE_ALL */ + .write("^(dbrepo\\." + DATABASE_1_ID + "\\..*)$") .build(); @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGatewayUnitTest.java similarity index 83% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGatewayUnitTest.java index 881f29ed04..bbf0e45307 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGatewayUnitTest.java @@ -1,13 +1,12 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.exception.DoiNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DoiNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpEntity; @@ -16,7 +15,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -25,7 +23,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class CrossrefGatewayUnitTest extends AbstractUnitTest { +public class CrossrefGatewayUnitTest extends BaseTest { @MockBean private RestTemplate restTemplate; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGatewayUnitTest.java new file mode 100644 index 0000000000..c1a60d0115 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGatewayUnitTest.java @@ -0,0 +1,286 @@ +package at.ac.tuwien.ifs.dbrepo.gateway; + +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.PermissionTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; + +@Log4j2 +@SpringBootTest +@ExtendWith(SpringExtension.class) +public class DashboardServiceGatewayUnitTest extends BaseTest { + + @MockBean + @Qualifier("dashboardServiceRestTemplate") + private RestTemplate restTemplate; + + @Autowired + private DashboardServiceGateway dashboardServiceGateway; + + @Test + public void update_succeeds() throws DashboardServiceException, DashboardServiceConnectionException { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dashboardServiceGateway.update(DATABASE_2_DTO); + } + + @Test + public void update_wrongStatus_failed() { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.update(DATABASE_1_DTO); + }); + } + + @Test + public void update_connection_failed() { + + /* mock */ + doThrow(HttpServerErrorException.ServiceUnavailable.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceConnectionException.class, () -> { + dashboardServiceGateway.update(DATABASE_1_DTO); + }); + } + + @Test + public void update_unauthorized_failed() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.update(DATABASE_1_DTO); + }); + } + + @Test + public void create_succeeds() throws DashboardServiceException, DashboardServiceConnectionException { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .body(DATABASE_2_CREATE_DASHBOARD_RESPONSE_DTO)); + + /* test */ + final CreateDashboardResponseDto response = dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + assertEquals(DATABASE_2_DASHBOARD_UID, response.getUid()); + } + + @Test + public void create_emptyBody_fails() { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .body(null)); // <<< + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + }); + } + + @Test + public void create_wrongStatus_failed() { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + }); + } + + @Test + public void create_connection_failed() { + + /* mock */ + doThrow(HttpServerErrorException.ServiceUnavailable.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class)); + + /* test */ + assertThrows(DashboardServiceConnectionException.class, () -> { + dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + }); + } + + @Test + public void create_unauthorized_failed() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class)); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + }); + } + + @Test + public void create_exists_failed() { + + /* mock */ + doThrow(HttpClientErrorException.Conflict.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(CreateDashboardResponseDto.class)); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.create(DATABASE_2_CREATE_DASHBOARD_DTO); + }); + } + + @Test + public void updateAccess_succeeds() throws DashboardServiceException, DashboardServiceConnectionException { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dashboardServiceGateway.updateAccess(DATABASE_2_DASHBOARD_UID, USER_2_USERNAME, PermissionTypeDto.VIEW); + } + + @Test + public void updateAccess_wrongStatus_failed() { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.updateAccess(DATABASE_2_DASHBOARD_UID, USER_2_USERNAME, PermissionTypeDto.VIEW); + }); + } + + @Test + public void updateAccess_connection_failed() { + + /* mock */ + doThrow(HttpServerErrorException.ServiceUnavailable.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceConnectionException.class, () -> { + dashboardServiceGateway.updateAccess(DATABASE_2_DASHBOARD_UID, USER_2_USERNAME, PermissionTypeDto.VIEW); + }); + } + + @Test + public void updateAccess_unauthorized_failed() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.updateAccess(DATABASE_2_DASHBOARD_UID, USER_2_USERNAME, PermissionTypeDto.VIEW); + }); + } + + @Test + public void updateAnonymousAccess_succeeds() throws DashboardServiceException, DashboardServiceConnectionException { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dashboardServiceGateway.updateAnonymousAccess(DATABASE_2_DASHBOARD_UID, DATABASE_2_BRIEF_DTO); + } + + @Test + public void updateAnonymousAccess_wrongStatus_failed() { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.updateAnonymousAccess(DATABASE_2_DASHBOARD_UID, DATABASE_2_BRIEF_DTO); + }); + } + + @Test + public void updateAnonymousAccess_connection_failed() { + + /* mock */ + doThrow(HttpServerErrorException.ServiceUnavailable.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceConnectionException.class, () -> { + dashboardServiceGateway.updateAnonymousAccess(DATABASE_2_DASHBOARD_UID, DATABASE_2_BRIEF_DTO); + }); + } + + @Test + public void updateAnonymousAccess_unauthorized_failed() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DashboardServiceException.class, () -> { + dashboardServiceGateway.updateAnonymousAccess(DATABASE_2_DASHBOARD_UID, DATABASE_2_BRIEF_DTO); + }); + } +} \ No newline at end of file diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGatewayUnitTest.java similarity index 97% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGatewayUnitTest.java index af1ecc9f1c..14df28608a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGatewayUnitTest.java @@ -1,13 +1,13 @@ -package at.tuwien.gateway; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableStatisticDto; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.gateway; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -32,7 +32,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class DataServiceGatewayUnitTest extends AbstractUnitTest { +public class DataServiceGatewayUnitTest extends BaseTest { @MockBean @Qualifier("dataServiceRestTemplate") @@ -1045,20 +1045,6 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { }); } - @Test - public void getTableStatistics_emptyBody_fails() { - - /* mock */ - when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .build()); - - /* test */ - assertThrows(DataServiceException.class, () -> { - dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); - }); - } - @Test public void updateTable_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGatewayIntegrationTest.java similarity index 87% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGatewayIntegrationTest.java index 583fa4c440..40d8eab970 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGatewayIntegrationTest.java @@ -1,10 +1,10 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.impl.KeycloakGatewayImpl; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.KeycloakUtils; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.impl.KeycloakGatewayImpl; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.KeycloakUtils; import dasniko.testcontainers.keycloak.KeycloakContainer; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -20,15 +20,13 @@ import org.testcontainers.images.PullPolicy; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.util.UUID; - import static org.junit.jupiter.api.Assertions.*; @Log4j2 @SpringBootTest @Testcontainers @ExtendWith(SpringExtension.class) -public class KeycloakGatewayIntegrationTest extends AbstractUnitTest { +public class KeycloakGatewayIntegrationTest extends BaseTest { @Autowired private KeycloakGatewayImpl keycloakGateway; @@ -38,13 +36,12 @@ public class KeycloakGatewayIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* auth service */ keycloakUtils.deleteUser(USER_1_USERNAME); } @Container - private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) + private static final KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) .withImagePullPolicy(PullPolicy.alwaysPull()) .withAdminUsername("admin") .withAdminPassword("admin") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGatewayUnitTest.java similarity index 82% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGatewayUnitTest.java index bcd27107bc..31d8baeab5 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGatewayUnitTest.java @@ -1,13 +1,12 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.exception.OrcidNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.OrcidNotFoundException; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpEntity; @@ -16,16 +15,17 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class OrcidGatewayUnitTest extends AbstractUnitTest { +public class OrcidGatewayUnitTest extends BaseTest { @MockBean private RestTemplate restTemplate; @@ -33,6 +33,9 @@ public class OrcidGatewayUnitTest extends AbstractUnitTest { @Autowired private OrcidGateway orcidGateway; + public OrcidGatewayUnitTest() throws IOException { + } + @Test public void findByUrl_succeeds() throws OrcidNotFoundException { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGatewayUnitTest.java similarity index 77% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGatewayUnitTest.java index ff9d4f741c..b8b100c413 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGatewayUnitTest.java @@ -1,15 +1,18 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.ror.RorDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.RorNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; @@ -20,7 +23,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class RorGatewayUnitTest extends AbstractUnitTest { +public class RorGatewayUnitTest extends BaseTest { @MockBean private RestTemplate restTemplate; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGatewayUnitTest.java similarity index 93% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGatewayUnitTest.java index b39dd06bac..3ff4a3a508 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGatewayUnitTest.java @@ -1,8 +1,10 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SearchServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SearchServiceException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,7 +27,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class SearchServiceGatewayUnitTest extends AbstractUnitTest { +public class SearchServiceGatewayUnitTest extends BaseTest { @MockBean @Qualifier("searchServiceRestTemplate") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandlerTest.java similarity index 95% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandlerTest.java index 87d7d0185a..7ab54f089c 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/handlers/ApiExceptionHandlerTest.java @@ -1,8 +1,8 @@ -package at.tuwien.handlers; +package at.ac.tuwien.ifs.dbrepo.handlers; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import com.auth0.jwt.exceptions.TokenExpiredException; import jakarta.ws.rs.NotAuthorizedException; import lombok.extern.log4j.Log4j2; @@ -23,14 +23,14 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import static at.tuwien.test.utils.EndpointUtils.getErrorCodes; -import static at.tuwien.test.utils.EndpointUtils.getExceptions; +import static at.ac.tuwien.ifs.dbrepo.core.test.utils.EndpointUtils.getErrorCodes; +import static at.ac.tuwien.ifs.dbrepo.core.test.utils.EndpointUtils.getExceptions; import static org.junit.jupiter.api.Assertions.*; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest -public class ApiExceptionHandlerTest extends AbstractUnitTest { +public class ApiExceptionHandlerTest extends BaseTest { @Autowired private ApiExceptionHandler apiExceptionHandler; @@ -49,7 +49,7 @@ public class ApiExceptionHandlerTest extends AbstractUnitTest { final Method method = optional.get(); /* exception */ Assertions.assertNotNull(exception.getDeclaredAnnotation(ResponseStatus.class).code()); - Assertions.assertNotEquals(exception.getDeclaredAnnotation(ResponseStatus.class).code(), HttpStatus.INTERNAL_SERVER_ERROR); + Assertions.assertNotEquals(HttpStatus.INTERNAL_SERVER_ERROR, exception.getDeclaredAnnotation(ResponseStatus.class).code()); Assertions.assertNotNull(exception.getDeclaredAnnotation(ResponseStatus.class).reason(), "Exception " + exception.getName() + " does not provide a reason code"); assertTrue(errorCodes.contains(exception.getDeclaredAnnotation(ResponseStatus.class).reason()), "Exception code " + exception.getDeclaredAnnotation(ResponseStatus.class).reason() + " does have a reason code mapped in localized ui error messages"); /* handler method */ @@ -239,6 +239,32 @@ public class ApiExceptionHandlerTest extends AbstractUnitTest { assertEquals("error.user.credentials", body.getCode()); } + @Test + public void handle_dashboardServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DashboardServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.dashboard.connection", body.getCode()); + } + + @Test + public void handle_dashboardServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DashboardServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.dashboard.invalid", body.getCode()); + } + @Test public void handle_dataServiceConnectionException_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mapper/MetadataMapperUnitTest.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mapper/MetadataMapperUnitTest.java index ac1103d2e5..0b3c5fdf68 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mapper/MetadataMapperUnitTest.java @@ -1,14 +1,12 @@ -package at.tuwien.mapper; - -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.entities.database.View; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierType; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.mapper; + +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierType; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -26,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.*; @Log4j2 @SpringBootTest -public class MetadataMapperUnitTest extends AbstractUnitTest { +public class MetadataMapperUnitTest extends BaseTest { private final DateTimeFormatter mariaDbFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]") .withZone(ZoneId.of("UTC")); @@ -34,11 +32,6 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { @Autowired private MetadataMapper metadataMapper; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void mapMariaDbInstant_succeeds() { final String timestamp = "2023-01-08 08:49:29"; @@ -72,7 +65,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { public void identifierCreateDtoToIdentifier_withDoi_succeeds() { /* test */ - final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_1_CREATE_WITH_DOI_DTO); + final Identifier response = metadataMapper.createIdentifierDtoToIdentifier(IDENTIFIER_1_CREATE_WITH_DOI_DTO); assertNull(response.getDatabase()); assertNull(response.getViewId()); assertNull(response.getQueryId()); @@ -85,7 +78,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { public void identifierCreateDtoToIdentifier_subset_succeeds() { /* test */ - final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_2_CREATE_DTO); + final Identifier response = metadataMapper.createIdentifierDtoToIdentifier(IDENTIFIER_2_CREATE_DTO); assertNull(response.getDatabase()); assertNull(response.getViewId()); assertNull(response.getTableId()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/ActuatorEndpointMvcTest.java similarity index 90% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/ActuatorEndpointMvcTest.java index a7a83a6184..7d8c74437a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/ActuatorEndpointMvcTest.java @@ -1,6 +1,6 @@ -package at.tuwien.mvc; +package at.ac.tuwien.ifs.dbrepo.mvc; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,7 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @SpringBootTest @AutoConfigureObservability -public class ActuatorEndpointMvcTest extends AbstractUnitTest { +public class ActuatorEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; 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/ac/tuwien/ifs/dbrepo/mvc/AuthenticationPrivilegedIntegrationMvcTest.java similarity index 87% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/AuthenticationPrivilegedIntegrationMvcTest.java index e6535ccf19..9a6354453b 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/ac/tuwien/ifs/dbrepo/mvc/AuthenticationPrivilegedIntegrationMvcTest.java @@ -1,16 +1,16 @@ -package at.tuwien.mvc; - -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.AuthServiceConnectionException; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.CredentialsInvalidException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.KeycloakUtils; +package at.ac.tuwien.ifs.dbrepo.mvc; + +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.CredentialsInvalidException; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.KeycloakUtils; import dasniko.testcontainers.keycloak.KeycloakContainer; import jakarta.transaction.Transactional; import lombok.extern.log4j.Log4j2; @@ -41,7 +41,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @Testcontainers @SpringBootTest -public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest { +public class AuthenticationPrivilegedIntegrationMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; @@ -65,7 +65,7 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest private KeycloakGateway keycloakGateway; @Container - private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) + private static final KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) .withImagePullPolicy(PullPolicy.alwaysPull()) .withAdminUsername("admin") .withAdminPassword("admin") @@ -79,7 +79,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest @BeforeEach public void beforeEach() throws AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_LOCAL)); @@ -115,7 +114,7 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) .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("X-Jdbc-Method", IMAGE_1_JDBC_METHOD)) .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method X-Host X-Port")) .andExpect(status().isOk()); } @@ -134,7 +133,7 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) .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("X-Jdbc-Method", IMAGE_1_JDBC_METHOD)) .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method X-Host X-Port")) .andExpect(status().isOk()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/IdentifierEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/IdentifierEndpointMvcTest.java similarity index 86% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/IdentifierEndpointMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/IdentifierEndpointMvcTest.java index 2594eb70b1..b0cdca73e2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/IdentifierEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/IdentifierEndpointMvcTest.java @@ -1,7 +1,7 @@ -package at.tuwien.mvc; +package at.ac.tuwien.ifs.dbrepo.mvc; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.gateway.OrcidGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.OrcidGateway; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import com.mchange.io.FileUtils; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; @@ -16,7 +16,8 @@ import org.springframework.test.web.servlet.MockMvc; import java.io.File; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -26,7 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc @SpringBootTest -public class IdentifierEndpointMvcTest extends AbstractUnitTest { +public class IdentifierEndpointMvcTest extends BaseTest { @MockBean private OrcidGateway orcidGateway; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/MetadataEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/MetadataEndpointMvcTest.java similarity index 93% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/MetadataEndpointMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/MetadataEndpointMvcTest.java index 7f9ba9743d..870251323e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/MetadataEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/MetadataEndpointMvcTest.java @@ -1,10 +1,9 @@ -package at.tuwien.mvc; +package at.ac.tuwien.ifs.dbrepo.mvc; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.config.MetadataConfig; +import at.ac.tuwien.ifs.dbrepo.config.MetadataConfig; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -28,7 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @AutoConfigureMockMvc @SpringBootTest -public class MetadataEndpointMvcTest extends AbstractUnitTest { +public class MetadataEndpointMvcTest extends BaseTest { @MockBean private IdentifierRepository identifierRepository; @@ -39,11 +38,6 @@ public class MetadataEndpointMvcTest extends AbstractUnitTest { @Autowired private MockMvc mockMvc; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void identify_succeeds() throws Exception { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/OpenApiEndpointMvcTest.java similarity index 91% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/OpenApiEndpointMvcTest.java index d685ca65cd..0d37944ba9 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/OpenApiEndpointMvcTest.java @@ -1,8 +1,8 @@ -package at.tuwien.mvc; +package at.ac.tuwien.ifs.dbrepo.mvc; -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.endpoints.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto; +import at.ac.tuwien.ifs.dbrepo.endpoints.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -30,7 +30,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ExtendWith(SpringExtension.class) @AutoConfigureMockMvc @SpringBootTest -public class OpenApiEndpointMvcTest extends AbstractUnitTest { +public class OpenApiEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; @@ -113,6 +113,7 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { } private void generic_openApiDocs(Class<?> endpoint) { + final String packageScope = "at.ac.tuwien.ifs.dbrepo"; final List<Method> methods = Arrays.stream(endpoint.getMethods()) .filter(m -> m.getDeclaringClass().equals(endpoint)) .toList(); @@ -120,9 +121,9 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { final List<Class<?>> exceptions = Arrays.stream(m.getExceptionTypes()) .toList(); final List<Class<?>> invalidExceptions = exceptions.stream() - .filter(e -> !e.getName().startsWith("at.tuwien.")) + .filter(e -> !e.getName().startsWith(packageScope)) .toList(); - assertTrue(invalidExceptions.isEmpty(), "method '" + m.getName() + "' throws exception(s) outside package scope at.tuwien: " + invalidExceptions.stream().map(Class::getName).toList()); + assertTrue(invalidExceptions.isEmpty(), "method '" + m.getName() + "' throws exception(s) outside package scope " + packageScope + ": " + invalidExceptions.stream().map(Class::getName).toList()); exceptions.forEach(exception -> { assertNotNull(m.getDeclaredAnnotation(Operation.class).summary()); final int status = exception.getAnnotation(ResponseStatus.class) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/PrometheusEndpointMvcTest.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/PrometheusEndpointMvcTest.java index 2adc2f0647..f3a15c7f3f 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/mvc/PrometheusEndpointMvcTest.java @@ -1,14 +1,15 @@ -package at.tuwien.mvc; - -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.api.database.DatabaseModifyImageDto; -import at.tuwien.api.database.DatabaseModifyVisibilityDto; -import at.tuwien.api.database.DatabaseTransferDto; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.config.MetricsConfig; -import at.tuwien.endpoints.*; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.mvc; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyImageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseTransferDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.config.MetricsConfig; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.endpoints.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import io.micrometer.observation.tck.TestObservationRegistry; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; @@ -38,7 +39,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest @Import(MetricsConfig.class) @AutoConfigureObservability -public class PrometheusEndpointMvcTest extends AbstractUnitTest { +public class PrometheusEndpointMvcTest extends BaseTest { @Autowired private MockMvc mockMvc; @@ -150,7 +151,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - containerEndpoint.create(CreateContainerDto.builder().name(CONTAINER_1_NAME).imageId(IMAGE_1_ID).build()); + containerEndpoint.create(CreateContainerDto.builder().name(CONTAINER_1_NAME).imageId(CONTAINER_1_ID).build()); } catch (Exception e) { /* ignore */ } @@ -281,17 +282,17 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - imageEndpoint.findById(IMAGE_1_ID); + imageEndpoint.findById(CONTAINER_1_ID); } catch (Exception e) { /* ignore */ } try { - imageEndpoint.update(IMAGE_1_ID, IMAGE_1_CHANGE_DTO); + imageEndpoint.update(CONTAINER_1_ID, IMAGE_1_CHANGE_DTO); } catch (Exception e) { /* ignore */ } try { - imageEndpoint.delete(IMAGE_1_ID); + imageEndpoint.delete(CONTAINER_1_ID); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AccessServiceUnitTest.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AccessServiceUnitTest.java index 1c96e6283d..17a7cb32f8 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AccessServiceUnitTest.java @@ -1,15 +1,14 @@ -package at.tuwien.service; - -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.entities.database.AccessType; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.repository.DatabaseRepository; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.AccessType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +33,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class AccessServiceUnitTest extends AbstractUnitTest { +public class AccessServiceUnitTest extends BaseTest { @MockBean private DatabaseRepository databaseRepository; @@ -50,11 +49,6 @@ public class AccessServiceUnitTest extends AbstractUnitTest { @Autowired private AccessService accessService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void list_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationServiceIntegrationTest.java similarity index 80% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationServiceIntegrationTest.java index d655a25cf1..016e0f949b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationServiceIntegrationTest.java @@ -1,13 +1,12 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.KeycloakUtils; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.KeycloakUtils; import dasniko.testcontainers.keycloak.KeycloakContainer; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +26,7 @@ import java.util.UUID; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest @ExtendWith(SpringExtension.class) -public class AuthenticationServiceIntegrationTest extends AbstractUnitTest { +public class AuthenticationServiceIntegrationTest extends BaseTest { @Autowired private AuthenticationService authenticationService; @@ -38,13 +37,8 @@ public class AuthenticationServiceIntegrationTest extends AbstractUnitTest { @Autowired private KeycloakUtils keycloakUtils; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Container - private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) + private static final KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) .withImagePullPolicy(PullPolicy.alwaysPull()) .withAdminUsername("admin") .withAdminPassword("admin") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/BrokerServiceIntegrationTest.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/BrokerServiceIntegrationTest.java index d04409c87b..ada49fbd9a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/BrokerServiceIntegrationTest.java @@ -1,18 +1,17 @@ -package at.tuwien.service; - -import at.tuwien.api.amqp.GrantExchangePermissionsDto; -import at.tuwien.api.amqp.GrantVirtualHostPermissionsDto; -import at.tuwien.api.amqp.TopicPermissionDto; -import at.tuwien.api.amqp.VirtualHostPermissionDto; -import at.tuwien.config.RabbitConfig; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.BrokerServiceConnectionException; -import at.tuwien.exception.BrokerServiceException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.AmqpUtils; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantExchangePermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantVirtualHostPermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.TopicPermissionDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.VirtualHostPermissionDto; +import at.ac.tuwien.ifs.dbrepo.config.RabbitConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.BrokerServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.BrokerServiceException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.AmqpUtils; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -public class BrokerServiceIntegrationTest extends AbstractUnitTest { +public class BrokerServiceIntegrationTest extends BaseTest { @Autowired private RabbitConfig rabbitConfig; @@ -54,11 +53,6 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { registry.add("dbrepo.endpoints.brokerService", rabbitContainer::getHttpUrl); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void updatePermissions_empty_succeeds() throws BrokerServiceException, BrokerServiceConnectionException { @@ -155,7 +149,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { BrokerServiceConnectionException { /* test */ - final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of(DATABASE_1_USER_1_READ_ACCESS)); + final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of(DATABASE_1.getAccesses().get(0))); assertEquals(USER_1_USERNAME, permissions.getUser()); assertEquals(REALM_DBREPO_NAME, permissions.getVhost()); assertEquals(DATABASE_1_EXCHANGE, permissions.getExchange()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ConceptServiceUnitTest.java similarity index 80% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ConceptServiceUnitTest.java index 164f335eb7..67f14f3ebb 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ConceptServiceUnitTest.java @@ -1,11 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.exception.ConceptNotFoundException; -import at.tuwien.repository.ConceptRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.entities.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.exception.ConceptNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.ConceptRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -23,7 +22,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class ConceptServiceUnitTest extends AbstractUnitTest { +public class ConceptServiceUnitTest extends BaseTest { @MockBean private ConceptRepository conceptRepository; @@ -31,11 +30,6 @@ public class ConceptServiceUnitTest extends AbstractUnitTest { @Autowired private ConceptService conceptService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findAll_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ContainerServiceUnitTest.java similarity index 84% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ContainerServiceUnitTest.java index a6fbbf7592..e8e17ea3ae 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ContainerServiceUnitTest.java @@ -1,15 +1,14 @@ -package at.tuwien.service; - -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.entities.container.Container; -import at.tuwien.exception.ContainerAlreadyExistsException; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.ImageRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.ImageRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -32,7 +31,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class ContainerServiceUnitTest extends AbstractUnitTest { +public class ContainerServiceUnitTest extends BaseTest { @MockBean private ContainerRepository containerRepository; @@ -43,22 +42,17 @@ public class ContainerServiceUnitTest extends AbstractUnitTest { @Autowired private ContainerService containerService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void create_succeeds() throws ContainerAlreadyExistsException, ImageNotFoundException { final CreateContainerDto request = CreateContainerDto.builder() - .imageId(IMAGE_1_ID) + .imageId(CONTAINER_1_ID) .name(CONTAINER_1_NAME) .build(); /* mock */ when(containerRepository.findByInternalName(CONTAINER_1_NAME)) .thenReturn(Optional.empty()); - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.of(IMAGE_1)); when(containerRepository.save(any(Container.class))) .thenReturn(CONTAINER_1); @@ -71,12 +65,12 @@ public class ContainerServiceUnitTest extends AbstractUnitTest { @Test public void create_containerExists_fails() { final CreateContainerDto request = CreateContainerDto.builder() - .imageId(IMAGE_1_ID) + .imageId(CONTAINER_1_ID) .name(CONTAINER_1_NAME) .build(); /* mock */ - when(containerRepository.findByInternalName(CONTAINER_1_INTERNALNAME)) + when(containerRepository.findByInternalName(CONTAINER_1_INTERNAL_NAME)) .thenReturn(Optional.of(CONTAINER_1)); /* test */ @@ -95,7 +89,7 @@ public class ContainerServiceUnitTest extends AbstractUnitTest { /* mock */ when(containerRepository.findByInternalName(CONTAINER_1_NAME)) .thenReturn(Optional.empty()); - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.empty()); /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DataCiteIdentifierServicePersistenceTest.java similarity index 89% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DataCiteIdentifierServicePersistenceTest.java index 260aebe7be..b96bc4bad2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DataCiteIdentifierServicePersistenceTest.java @@ -1,20 +1,21 @@ -package at.tuwien.service; - -import at.tuwien.api.datacite.DataCiteBody; -import at.tuwien.api.datacite.doi.DataCiteDoi; -import at.tuwien.api.identifier.BibliographyTypeDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.identifier.Creator; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierStatusType; -import at.tuwien.entities.identifier.NameIdentifierSchemeType; -import at.tuwien.exception.*; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.DataCiteBody; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.DataCiteDoi; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Creator; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierStatusType; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.NameIdentifierSchemeType; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -45,8 +46,8 @@ import static org.mockito.Mockito.when; @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -@SpringBootTest(properties = "spring.profiles.active:local,junit,doi") -public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { +@SpringBootTest(properties = "spring.profiles.active=local,junit,doi") +public class DataCiteIdentifierServicePersistenceTest extends BaseTest { @MockBean private SearchServiceGateway searchServiceGateway; @@ -75,7 +76,6 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_5)); @@ -89,7 +89,7 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { /* test */ final List<Identifier> response = dataCiteIdentifierService.findAll(null, null, null, null, null); assertEquals(7, response.size()); - for (UUID id : List.of(IDENTIFIER_1_ID, IDENTIFIER_2_ID, IDENTIFIER_3_ID, IDENTIFIER_4_ID, IDENTIFIER_5_ID, IDENTIFIER_6_ID, IDENTIFIER_7_ID)) { + for (UUID id : List.of(IDENTIFIER_1_ID, IDENTIFIER_2_ID, IDENTIFIER_3_ID, IDENTIFIER_4_ID, IDENTIFIER_5_ID, IDENTIFIER_6_ID, IDENTIFIER_7.getId())) { assertTrue(response.stream().map(Identifier::getId).toList().contains(id)); } } @@ -202,7 +202,7 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { @Test public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, DataServiceException, QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + SearchServiceConnectionException, ViewNotFoundException, ExternalServiceException { final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) .body(IDENTIFIER_1_DATA_CITE); @@ -228,7 +228,7 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { /* test */ final Identifier response = dataCiteIdentifierService.publish(IDENTIFIER_7); - assertEquals(IDENTIFIER_7_ID, response.getId()); + assertEquals(IDENTIFIER_7.getId(), response.getId()); assertEquals(IdentifierStatusType.PUBLISHED, response.getStatus()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServicePersistenceTest.java similarity index 66% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServicePersistenceTest.java index b1886aa835..2bb1d9e89d 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServicePersistenceTest.java @@ -1,13 +1,12 @@ -package at.tuwien.service; - -import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.Database; -import at.tuwien.exception.DatabaseNotFoundException; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,13 +20,12 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; @Log4j2 @SpringBootTest @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) -public class DatabaseServicePersistenceTest extends AbstractUnitTest { +public class DatabaseServicePersistenceTest extends BaseTest { @Autowired private DatabaseService databaseService; @@ -46,7 +44,6 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_5)); @@ -68,16 +65,7 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { public void findAllPublicOrSchemaPublicByInternalName_privateEmpty_succeeds() { /* test */ - final List<Database> response = databaseService.findAllPublicOrSchemaPublicByInternalName(DATABASE_1_INTERNALNAME); - assertEquals(0, response.size()); - } - - @Test - @Transactional(readOnly = true) - public void findAllAtLestReadAccess_privateNoAccessEmpty_succeeds() { - - /* test */ - final List<Database> response = databaseService.findAllAtLestReadAccess(USER_4_ID); + final List<Database> response = databaseService.findAllPublicOrSchemaPublicByInternalName(DATABASE_1_INTERNAL_NAME); assertEquals(0, response.size()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServiceUnitTest.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServiceUnitTest.java index 85829f6ae6..b2f42bd167 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseServiceUnitTest.java @@ -1,18 +1,17 @@ -package at.tuwien.service; - -import at.tuwien.api.database.DatabaseModifyVisibilityDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -32,7 +31,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class DatabaseServiceUnitTest extends AbstractUnitTest { +public class DatabaseServiceUnitTest extends BaseTest { @MockBean private SearchServiceGateway searchServiceGateway; @@ -46,11 +45,6 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Autowired private DatabaseService databaseService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findAll_succeeds() { /* mock */ @@ -215,8 +209,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Test public void updateViewMetadata_oneMissing_succeeds() throws SearchServiceException, DataServiceException, - QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, - DataServiceConnectionException, ViewNotFoundException { + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { /* mock */ when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) @@ -233,8 +227,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Test public void updateViewMetadata_allKnown_succeeds() throws SearchServiceException, DataServiceException, - QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, - DataServiceConnectionException, ViewNotFoundException { + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { /* mock */ when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) @@ -251,8 +245,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Test public void updateTableMetadata_empty_succeeds() throws TableNotFoundException, SearchServiceException, - MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, - SearchServiceConnectionException, DataServiceConnectionException { + MalformedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException { /* mock */ when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) @@ -269,8 +263,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Test public void updateTableMetadata_allKnown_succeeds() throws TableNotFoundException, SearchServiceException, - MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, - SearchServiceConnectionException, DataServiceConnectionException { + MalformedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException { /* mock */ when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) @@ -287,8 +281,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { @Test public void updateTableMetadata_oneMissing_succeeds() throws TableNotFoundException, SearchServiceException, - MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, - SearchServiceConnectionException, DataServiceConnectionException { + MalformedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException { /* mock */ when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) @@ -303,7 +297,7 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { assertNotNull(response); final Optional<Table> optional = response.getTables() .stream() - .filter(t -> t.getInternalName().equals(TABLE_5_INTERNALNAME)) + .filter(t -> t.getInternalName().equals(TABLE_5_INTERNAL_NAME)) .findFirst(); assertTrue(optional.isPresent()); final Table table = optional.get(); @@ -513,9 +507,9 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - protected Database generic_create() throws DataServiceException, - DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, - ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException { + protected Database generic_create() throws DataServiceException, DataServiceConnectionException, + UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, + SearchServiceConnectionException, DashboardServiceException, DashboardServiceConnectionException { /* mock */ when(searchServiceGateway.update(any(Database.class))) @@ -525,7 +519,7 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { /* test */ final Database response = databaseService.create(CONTAINER_1, DATABASE_1_CREATE, USER_1, List.of(USER_LOCAL)); - assertTrue(response.getInternalName().startsWith(DATABASE_1_INTERNALNAME)); + assertTrue(response.getInternalName().startsWith(DATABASE_1_INTERNAL_NAME)); assertNotNull(response.getContainer()); assertNotNull(response.getTables()); assertNotNull(response.getViews()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/EntityServiceUnitTest.java similarity index 86% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/EntityServiceUnitTest.java index afe3b6e2b8..27987dd6b4 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/EntityServiceUnitTest.java @@ -1,11 +1,12 @@ -package at.tuwien.service; - -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.exception.*; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.TableColumnEntityDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.OntologyNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SemanticEntityNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -24,7 +25,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class EntityServiceUnitTest extends AbstractUnitTest { +public class EntityServiceUnitTest extends BaseTest { @MockBean private OntologyService ontologyService; @@ -32,11 +33,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { @Autowired private EntityService entityService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findByLabel_wikidataSparql_succeeds() throws MalformedException { @@ -49,7 +45,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { assertFalse(response.isEmpty()); final EntityDto entity0 = response.get(0); assertNotNull(entity0.getUri()); - log.trace("found concept {}", entity0); } @Test @@ -66,7 +61,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { assertEquals(1, response.size()); final EntityDto entity0 = response.get(0); assertNotNull(entity0.getUri()); - log.trace("found concept {}", entity0); } @Test @@ -82,7 +76,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { /* test */ final EntityDto response = entityService.findOneByUri(CONCEPT_1_URI); assertNotNull(response.getUri()); - log.trace("found concept {}", response); } @Test @@ -97,7 +90,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { assertFalse(response.isEmpty()); final EntityDto entity0 = response.get(0); assertNotNull(entity0.getUri()); - log.trace("found unit {}", entity0); } @Test @@ -114,7 +106,6 @@ public class EntityServiceUnitTest extends AbstractUnitTest { assertEquals(1, response.size()); final EntityDto entity0 = response.get(0); assertNotNull(entity0.getUri()); - log.trace("found unit {}", entity0); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierServicePersistenceTest.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierServicePersistenceTest.java index c053afa51d..259680ad1a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierServicePersistenceTest.java @@ -1,18 +1,19 @@ -package at.tuwien.service; - -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.identifier.BibliographyTypeDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.License; -import at.tuwien.entities.identifier.*; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -41,7 +42,7 @@ import static org.mockito.Mockito.when; @SpringBootTest @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -public class IdentifierServicePersistenceTest extends AbstractUnitTest { +public class IdentifierServicePersistenceTest extends BaseTest { @MockBean private DataServiceGateway dataServiceGateway; @@ -70,7 +71,6 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_5)); @@ -84,7 +84,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { /* test */ final List<Identifier> response = identifierService.findAll(null, null, null, null, null); assertEquals(7, response.size()); - for (UUID id : List.of(IDENTIFIER_1_ID, IDENTIFIER_2_ID, IDENTIFIER_3_ID, IDENTIFIER_4_ID, IDENTIFIER_5_ID, IDENTIFIER_6_ID, IDENTIFIER_7_ID)) { + for (UUID id : List.of(IDENTIFIER_1_ID, IDENTIFIER_2_ID, IDENTIFIER_3_ID, IDENTIFIER_4_ID, IDENTIFIER_5_ID, IDENTIFIER_6_ID, IDENTIFIER_7.getId())) { assertTrue(response.stream().map(Identifier::getId).toList().contains(id)); } } @@ -345,7 +345,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { final List<IdentifierTitle> titles = response.getTitles(); assertEquals(2, titles.size()); final IdentifierTitle title0 = titles.get(0); - assertEquals(IDENTIFIER_1_TITLE_1_TITLE, title0.getTitle()); + assertEquals(IDENTIFIER_1.getTitles().get(0).getTitle(), title0.getTitle()); assertEquals(IDENTIFIER_1_TITLE_1_LANG, title0.getLanguage()); assertEquals(IDENTIFIER_1_TITLE_1_TYPE, title0.getTitleType()); final IdentifierTitle title1 = titles.get(1); @@ -357,7 +357,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { final List<IdentifierDescription> descriptions = response.getDescriptions(); final IdentifierDescription description0 = descriptions.get(0); assertNotNull(description0.getId()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION, description0.getDescription()); + assertEquals(IDENTIFIER_1.getDescriptions().get(0).getDescription(), description0.getDescription()); assertEquals(IDENTIFIER_1_DESCRIPTION_1_LANG, description0.getLanguage()); assertEquals(IDENTIFIER_1_DESCRIPTION_1_TYPE, description0.getDescriptionType()); assertNotNull(response.getCreators()); @@ -391,7 +391,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { final List<IdentifierTitle> titles = response.getTitles(); assertEquals(1, titles.size()); final IdentifierTitle title0 = titles.get(0); - assertEquals(IDENTIFIER_1_TITLE_1_TITLE, title0.getTitle()); + assertEquals(IDENTIFIER_1.getTitles().get(0).getTitle(), title0.getTitle()); assertEquals(IDENTIFIER_1_TITLE_1_LANG, title0.getLanguage()); assertEquals(IDENTIFIER_1_TITLE_1_TYPE, title0.getTitleType()); assertNotNull(response.getDescriptions()); @@ -476,8 +476,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { @Test public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, DataServiceException, QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, - ExternalServiceException { + SearchServiceConnectionException, ViewNotFoundException, ExternalServiceException { /* test */ final Identifier response = identifierService.create(DATABASE_1, USER_1, IDENTIFIER_1_CREATE_WITH_DOI_DTO); @@ -491,7 +490,7 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { /* test */ final Identifier response = identifierService.publish(IDENTIFIER_7); - assertEquals(IDENTIFIER_7_ID, response.getId()); + assertEquals(IDENTIFIER_7.getId(), response.getId()); assertEquals(IdentifierStatusType.PUBLISHED, response.getStatus()); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServicePersistenceTest.java similarity index 65% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServicePersistenceTest.java index fb501cb281..8e597f5c6b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServicePersistenceTest.java @@ -1,11 +1,11 @@ -package at.tuwien.service; - -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.ImageRepository; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.ImageRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.*; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) @SpringBootTest -public class ImageServicePersistenceTest extends AbstractUnitTest { +public class ImageServicePersistenceTest extends BaseTest { @Autowired private ImageService imageService; @@ -34,7 +34,6 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ imageRepository.save(IMAGE_1); } @@ -44,11 +43,11 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version("11.1.4") // new tag - .registry(IMAGE_1_REGISTRY) - .jdbcMethod(IMAGE_1_JDBC) + .registry(IMAGE_1.getRegistry()) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .defaultPort(IMAGE_1_PORT) + .driverClass(IMAGE_1.getDriverClass()) + .defaultPort(IMAGE_1_DEFAULT_PORT) .isDefault(false) .build(); @@ -61,9 +60,9 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) - .defaultPort(IMAGE_1_PORT) - .driverClass(IMAGE_1_DRIVER) - .jdbcMethod(IMAGE_1_JDBC) + .defaultPort(IMAGE_1_DEFAULT_PORT) + .driverClass(IMAGE_1.getDriverClass()) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .dialect(IMAGE_1_DIALECT) .isDefault(IMAGE_1_IS_DEFAULT) .build(); @@ -79,10 +78,10 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name("mariadb") .version("10.5") - .registry(IMAGE_1_REGISTRY) - .defaultPort(IMAGE_1_PORT) - .driverClass(IMAGE_1_DRIVER) - .jdbcMethod(IMAGE_1_JDBC) + .registry(IMAGE_1.getRegistry()) + .defaultPort(IMAGE_1_DEFAULT_PORT) + .driverClass(IMAGE_1.getDriverClass()) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .dialect(IMAGE_1_DIALECT) .isDefault(true) // <<<< .build(); @@ -94,11 +93,11 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { } @Test - public void delete_hasNoContainer_succeeds() { + public void delete_hasNoContainer_succeeds() { /* test */ imageService.delete(IMAGE_1); - assertTrue(imageRepository.findById(IMAGE_1_ID).isEmpty()); + assertTrue(imageRepository.findById(CONTAINER_1_ID).isEmpty()); assertFalse(containerRepository.findById(CONTAINER_1_ID).isPresent()); /* container should NEVER be deletable in the metadata db */ } @@ -107,7 +106,7 @@ public class ImageServicePersistenceTest extends AbstractUnitTest { /* test */ imageService.delete(IMAGE_1); - assertTrue(imageRepository.findById(IMAGE_1_ID).isEmpty()); + assertTrue(imageRepository.findById(CONTAINER_1_ID).isEmpty()); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServiceUnitTest.java similarity index 76% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServiceUnitTest.java index dc77ff263b..4ad64bfabe 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ImageServiceUnitTest.java @@ -1,16 +1,14 @@ -package at.tuwien.service; - -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.container.image.ImageChangeDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.repository.ImageRepository; -import at.tuwien.service.impl.ImageServiceImpl; -import jakarta.validation.ConstraintViolationException; -import org.junit.jupiter.api.BeforeEach; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageChangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.ImageRepository; +import at.ac.tuwien.ifs.dbrepo.service.impl.ImageServiceImpl; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -23,11 +21,12 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @ExtendWith(SpringExtension.class) @SpringBootTest -public class ImageServiceUnitTest extends AbstractUnitTest { +public class ImageServiceUnitTest extends BaseTest { @MockBean private ImageRepository imageRepository; @@ -35,11 +34,6 @@ public class ImageServiceUnitTest extends AbstractUnitTest { @Autowired private ImageService imageService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void getAll_succeeds() { @@ -58,11 +52,11 @@ public class ImageServiceUnitTest extends AbstractUnitTest { public void getById_succeeds() throws ImageNotFoundException { /* mock */ - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.of(IMAGE_1)); /* test */ - final ContainerImage response = imageService.find(IMAGE_1_ID); + final ContainerImage response = imageService.find(CONTAINER_1_ID); assertEquals(IMAGE_1_NAME, response.getName()); assertEquals(IMAGE_1_VERSION, response.getVersion()); } @@ -71,12 +65,12 @@ public class ImageServiceUnitTest extends AbstractUnitTest { public void getById_notFound_fails() { /* mock */ - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.empty()); /* test */ assertThrows(ImageNotFoundException.class, () -> { - imageService.find(IMAGE_1_ID); + imageService.find(CONTAINER_1_ID); }); } @@ -85,7 +79,7 @@ public class ImageServiceUnitTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .build(); /* mock */ @@ -103,7 +97,7 @@ public class ImageServiceUnitTest extends AbstractUnitTest { final ImageCreateDto request = ImageCreateDto.builder() .name(IMAGE_1_NAME) .version("10.5") - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .isDefault(true) .build(); @@ -123,11 +117,11 @@ public class ImageServiceUnitTest extends AbstractUnitTest { public void update_succeeds() { final ImageServiceImpl mockImageService = mock(ImageServiceImpl.class); final ImageChangeDto request = ImageChangeDto.builder() - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .build(); /* mock */ - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.of(IMAGE_1)); when(imageRepository.save(any())) .thenReturn(IMAGE_1); @@ -148,7 +142,7 @@ public class ImageServiceUnitTest extends AbstractUnitTest { .build(); /* mock */ - when(imageRepository.findById(IMAGE_1_ID)) + when(imageRepository.findById(CONTAINER_1_ID)) .thenReturn(Optional.of(IMAGE_1)); when(imageRepository.save(any())) .thenReturn(IMAGE_1); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/LicenseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/LicenseServiceUnitTest.java similarity index 79% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/LicenseServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/LicenseServiceUnitTest.java index a73ce8df24..417c50424f 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/LicenseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/LicenseServiceUnitTest.java @@ -1,11 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.exception.LicenseNotFoundException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.entities.database.License; -import at.tuwien.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; +import at.ac.tuwien.ifs.dbrepo.core.exception.LicenseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -24,7 +23,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class LicenseServiceUnitTest extends AbstractUnitTest { +public class LicenseServiceUnitTest extends BaseTest { @MockBean private LicenseRepository licenseRepository; @@ -32,11 +31,6 @@ public class LicenseServiceUnitTest extends AbstractUnitTest { @Autowired private LicenseService licenseService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findAll_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MessageServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MessageServiceUnitTest.java similarity index 85% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MessageServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MessageServiceUnitTest.java index fb7806f454..0fb606d6df 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MessageServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MessageServiceUnitTest.java @@ -1,13 +1,12 @@ -package at.tuwien.service; - -import at.tuwien.exception.MessageNotFoundException; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.repository.BannerMessageRepository; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.exception.MessageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.BannerMessageRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -23,14 +22,13 @@ import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; @Log4j2 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest @ExtendWith(SpringExtension.class) -public class MessageServiceUnitTest extends AbstractUnitTest { +public class MessageServiceUnitTest extends BaseTest { @MockBean private BannerMessageRepository bannerMessageRepository; @@ -38,11 +36,6 @@ public class MessageServiceUnitTest extends AbstractUnitTest { @Autowired private BannerMessageService bannerMessageService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findAll_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MetadataServiceUnitTest.java similarity index 88% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MetadataServiceUnitTest.java index 2f4fd3a85a..a00b44e392 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/MetadataServiceUnitTest.java @@ -1,22 +1,21 @@ -package at.tuwien.service; - -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.api.ror.RorDto; -import at.tuwien.api.user.external.ExternalMetadataDto; -import at.tuwien.api.user.external.affiliation.ExternalAffiliationDto; -import at.tuwien.exception.*; -import at.tuwien.gateway.CrossrefGateway; -import at.tuwien.gateway.OrcidGateway; -import at.tuwien.gateway.RorGateway; -import at.tuwien.oaipmh.OaiErrorType; -import at.tuwien.oaipmh.OaiListIdentifiersParameters; -import at.tuwien.oaipmh.OaiRecordParameters; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalMetadataDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.affiliation.ExternalAffiliationDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.CrossrefGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.OrcidGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.RorGateway; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiErrorType; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiListIdentifiersParameters; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiRecordParameters; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -40,7 +39,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class MetadataServiceUnitTest extends AbstractUnitTest { +public class MetadataServiceUnitTest extends BaseTest { @MockBean private OrcidGateway orcidGateway; @@ -60,11 +59,6 @@ public class MetadataServiceUnitTest extends AbstractUnitTest { @Autowired private ObjectMapper objectMapper; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void identify_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java similarity index 89% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java index 5ef5f9742b..21c2f6199a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java @@ -1,8 +1,9 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.config.S3Config; -import at.tuwien.exception.*; -import at.tuwien.test.AbstractUnitTest; +import at.ac.tuwien.ifs.dbrepo.config.S3Config; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest @ExtendWith(SpringExtension.class) -public class StorageServiceIntegrationTest extends AbstractUnitTest { +public class StorageServiceIntegrationTest extends BaseTest { @Autowired private StorageService storageService; @@ -45,7 +46,7 @@ public class StorageServiceIntegrationTest extends AbstractUnitTest { private S3Config s3Config; @Container - private static final MinIOContainer minIOContainer = new MinIOContainer("minio/minio:RELEASE.2024-06-06T09-36-42Z"); + private static final MinIOContainer minIOContainer = new MinIOContainer(MINIO_IMAGE); @DynamicPropertySource static void dynamicProperties(DynamicPropertyRegistry registry) { @@ -54,7 +55,6 @@ public class StorageServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() throws SQLException { - genesis(); /* s3 */ if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3Bucket()))) { s3Client.createBucket(CreateBucketRequest.builder() diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/TableServicePersistenceTest.java similarity index 84% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/TableServicePersistenceTest.java index 459c3b6dbe..9cdacb06b3 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/TableServicePersistenceTest.java @@ -1,24 +1,24 @@ -package at.tuwien.service; - -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnType; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; -import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; -import at.tuwien.entities.database.table.constraints.unique.Unique; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey.PrimaryKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique.Unique; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -42,7 +42,7 @@ import static org.mockito.Mockito.*; @SpringBootTest @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) -public class TableServicePersistenceTest extends AbstractUnitTest { +public class TableServicePersistenceTest extends BaseTest { @MockBean private SearchServiceGateway searchServiceGateway; @@ -70,7 +70,6 @@ public class TableServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3)); @@ -81,7 +80,9 @@ public class TableServicePersistenceTest extends AbstractUnitTest { @Test @Transactional public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, - UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, + SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, + SemanticEntityNotFoundException { final CreateTableDto request = CreateTableDto.builder() .name("New Table") .description("A wonderful table") 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/ac/tuwien/ifs/dbrepo/service/TableServiceUnitTest.java similarity index 89% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/TableServiceUnitTest.java index 9b0b7fcb1a..0c260f3ed6 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/ac/tuwien/ifs/dbrepo/service/TableServiceUnitTest.java @@ -1,28 +1,27 @@ -package at.tuwien.service; - -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableStatisticDto; -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; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.CreateForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.ColumnEnum; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.ColumnSet; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.Constraints; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -42,7 +41,7 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class TableServiceUnitTest extends AbstractUnitTest { +public class TableServiceUnitTest extends BaseTest { @MockBean private DatabaseRepository databaseRepository; @@ -68,11 +67,6 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Autowired private TableService tableService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findById_succeeds() throws TableNotFoundException, DatabaseNotFoundException { @@ -188,15 +182,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { public void updateStatistics_columnNotFound_fails() throws TableNotFoundException, DataServiceException, DataServiceConnectionException { final TableStatisticDto mock = TableStatisticDto.builder() - .columns(new HashMap<>() {{ - put("unknown_column", ColumnStatisticDto.builder() - .min(BigDecimal.valueOf(11.2)) - .max(BigDecimal.valueOf(23.1)) - .mean(BigDecimal.valueOf(13.5333)) - .median(BigDecimal.valueOf(11.4)) - .stdDev(BigDecimal.valueOf(4.2952)) - .build()); - }}) + .columns(new LinkedList<>(List.of(ColumnStatisticDto.builder() + .name("unknown_column") + .min(BigDecimal.valueOf(11.2)) + .max(BigDecimal.valueOf(23.1)) + .mean(BigDecimal.valueOf(13.5333)) + .median(BigDecimal.valueOf(11.4)) + .stdDev(BigDecimal.valueOf(4.2952)) + .build()))) .build(); /* mock */ @@ -286,7 +279,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { /* test */ final Table response = tableService.createTable(DATABASE_1, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); - assertEquals(TABLE_3_INTERNALNAME, response.getInternalName()); + assertEquals(TABLE_3_INTERNAL_NAME, response.getInternalName()); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UnitServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UnitServiceUnitTest.java similarity index 80% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UnitServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UnitServiceUnitTest.java index 67b396c660..e8e73fca32 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UnitServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UnitServiceUnitTest.java @@ -1,11 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.repository.UnitRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.entities.database.table.columns.TableColumnUnit; -import at.tuwien.exception.UnitNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.exception.UnitNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.UnitRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -24,7 +23,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class UnitServiceUnitTest extends AbstractUnitTest { +public class UnitServiceUnitTest extends BaseTest { @MockBean private UnitRepository unitRepository; @@ -32,11 +31,6 @@ public class UnitServiceUnitTest extends AbstractUnitTest { @Autowired private UnitService unitService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test @Transactional public void findAll_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceIntegrationTest.java similarity index 75% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceIntegrationTest.java index 39aed0d28e..9311d0dd34 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceIntegrationTest.java @@ -1,12 +1,11 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.utils.KeycloakUtils; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.utils.KeycloakUtils; import dasniko.testcontainers.keycloak.KeycloakContainer; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -14,7 +13,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -22,17 +20,14 @@ import org.testcontainers.images.PullPolicy; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; @Log4j2 @Testcontainers @ExtendWith(SpringExtension.class) @SpringBootTest -public class UserServiceIntegrationTest extends AbstractUnitTest { +public class UserServiceIntegrationTest extends BaseTest { @Autowired private UserRepository userRepository; @@ -45,14 +40,13 @@ public class UserServiceIntegrationTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* keycloak */ userRepository.deleteAll(); keycloakUtils.deleteUser(USER_1_USERNAME); } @Container - private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) + private static final KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) .withImagePullPolicy(PullPolicy.alwaysPull()) .withAdminUsername("admin") .withAdminPassword("admin") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServicePersistenceTest.java similarity index 84% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServicePersistenceTest.java index c224fa9a85..cb4e873ac9 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServicePersistenceTest.java @@ -1,12 +1,12 @@ -package at.tuwien.service; - -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,7 +26,7 @@ import static org.mockito.Mockito.doNothing; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest @ExtendWith(SpringExtension.class) -public class UserServicePersistenceTest extends AbstractUnitTest { +public class UserServicePersistenceTest extends BaseTest { @Autowired private UserRepository userRepository; @@ -39,7 +39,6 @@ public class UserServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ userRepository.saveAll(List.of(USER_1, USER_LOCAL)); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceUnitTest.java similarity index 82% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceUnitTest.java index c610f3ee95..8a6a29400b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/UserServiceUnitTest.java @@ -1,13 +1,12 @@ -package at.tuwien.service; - -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; -import org.junit.jupiter.api.BeforeEach; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -25,7 +24,7 @@ import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @SpringBootTest -public class UserServiceUnitTest extends AbstractUnitTest { +public class UserServiceUnitTest extends BaseTest { @MockBean private UserRepository userRepository; @@ -36,11 +35,6 @@ public class UserServiceUnitTest extends AbstractUnitTest { @Autowired private UserService userService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void findByUsername_succeeds() throws UserNotFoundException { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ViewServicePersistenceTest.java similarity index 78% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ViewServicePersistenceTest.java index 57a84965dc..33cc7db8a4 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ViewServicePersistenceTest.java @@ -1,16 +1,15 @@ -package at.tuwien.service; - -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.database.ViewColumn; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.repository.UserRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -35,7 +34,7 @@ import static org.mockito.Mockito.when; @Disabled("CI/CD") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) -public class ViewServicePersistenceTest extends AbstractUnitTest { +public class ViewServicePersistenceTest extends BaseTest { @Autowired private UserRepository userRepository; @@ -60,7 +59,6 @@ public class ViewServicePersistenceTest extends AbstractUnitTest { @BeforeEach public void beforeEach() { - genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3)); 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/ac/tuwien/ifs/dbrepo/service/ViewServiceUnitTest.java similarity index 86% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/ViewServiceUnitTest.java index e99fef1acc..a50b7ca339 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/ac/tuwien/ifs/dbrepo/service/ViewServiceUnitTest.java @@ -1,15 +1,14 @@ -package at.tuwien.service; - -import at.tuwien.api.database.CreateViewDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.test.AbstractUnitTest; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -29,7 +28,7 @@ import static org.mockito.Mockito.*; @Testcontainers @SpringBootTest @ExtendWith(SpringExtension.class) -public class ViewServiceUnitTest extends AbstractUnitTest { +public class ViewServiceUnitTest extends BaseTest { @MockBean private DataServiceGateway dataServiceGateway; @@ -43,11 +42,6 @@ public class ViewServiceUnitTest extends AbstractUnitTest { @Autowired private ViewService viewService; - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, @@ -94,20 +88,6 @@ public class ViewServiceUnitTest extends AbstractUnitTest { }); } - @Test - public void findAll_public_succeeds() { - - /* test */ - viewService.findAll(DATABASE_1, null); - } - - @Test - public void findAll_publicAndPrivate_succeeds() { - - /* test */ - viewService.findAll(DATABASE_1, USER_1); - } - @Test public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/AmqpUtils.java similarity index 98% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/AmqpUtils.java index df86598714..09017252d8 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/AmqpUtils.java @@ -1,7 +1,7 @@ -package at.tuwien.utils; +package at.ac.tuwien.ifs.dbrepo.utils; -import at.tuwien.api.amqp.*; -import at.tuwien.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.*; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/H2Utils.java similarity index 96% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/H2Utils.java index 7c80d5274a..f10486047a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/H2Utils.java @@ -1,4 +1,4 @@ -package at.tuwien.utils; +package at.ac.tuwien.ifs.dbrepo.utils; import jakarta.persistence.EntityManager; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/KeycloakUtils.java similarity index 90% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/KeycloakUtils.java index 100178a337..9a0ea26a73 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/KeycloakUtils.java @@ -1,9 +1,9 @@ -package at.tuwien.utils; +package at.ac.tuwien.ifs.dbrepo.utils; -import at.tuwien.api.keycloak.UserCreateDto; -import at.tuwien.config.KeycloakConfig; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.UserCreateDto; +import at.ac.tuwien.ifs.dbrepo.config.KeycloakConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; import jakarta.ws.rs.core.Response; import lombok.extern.log4j.Log4j2; import org.keycloak.admin.client.Keycloak; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/XmlUtils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/XmlUtils.java similarity index 96% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/XmlUtils.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/XmlUtils.java index b351d2798e..268d2c0be5 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/XmlUtils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/utils/XmlUtils.java @@ -1,4 +1,4 @@ -package at.tuwien.utils; +package at.ac.tuwien.ifs.dbrepo.utils; import java.io.File; import java.io.IOException; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/validator/EndpointValidatorUnitTest.java similarity index 94% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/validator/EndpointValidatorUnitTest.java index 1e7ce07afd..3d3675c285 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/validator/EndpointValidatorUnitTest.java @@ -1,20 +1,19 @@ -package at.tuwien.validator; - -import at.tuwien.SortType; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.identifier.IdentifierSaveDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.TableService; -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.validation.EndpointValidator; +package at.ac.tuwien.ifs.dbrepo.validator; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.SortType; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.service.AccessService; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.service.TableService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import at.ac.tuwien.ifs.dbrepo.validation.EndpointValidator; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -38,7 +37,7 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) -public class EndpointValidatorUnitTest extends AbstractUnitTest { +public class EndpointValidatorUnitTest extends BaseTest { @MockBean private DatabaseService databaseService; @@ -78,11 +77,6 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { ); } - @BeforeEach - public void beforeEach() { - genesis(); - } - @Test public void validateDataParams_succeeds() throws PaginationException { @@ -216,7 +210,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); when(accessService.find(eq(DATABASE_1), any(User.class))) - .thenReturn(DATABASE_1_USER_1_READ_ACCESS); + .thenReturn(DATABASE_1.getAccesses().get(0)); /* test */ endpointValidator.validateOnlyAccessOrPublic(DATABASE_1, USER_1_PRINCIPAL); @@ -286,7 +280,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); when(accessService.find(eq(DATABASE_1), any(User.class))) - .thenReturn(DATABASE_1_USER_1_READ_ACCESS); + .thenReturn(DATABASE_1.getAccesses().get(0)); /* test */ assertThrows(NotAllowedException.class, () -> { @@ -374,7 +368,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); when(accessService.find(DATABASE_1, USER_1)) - .thenReturn(DATABASE_1_USER_1_READ_ACCESS); + .thenReturn(DATABASE_1.getAccesses().get(0)); /* test */ assertThrows(NotAllowedException.class, () -> { @@ -610,7 +604,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { public void validateOnlyMineOrWriteAccessOrHasRole_readAccess_fails() { /* test */ - assertFalse(endpointValidator.validateOnlyMineOrWriteAccessOrHasRole(USER_1, USER_1_PRINCIPAL, DATABASE_1_USER_1_READ_ACCESS, "nobody-role")); + assertFalse(endpointValidator.validateOnlyMineOrWriteAccessOrHasRole(USER_1, USER_1_PRINCIPAL, DATABASE_1.getAccesses().get(0), "nobody-role")); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties index 0929175cf7..d96b443102 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties @@ -23,10 +23,10 @@ logging.level.com.github.dockerjava.=warn logging.level.com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.wire.=off # datacite -dbrepo.datacite.url: https://api.test.datacite.org -dbrepo.datacite.prefix: 10.12345 -dbrepo.datacite.username: test-user -dbrepo.datacite.password: test-password +dbrepo.datacite.url= https://api.test.datacite.org +dbrepo.datacite.prefix= 10.12345 +dbrepo.datacite.username= test-user +dbrepo.datacite.password= test-password # s3 dbrepo.s3.accessKeyId=minioadmin diff --git a/dbrepo-metadata-service/services/pom.xml b/dbrepo-metadata-service/services/pom.xml index a0b354871b..12d34b7e8f 100644 --- a/dbrepo-metadata-service/services/pom.xml +++ b/dbrepo-metadata-service/services/pom.xml @@ -6,17 +6,17 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-services</artifactId> <name>dbrepo-metadata-service-services</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-api</artifactId> + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> <version>${project.version}</version> </dependency> <dependency> @@ -24,11 +24,6 @@ <artifactId>dbrepo-metadata-service-oai</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>at.tuwien</groupId> - <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>${project.version}</version> - </dependency> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service-repositories</artifactId> diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/AuthTokenFilter.java similarity index 95% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/AuthTokenFilter.java index b056eafe17..fc7d7bdaa2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/AuthTokenFilter.java @@ -1,7 +1,7 @@ -package at.tuwien.auth; +package at.ac.tuwien.ifs.dbrepo.auth; -import at.tuwien.api.auth.RealmAccessDto; -import at.tuwien.api.user.UserDetailsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.RealmAccessDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDetailsDto; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; @@ -91,7 +91,7 @@ public class AuthTokenFilter extends OncePerRequestFilter { public String parseJwt(HttpServletRequest request) { String headerAuth = request.getHeader("Authorization"); if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { - return headerAuth.substring(7, headerAuth.length()); + return headerAuth.substring(7); } return null; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/BasicAuthenticationProvider.java similarity index 84% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/BasicAuthenticationProvider.java index 963249b393..5ab64107cd 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/BasicAuthenticationProvider.java @@ -1,7 +1,7 @@ -package at.tuwien.auth; +package at.ac.tuwien.ifs.dbrepo.auth; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.service.CredentialService; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.service.CredentialService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; @@ -28,7 +28,7 @@ public class BasicAuthenticationProvider implements AuthenticationManager { public Authentication authenticate(Authentication auth) throws AuthenticationException { final TokenDto tokenDto = credentialService.getAccessToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); - log.debug("set basic auth principal: {}", userDetails); + log.debug("set basic auth principal username: {}", userDetails.getUsername()); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/InternalRequestInterceptor.java similarity index 87% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/InternalRequestInterceptor.java index 6d7480ba80..272dfda2cf 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/auth/InternalRequestInterceptor.java @@ -1,8 +1,8 @@ -package at.tuwien.auth; +package at.ac.tuwien.ifs.dbrepo.auth; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.config.GatewayConfig; -import at.tuwien.service.CredentialService; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.service.CredentialService; import lombok.extern.log4j.Log4j2; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/CacheConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/CacheConfig.java similarity index 89% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/CacheConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/CacheConfig.java index 9229927e83..4fd448efa2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/CacheConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/CacheConfig.java @@ -1,6 +1,6 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.beans.factory.annotation.Value; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/DataCiteConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/DataCiteConfig.java similarity index 97% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/DataCiteConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/DataCiteConfig.java index 9667553119..1c00d625dd 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/DataCiteConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/DataCiteConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/EndpointConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/EndpointConfig.java similarity index 86% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/EndpointConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/EndpointConfig.java index 20e2805a03..2512863082 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/EndpointConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/EndpointConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import org.springframework.beans.factory.annotation.Value; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/GatewayConfig.java similarity index 82% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/GatewayConfig.java index 34b0acbcb7..3fe7f59c77 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/GatewayConfig.java @@ -1,7 +1,7 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.auth.InternalRequestInterceptor; -import at.tuwien.service.CredentialService; +import at.ac.tuwien.ifs.dbrepo.auth.InternalRequestInterceptor; +import at.ac.tuwien.ifs.dbrepo.service.CredentialService; import lombok.Getter; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +27,9 @@ public class GatewayConfig { @Value("${dbrepo.endpoints.searchService}") private String searchEndpoint; + @Value("${dbrepo.endpoints.dashboardService}") + private String dashboardEndpoint; + @Value("${dbrepo.endpoints.rorService}") private String rorEndpoint; @@ -89,4 +92,13 @@ public class GatewayConfig { return restTemplate; } + @Bean("dashboardServiceRestTemplate") + public RestTemplate dashboardServiceRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(dashboardEndpoint)); + restTemplate.getInterceptors() + .add(new InternalRequestInterceptor(credentialService, this)); + return restTemplate; + } + } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JacksonConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JacksonConfig.java similarity index 84% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JacksonConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JacksonConfig.java index 61e7f2b180..8ff2d5434e 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JacksonConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JacksonConfig.java @@ -1,6 +1,5 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.hibernate6.Hibernate6Module; @@ -10,7 +9,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Date; import java.util.TimeZone; @Slf4j @@ -18,7 +16,7 @@ import java.util.TimeZone; public class JacksonConfig { @Bean - public ObjectMapper objectMapper() throws JsonProcessingException { + public ObjectMapper objectMapper() { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new JavaTimeModule()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JenaConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JenaConfig.java similarity index 92% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JenaConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JenaConfig.java index e9395e4470..4e1868e8b8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/JenaConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/JenaConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import org.apache.jena.query.Dataset; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/KeycloakConfig.java similarity index 96% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/KeycloakConfig.java index 4b62b61dcb..34596462e7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/KeycloakConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import org.keycloak.admin.client.Keycloak; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetadataConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetadataConfig.java similarity index 93% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetadataConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetadataConfig.java index d2484407ee..f79360781e 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetadataConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetadataConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import org.springframework.beans.factory.annotation.Value; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetricsConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetricsConfig.java similarity index 90% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetricsConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetricsConfig.java index b86a97a4dc..8509d27c44 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/MetricsConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/MetricsConfig.java @@ -1,10 +1,10 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.entities.database.table.Table; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.repository.TableRepository; -import at.tuwien.repository.ViewRepository; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.repository.TableRepository; +import at.ac.tuwien.ifs.dbrepo.repository.ViewRepository; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.Metrics; import io.micrometer.observation.ObservationRegistry; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java similarity index 93% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java index 0ed5001dd4..a727e972e2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/RabbitConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/S3Config.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/S3Config.java similarity index 97% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/S3Config.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/S3Config.java index 6c82c29e25..6202d2b2a8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/S3Config.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/S3Config.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import lombok.Getter; import lombok.extern.slf4j.Slf4j; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/SecurityConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SecurityConfig.java similarity index 91% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/SecurityConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SecurityConfig.java index 03be90470f..1d08f95630 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/SecurityConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/SecurityConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/TemplateConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/TemplateConfig.java similarity index 96% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/TemplateConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/TemplateConfig.java index d38f17c6cb..28c5210e29 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/TemplateConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/TemplateConfig.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/WebSecurityConfig.java similarity index 95% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/WebSecurityConfig.java index 2413384696..653c25c337 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/config/WebSecurityConfig.java @@ -1,8 +1,8 @@ -package at.tuwien.config; +package at.ac.tuwien.ifs.dbrepo.config; -import at.tuwien.auth.AuthTokenFilter; -import at.tuwien.auth.BasicAuthenticationProvider; -import at.tuwien.service.CredentialService; +import at.ac.tuwien.ifs.dbrepo.auth.AuthTokenFilter; +import at.ac.tuwien.ifs.dbrepo.auth.BasicAuthenticationProvider; +import at.ac.tuwien.ifs.dbrepo.service.CredentialService; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.SecurityScheme; import jakarta.servlet.http.HttpServletResponse; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGateway.java similarity index 85% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGateway.java index 42e8912d0c..44e3938980 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/BrokerServiceGateway.java @@ -1,8 +1,8 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.amqp.*; -import at.tuwien.api.user.ExchangeUpdatePermissionsDto; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.*; +import at.ac.tuwien.ifs.dbrepo.core.api.user.ExchangeUpdatePermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; public interface BrokerServiceGateway { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGateway.java similarity index 70% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGateway.java index 58e023ac9d..07e4c5b1e2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/CrossrefGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/CrossrefGateway.java @@ -1,7 +1,7 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.exception.DoiNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DoiNotFoundException; public interface CrossrefGateway { diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGateway.java new file mode 100644 index 0000000000..95df0c6548 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DashboardServiceGateway.java @@ -0,0 +1,51 @@ +package at.ac.tuwien.ifs.dbrepo.gateway; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.PermissionTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceException; + +public interface DashboardServiceGateway { + + /** + * Updates a dashboard configuration by given database. + * @param database The database. + * @throws DashboardServiceConnectionException The connection to the dashboard service failed. + * @throws DashboardServiceException The dashboard service failed to update the dashboard configuration. + */ + void update(DatabaseDto database) throws DashboardServiceConnectionException, DashboardServiceException; + + /** + * Creates a dashboard by given metadata. + * @param data The metadata. + * @return The dashboard response. + * @throws DashboardServiceConnectionException The connection to the dashboard service failed. + * @throws DashboardServiceException The dashboard service failed to create the dashboard. + */ + CreateDashboardResponseDto create(CreateDashboardDto data) throws DashboardServiceConnectionException, + DashboardServiceException; + + /** + * Updates the access on a dashboard for a given user by given dashboard uid and username. + * @param dashboardUid The dashboard uid. + * @param username The username. + * @param permission The access. + * @throws DashboardServiceConnectionException The connection to the dashboard service failed. + * @throws DashboardServiceException The dashboard service failed to update access to the dashboard. + */ + void updateAccess(String dashboardUid, String username, PermissionTypeDto permission) + throws DashboardServiceConnectionException, DashboardServiceException; + + /** + * Updates the access on a dashboard for anonymous users by given dashboard uid. + * @param dashboardUid The dashboard uid. + * @param database The database. + * @throws DashboardServiceConnectionException The connection to the dashboard service failed. + * @throws DashboardServiceException The dashboard service failed to update access to the dashboard. + */ + void updateAnonymousAccess(String dashboardUid, DatabaseBriefDto database) + throws DashboardServiceConnectionException, DashboardServiceException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGateway.java similarity index 90% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGateway.java index 3996448d21..d7d54ca8e7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/DataServiceGateway.java @@ -1,17 +1,17 @@ -package at.tuwien.gateway; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.CreateViewDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableStatisticDto; -import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.exception.*; +package at.ac.tuwien.ifs.dbrepo.gateway; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import java.util.List; import java.util.UUID; @@ -173,7 +173,7 @@ public interface DataServiceGateway { * * @param databaseId The database id. * @param tableId The table id. - * @return The statistic, if successful. + * @return The statistic, if successful. If no column can be analyzed, the response is null. * @throws DataServiceConnectionException The connection to the data service could not be established. * @throws DataServiceException The data service responded unexpectedly. * @throws TableNotFoundException The table was not found in the database. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGateway.java similarity index 65% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGateway.java index 9436db80cb..a829db05bf 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/KeycloakGateway.java @@ -1,9 +1,9 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; import org.keycloak.representations.idm.UserRepresentation; import java.util.UUID; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGateway.java similarity index 69% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGateway.java index 2cd5f142e6..98336290b3 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/OrcidGateway.java @@ -1,7 +1,7 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.exception.OrcidNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.OrcidNotFoundException; import org.springframework.stereotype.Service; @Service diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGateway.java similarity index 69% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGateway.java index 27603b9919..8a49aa636b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/RorGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/RorGateway.java @@ -1,7 +1,7 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.ror.RorDto; -import at.tuwien.exception.RorNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.RorNotFoundException; public interface RorGateway { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGateway.java similarity index 60% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGateway.java index 1b3b20485f..fdf4b430fe 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/SearchServiceGateway.java @@ -1,8 +1,8 @@ -package at.tuwien.gateway; +package at.ac.tuwien.ifs.dbrepo.gateway; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.entities.database.Database; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import java.util.UUID; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/BrokerServiceGatewayImpl.java similarity index 94% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/BrokerServiceGatewayImpl.java index da1c289185..9c35fa4182 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/BrokerServiceGatewayImpl.java @@ -1,17 +1,16 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.amqp.*; -import at.tuwien.api.user.ExchangeUpdatePermissionsDto; -import at.tuwien.config.RabbitConfig; -import at.tuwien.exception.*; -import at.tuwien.gateway.BrokerServiceGateway; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.*; +import at.ac.tuwien.ifs.dbrepo.core.api.user.ExchangeUpdatePermissionsDto; +import at.ac.tuwien.ifs.dbrepo.config.RabbitConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.BrokerServiceGateway; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @Slf4j diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/CrossrefGatewayImpl.java similarity index 83% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/CrossrefGatewayImpl.java index 8fd957f330..e718c388b4 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/CrossrefGatewayImpl.java @@ -1,18 +1,16 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.DoiNotFoundException; -import at.tuwien.gateway.CrossrefGateway; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.DoiNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.CrossrefGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @Log4j2 diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DashboardServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DashboardServiceGatewayImpl.java new file mode 100644 index 0000000000..8f36db0f3b --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DashboardServiceGatewayImpl.java @@ -0,0 +1,142 @@ +package at.ac.tuwien.ifs.dbrepo.gateway.impl; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.PermissionTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.UpdateDashboardAccessDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceException; +import at.ac.tuwien.ifs.dbrepo.gateway.DashboardServiceGateway; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +@Log4j2 +@Service +public class DashboardServiceGatewayImpl implements DashboardServiceGateway { + + private final RestTemplate restTemplate; + private final GatewayConfig gatewayConfig; + + @Autowired + public DashboardServiceGatewayImpl(@Qualifier("dashboardServiceRestTemplate") RestTemplate restTemplate, + GatewayConfig gatewayConfig) { + this.restTemplate = restTemplate; + this.gatewayConfig = gatewayConfig; + } + + @Override + public void update(DatabaseDto database) throws DashboardServiceConnectionException, DashboardServiceException { + final ResponseEntity<Void> response; + final String path = "/api/dashboard/" + database.getDashboardUid(); + log.trace("update dashboard at endpoint {} with path {}", gatewayConfig.getDashboardEndpoint(), path); + try { + response = restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(database), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to update dashboard: {}", e.getMessage()); + throw new DashboardServiceConnectionException("Failed to update dashboard: " + e.getMessage(), e); + } catch (HttpClientErrorException.Unauthorized e) { + log.error("Failed to update dashboard: unauthorized: {}", e.getMessage()); + throw new DashboardServiceException("Failed to update dashboard: unauthorized: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { + log.error("Failed to update dashboard: response code is not 202"); + throw new DashboardServiceException("Failed to update dashboard: response code is not 202"); + } + log.info("Updated dashboard with uid: {}", database.getDashboardUid()); + } + + @Override + public CreateDashboardResponseDto create(CreateDashboardDto data) throws DashboardServiceConnectionException, + DashboardServiceException { + final ResponseEntity<CreateDashboardResponseDto> response; + final String path = "/api/dashboard"; + log.trace("create dashboard at endpoint {} with path {}", gatewayConfig.getDashboardEndpoint(), path); + try { + response = restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<>(data), CreateDashboardResponseDto.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to create dashboard: {}", e.getMessage()); + throw new DashboardServiceConnectionException("Failed to create dashboard: " + e.getMessage(), e); + } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { + log.error("Failed to create dashboard: malformed payload: {}", e.getMessage()); + throw new DashboardServiceException("Failed to create dashboard: malformed payload: " + e.getMessage(), e); + } catch (HttpClientErrorException.Conflict e) { + log.error("Failed to create dashboard: exists: {}", e.getMessage()); + throw new DashboardServiceException("Failed to create dashboard: exists: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.CREATED)) { + log.error("Failed to create dashboard: response code is not 201"); + throw new DashboardServiceException("Failed to create dashboard: response code is not 201"); + } + final CreateDashboardResponseDto body = response.getBody(); + if (body == null) { + log.error("Failed to create dashboard: body is empty"); + throw new DashboardServiceException("Failed to create dashboard: body is empty"); + } + log.info("Created dashboard with uid: {}", body.getUid()); + return body; + } + + @Override + public void updateAccess(String dashboardUid, String username, PermissionTypeDto permission) + throws DashboardServiceConnectionException, DashboardServiceException { + final ResponseEntity<Void> response; + final String path = "/api/dashboard/" + dashboardUid + "/access/" + username; + log.trace("update dashboard access at endpoint {} with path {}", gatewayConfig.getDashboardEndpoint(), path); + try { + response = restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(UpdateDashboardAccessDto.builder() + .permission(permission) + .build()), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to update dashboard access: {}", e.getMessage()); + throw new DashboardServiceConnectionException("Failed to update dashboard access: " + e.getMessage(), e); + } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { + log.error("Failed to update dashboard access: malformed payload: {}", e.getMessage()); + throw new DashboardServiceException("Failed to update dashboard access: malformed payload: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { + log.error("Failed to update dashboard access: response code is not 202"); + throw new DashboardServiceException("Failed to update dashboard access: response code is not 202"); + } + log.info("Updated dashboard access for user with username: {}", username); + } + + @Override + public void updateAnonymousAccess(String dashboardUid, DatabaseBriefDto database) + throws DashboardServiceConnectionException, DashboardServiceException { + final ResponseEntity<Void> response; + final String path = "/api/dashboard/" + dashboardUid + "/access"; + log.trace("update dashboard anonymous access at endpoint {} with path {}", gatewayConfig.getDashboardEndpoint(), + path); + try { + response = restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>(database), Void.class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to update dashboard anonymous access: {}", e.getMessage()); + throw new DashboardServiceConnectionException("Failed to update dashboard anonymous access: " + e.getMessage(), e); + } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { + log.error("Failed to update dashboard anonymous access: malformed payload: {}", e.getMessage()); + throw new DashboardServiceException("Failed to update dashboard anonymous access: malformed payload: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { + log.error("Failed to update dashboard access: response code is not 202"); + throw new DashboardServiceException("Failed to update dashboard access: response code is not 202"); + } + log.info("Updated dashboard anonymous access"); + } +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DataServiceGatewayImpl.java similarity index 96% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DataServiceGatewayImpl.java index ba855feda3..41ab74b9cc 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/DataServiceGatewayImpl.java @@ -1,16 +1,16 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.database.*; -import at.tuwien.api.database.internal.CreateDatabaseDto; -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TableStatisticDto; -import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.core.api.database.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; @@ -398,12 +398,7 @@ public class DataServiceGatewayImpl implements DataServiceGateway { log.error("Failed to analyse table statistic: wrong http code: {}", response.getStatusCode()); throw new DataServiceException("Failed to analyse table statistic: wrong http code: " + response.getStatusCode()); } - final TableStatisticDto body = response.getBody(); - if (body == null) { - log.error("Failed to analyse table statistic: empty body: {}", response.getStatusCode()); - throw new DataServiceException("Failed to analyse table statistic: empty body"); - } - return body; + return response.getBody(); } } 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/ac/tuwien/ifs/dbrepo/gateway/impl/KeycloakGatewayImpl.java similarity index 90% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/KeycloakGatewayImpl.java index 4eb96aeee5..f3f5c4ad09 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/KeycloakGatewayImpl.java @@ -1,12 +1,12 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.config.KeycloakConfig; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.config.KeycloakConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; import jakarta.ws.rs.ForbiddenException; import jakarta.ws.rs.NotAuthorizedException; import jakarta.ws.rs.NotFoundException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/OrcidGatewayImpl.java similarity index 82% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/OrcidGatewayImpl.java index 7634e421fe..78751b72be 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/OrcidGatewayImpl.java @@ -1,17 +1,15 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.exception.OrcidNotFoundException; -import at.tuwien.gateway.OrcidGateway; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.OrcidNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.OrcidGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @Log4j2 diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/RorGatewayImpl.java similarity index 83% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/RorGatewayImpl.java index 37ed982f9e..b8af43362d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/RorGatewayImpl.java @@ -1,18 +1,16 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.ror.RorDto; -import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.RorNotFoundException; -import at.tuwien.gateway.RorGateway; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.core.exception.RorNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.RorGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @Log4j2 diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/SearchServiceGatewayImpl.java similarity index 87% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/SearchServiceGatewayImpl.java index 89b4dff5c7..97977fbb43 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/SearchServiceGatewayImpl.java @@ -1,13 +1,13 @@ -package at.tuwien.gateway.impl; +package at.ac.tuwien.ifs.dbrepo.gateway.impl; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.config.GatewayConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.exception.DatabaseNotFoundException; -import at.tuwien.exception.SearchServiceConnectionException; -import at.tuwien.exception.SearchServiceException; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto; +import at.ac.tuwien.ifs.dbrepo.config.GatewayConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SearchServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SearchServiceException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -37,7 +37,8 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { } @Override - public DatabaseBriefDto update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException { + public DatabaseBriefDto update(Database database) throws SearchServiceConnectionException, SearchServiceException, + DatabaseNotFoundException { final ResponseEntity<DatabaseBriefDto> response; final HttpHeaders headers = new HttpHeaders(); headers.set("Accept", "application/json"); diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AccessService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AccessService.java new file mode 100644 index 0000000000..21f8f0444b --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AccessService.java @@ -0,0 +1,81 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; + +import java.security.Principal; +import java.util.List; + +public interface AccessService { + + /** + * Loads all database access definitions for a database with id. + * + * @param database The database. + * @return The list of database access definitions. + */ + List<DatabaseAccess> list(Database database); + + /** + * Finds database access by given database and user, where the access is determined by the username (needed since {@link Principal#getName()} embeds the username). + * + * @param database The database. + * @param user The user. + * @return The database access, if successful. + * @throws AccessNotFoundException The access was not found in the metadata database. + */ + DatabaseAccess find(Database database, User user) throws AccessNotFoundException; + + /** + * Give somebody access to a database of container. + * + * @param database The database. + * @param access The access. + * @param user The user. + * @return The database access, if successful. + * @throws DataServiceException The data service responded with an unexpected error code. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata/search database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + DatabaseAccess create(Database database, User user, AccessTypeDto access) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Update access to a database. + * + * @param database The database. + * @param user The user. + * @param access The updated access. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws AccessNotFoundException The access was not found. + * @throws DatabaseNotFoundException The database was not found in the metadata/search database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + void update(Database database, User user, AccessTypeDto access) throws DataServiceException, + DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Revokes access to a database of container. + * + * @param database The database. + * @param user The user. + * @throws AccessNotFoundException The access was not found. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata/search database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + void delete(Database database, User user) throws AccessNotFoundException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationService.java new file mode 100644 index 0000000000..808c774e23 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/AuthenticationService.java @@ -0,0 +1,18 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; + +public interface AuthenticationService { + + /** + * Deletes a user at the Authentication Service with given user id. + * + * @param user The user. + * @throws AuthServiceException The auth service responded with unexpected behavior. + * @throws UserNotFoundException The user was not found after creation in the auth database. + */ + void delete(User user) throws AuthServiceException, UserNotFoundException; + +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BannerMessageService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BannerMessageService.java similarity index 81% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BannerMessageService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BannerMessageService.java index a7973b6171..98c6b12679 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BannerMessageService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BannerMessageService.java @@ -1,9 +1,9 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.exception.MessageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.exception.MessageNotFoundException; import java.util.List; import java.util.UUID; diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BrokerService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BrokerService.java new file mode 100644 index 0000000000..6f9109cbe0 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/BrokerService.java @@ -0,0 +1,25 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; + +public interface BrokerService { + + /** + * Updates the virtual host permissions in the Broker Service for a user with given principal. + * + * @param user The user. + * @throws BrokerServiceException The broker service responded with an unexpected response code. + * @throws BrokerServiceConnectionException The connection to the broker service could not be established. + */ + void setVirtualHostPermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; + + /** + * Sets topic exchange permissions for a user. + * + * @param user The user. + * @throws BrokerServiceException The broker service responded with an unexpected response code. + * @throws BrokerServiceConnectionException The connection to the broker service could not be established. + */ + void setTopicExchangePermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ConceptService.java similarity index 75% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ConceptService.java index 94fa1e0c89..ec582b10d8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ConceptService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ConceptService.java @@ -1,7 +1,7 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.entities.database.table.columns.TableColumnConcept; -import at.tuwien.exception.ConceptNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.exception.ConceptNotFoundException; import java.util.List; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ContainerService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ContainerService.java similarity index 75% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ContainerService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ContainerService.java index d559b5134d..fcda5ef460 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ContainerService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ContainerService.java @@ -1,10 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.entities.container.Container; -import at.tuwien.exception.ContainerAlreadyExistsException; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; import java.util.List; import java.util.UUID; @@ -19,8 +19,7 @@ public interface ContainerService { * @throws ImageNotFoundException The image of the container was not found in the metadata database. * @throws ContainerAlreadyExistsException A container with this name already exists. */ - Container create(CreateContainerDto createDto) throws ImageNotFoundException, - ContainerAlreadyExistsException; + Container create(CreateContainerDto createDto) throws ImageNotFoundException, ContainerAlreadyExistsException; /** * Removes a container by given id from the metadata database. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/CredentialService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/CredentialService.java similarity index 80% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/CredentialService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/CredentialService.java index b1c28cf170..4a54849006 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/CredentialService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/CredentialService.java @@ -1,6 +1,6 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; public interface CredentialService { diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DashboardService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DashboardService.java new file mode 100644 index 0000000000..77be6e2447 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DashboardService.java @@ -0,0 +1,44 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceException; + +public interface DashboardService { + + /** + * Updates the panels in the dashboard in the dashboard service for a given database. Only updates the dashboard if + * (and only if) the {@link Database#isDashboardEnabled} is set to true. + * + * @param database The database. + * @throws DashboardServiceException The dashboard service responded with an unexpected error code. + * @throws DashboardServiceConnectionException The connection to the dashboard service could not be established. + */ + void update(Database database) throws DashboardServiceException, DashboardServiceConnectionException; + + /** + * Creates the dashboard in the dashboard service for a given database. Does not create panels. + * + * @param database The database. + * @return The response containing the UID of the created dashboard. + * @throws DashboardServiceException The dashboard service responded with an unexpected error code. + * @throws DashboardServiceConnectionException The connection to the dashboard service could not be established. + */ + CreateDashboardResponseDto create(Database database) throws DashboardServiceException, + DashboardServiceConnectionException; + + /** + * Updates the access on the dashboard in the dashboard service. + * + * @param database The database. + * @param user The user whose access is updated. + * @param access The access type. + * @throws DashboardServiceException The dashboard service responded with an unexpected error code. + * @throws DashboardServiceConnectionException The connection to the dashboard service could not be established. + */ + void updateAccess(Database database, User user, AccessTypeDto access) throws DashboardServiceException, + DashboardServiceConnectionException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java new file mode 100644 index 0000000000..351e383b05 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java @@ -0,0 +1,193 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +public interface DatabaseService { + + /** + * Finds all databases stored in the metadata database. + * + * @return List of databases. + */ + List<Database> findAll(); + + /** + * Filters all databases where {@link Database#isPublic} or {@link Database#isSchemaPublic} evaluates to true. + * + * @return List of databases. + */ + List<Database> findAllPublicOrSchemaPublic(); + + /** + * Filters all databases whose internal name matches the given internal name. + * + * @param internalName The internal name. + * @return List of databases. + */ + List<Database> findByInternalName(String internalName); + + /** + * Filters all databases where {@link Database#isPublic} or {@link Database#isSchemaPublic} and the user by given id + * has at least read access and whose internal name matches the given internal name evaluates to true. + * @param userId The user id. + * @param internalName The internal name. + * @return List of databases. + */ + List<Database> findAllPublicOrSchemaPublicOrReadAccessByInternalName(UUID userId, String internalName); + + /** + * Filters all databases where {@link Database#isPublic} or {@link Database#isSchemaPublic} or the user by given id + * has at least read access evaluate to true. + * + * @param userId The user id. + * @return List of databases. + */ + List<Database> findAllPublicOrSchemaPublicOrReadAccess(UUID userId); + + /** + * Filters all databases where {@link Database#isPublic} or {@link Database#isSchemaPublic} or the internal name + * matches the given internal name evaluate to true. + * + * @param internalName The internal name. + * @return List of databases. + */ + List<Database> findAllPublicOrSchemaPublicByInternalName(String internalName); + + /** + * Find a database by given id. + * + * @param databaseId The id. + * @return The database, if successful. + * @throws DatabaseNotFoundException The database was not found in the metadata database. + */ + Database findById(UUID databaseId) throws DatabaseNotFoundException; + + /** + * Creates a new database with minimal metadata in the metadata database and creates a new database on the + * container. + * + * @param container The container. + * @param createDto The metadata. + * @param user The user. + * @param internalUsers The list of internal users. + * @return The database, if successful. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws DashboardServiceException The dashboard service responded with an unexpected error code. + * @throws DashboardServiceConnectionException The connection to the dashboard service could not be established. + */ + Database create(Container container, CreateDatabaseDto createDto, User user, List<User> internalUsers) + throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException; + + /** + * Updates the user's password. + * + * @param database The database. + * @param user The user. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + */ + void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException; + + /** + * Updates the visibility of the database. + * + * @param database The database. + * @param data The visibility + * @return The database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + Database modifyVisibility(Database database, DatabaseModifyVisibilityDto data) throws DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException; + + /** + * Transfer ownership of a database + * + * @param database The database. + * @param user The payload with the new owner. + * @return The database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + Database modifyOwner(Database database, User user) throws DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Modify image of database with given id. + * + * @param database The database. + * @param image The image. + * @return The database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + Database modifyImage(Database database, byte[] image) throws DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Modify dashboard uid of database with given id. + * + * @param database The database. + * @param uid The dashboard uid. + * @return The database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + Database modifyDashboard(Database database, String uid) throws DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Updates the table metadata of a given database. + * + * @param database The database. + * @return The updated database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws TableNotFoundException The table was not found in the metadata database. + */ + Database updateTableMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, + SearchServiceException, SearchServiceConnectionException, DataServiceConnectionException, + MalformedException, TableNotFoundException; + + /** + * Updates the view metadata of a given database. + * + * @param database The database. + * @return The updated database, if successful. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws ViewNotFoundException The view was not found in the metadata database. + */ + Database updateViewMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, + SearchServiceException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/EntityService.java similarity index 54% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/EntityService.java index 69a801cf5c..c767ad3a7b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/EntityService.java @@ -1,11 +1,13 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.TableColumnEntityDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException; +import at.ac.tuwien.ifs.dbrepo.core.exception.OntologyNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.SemanticEntityNotFoundException; import java.util.List; @@ -16,7 +18,8 @@ public interface EntityService { * * @param ontology The ontology. * @param label The label. - * @return The list of entities that match. + * @return List of entities. + * @throws MalformedException The query is malformed. */ List<EntityDto> findByLabel(Ontology ontology, String label) throws MalformedException; @@ -26,7 +29,8 @@ public interface EntityService { * @param ontology The ontology. * @param label The label. * @param limit The maximum number of entities to return. - * @return The list of entities that match. + * @return List of entities. + * @throws MalformedException The query is malformed. */ List<EntityDto> findByLabel(Ontology ontology, String label, Integer limit) throws MalformedException; @@ -34,7 +38,9 @@ public interface EntityService { * Finds entities in the ontology whose uri match the given uri. * * @param uri The uri. - * @return The list of entities that match. + * @return List of entities. + * @throws MalformedException The query is malformed. + * @throws OntologyNotFoundException The ontology was not found in the metadata database. */ List<EntityDto> findByUri(String uri) throws MalformedException, OntologyNotFoundException; @@ -43,14 +49,19 @@ public interface EntityService { * * @param uri The uri. * @return The entity, if successful. + * @throws MalformedException The query is malformed. + * @throws SemanticEntityNotFoundException The semantic entity was not found in the metadata database. + * @throws OntologyNotFoundException The ontology was not found in the metadata database. */ - EntityDto findOneByUri(String uri) throws MalformedException, SemanticEntityNotFoundException, OntologyNotFoundException; + EntityDto findOneByUri(String uri) throws MalformedException, SemanticEntityNotFoundException, + OntologyNotFoundException; /** * Attempts to suggest table semantics for a table with given id in database with given id. * * @param table The table. * @return The list of entities that were suggested. + * @throws MalformedException The query is malformed. */ List<EntityDto> suggestByTable(Table table) throws MalformedException; @@ -59,6 +70,7 @@ public interface EntityService { * * @param column The table column. * @return The list of entities that were suggested. + * @throws MalformedException The query is malformed. */ List<TableColumnEntityDto> suggestByColumn(TableColumn column) throws MalformedException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierService.java similarity index 54% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierService.java index 8c9a3088fe..ac23dc1b4f 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/IdentifierService.java @@ -1,13 +1,13 @@ -package at.tuwien.service; - -import at.tuwien.api.identifier.BibliographyTypeDto; -import at.tuwien.api.identifier.CreateIdentifierDto; -import at.tuwien.api.identifier.IdentifierSaveDto; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.CreateIdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; import org.springframework.core.io.InputStreamResource; import org.springframework.stereotype.Service; @@ -91,11 +91,12 @@ public interface IdentifierService { * * @param identifier The identifier. * @return The resulting identifier. - * @throws SearchServiceException - * @throws DatabaseNotFoundException - * @throws SearchServiceConnectionException - * @throws MalformedException - * @throws DataServiceConnectionException + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws ExternalServiceException The DataCite system rejected the publish-request. */ Identifier publish(Identifier identifier) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, DataServiceConnectionException, @@ -108,19 +109,20 @@ public interface IdentifierService { * @param user The user. * @param data The data. * @return The created identifier from the metadata database if successful. - * @throws DataServiceException - * @throws DataServiceConnectionException - * @throws IdentifierNotFoundException - * @throws MalformedException - * @throws ViewNotFoundException - * @throws DatabaseNotFoundException - * @throws QueryNotFoundException - * @throws SearchServiceException - * @throws SearchServiceConnectionException + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws IdentifierNotFoundException The identifier was not found in the metadata service. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws ViewNotFoundException The view was not found in the metadata service. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws QueryNotFoundException The subset was not found in the data service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. */ Identifier save(Database database, User user, IdentifierSaveDto data) throws DataServiceException, DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, - DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException; + DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, + ExternalServiceException; /** * Creates a new identifier in the metadata database for a query or database. @@ -129,19 +131,18 @@ public interface IdentifierService { * @param user The user. * @param data The data. * @return The created identifier from the metadata database if successful. - * @throws DataServiceException - * @throws DataServiceConnectionException - * @throws IdentifierNotFoundException - * @throws MalformedException - * @throws ViewNotFoundException - * @throws DatabaseNotFoundException - * @throws QueryNotFoundException - * @throws SearchServiceException - * @throws SearchServiceConnectionException + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws ViewNotFoundException The view was not found in the metadata service. + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws QueryNotFoundException The subset was not found in the data service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. */ Identifier create(Database database, User user, CreateIdentifierDto data) throws DataServiceException, - DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, - DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException; + DataServiceConnectionException, MalformedException, ViewNotFoundException, DatabaseNotFoundException, + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException; /** * Export metadata for a identifier @@ -166,13 +167,10 @@ public interface IdentifierService { * database, but sets it as deleted. * * @param identifier The identifier. - * @throws DataServiceException - * @throws DataServiceConnectionException - * @throws IdentifierNotFoundException - * @throws DatabaseNotFoundException - * @throws SearchServiceException - * @throws SearchServiceConnectionException + * @throws DatabaseNotFoundException The created database was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. */ - void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, IdentifierNotFoundException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; + void delete(Identifier identifier) throws DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ImageService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ImageService.java similarity index 73% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ImageService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ImageService.java index c5f353c7a1..09afe61aae 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ImageService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ImageService.java @@ -1,11 +1,11 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.container.image.ImageChangeDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageChangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; import java.security.Principal; import java.util.List; @@ -25,6 +25,7 @@ public interface ImageService { * * @param imageId The image id. * @return The image, if successful. + * @throws ImageNotFoundException The image was not found in the metadata service. */ ContainerImage find(UUID imageId) throws ImageNotFoundException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/LicenseService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/LicenseService.java similarity index 74% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/LicenseService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/LicenseService.java index 4bea349946..a0854ab374 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/LicenseService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/LicenseService.java @@ -1,7 +1,7 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.entities.database.License; -import at.tuwien.exception.LicenseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; +import at.ac.tuwien.ifs.dbrepo.core.exception.LicenseNotFoundException; import java.util.List; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/MetadataService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/MetadataService.java similarity index 62% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/MetadataService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/MetadataService.java index 95c2b299e4..bbc2d2d494 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/MetadataService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/MetadataService.java @@ -1,10 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.user.external.ExternalMetadataDto; -import at.tuwien.exception.*; -import at.tuwien.oaipmh.OaiErrorType; -import at.tuwien.oaipmh.OaiListIdentifiersParameters; -import at.tuwien.oaipmh.OaiRecordParameters; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalMetadataDto; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiErrorType; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiListIdentifiersParameters; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiRecordParameters; public interface MetadataService { @@ -28,6 +28,7 @@ public interface MetadataService { * * @param parameters The parameters. * @return The xml record. + * @throws IdentifierNotFoundException The identifier was not found. */ String getRecord(OaiRecordParameters parameters) throws IdentifierNotFoundException; @@ -51,9 +52,10 @@ public interface MetadataService { * * @param url The user identifier. * @return The user metadata. - * @throws OrcidNotFoundException The provided identifier is of ORCID type and does not exist. - * @throws RorNotFoundException The provided identifier is of ROR type and does not exist. - * @throws DoiNotFoundException The doi was not found. + * @throws OrcidNotFoundException The provided identifier is of ORCID type and does not exist. + * @throws RorNotFoundException The provided identifier is of ROR type and does not exist. + * @throws DoiNotFoundException The doi was not found. + * @throws IdentifierNotSupportedException The identifier is not supported. */ ExternalMetadataDto findByUrl(String url) throws OrcidNotFoundException, RorNotFoundException, DoiNotFoundException, IdentifierNotSupportedException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/OntologyService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/OntologyService.java similarity index 72% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/OntologyService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/OntologyService.java index c8e4c70676..584ab4178c 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/OntologyService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/OntologyService.java @@ -1,9 +1,9 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.semantics.OntologyCreateDto; -import at.tuwien.api.semantics.OntologyModifyDto; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.OntologyNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyModifyDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.exception.OntologyNotFoundException; import java.security.Principal; import java.util.List; @@ -34,6 +34,13 @@ public interface OntologyService { */ Ontology find(UUID ontologyId) throws OntologyNotFoundException; + /** + * Finds an ontology in the metadata database with given entity uri. + * + * @param entityUri The entity uri. + * @return The ontology, if successful. + * @throws OntologyNotFoundException The ontology was not found in the metadata database. + */ Ontology find(String entityUri) throws OntologyNotFoundException; /** diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java similarity index 73% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java index 7cb195ce4e..33a96b1296 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java @@ -1,7 +1,7 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; import java.io.InputStream; @@ -13,8 +13,8 @@ public interface StorageService { * @param bucket The bucket name. * @param key The object key. * @return The input stream, if successful. + * @throws StorageNotFoundException The object could not be found in the Storage Service. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. - * @throws StorageNotFoundException The object could not be found in the Storage Service. */ InputStream getObject(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException; @@ -25,7 +25,7 @@ public interface StorageService { * @param key The object key. * @return The byte array. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. - * @throws StorageNotFoundException The object could not be found in the Storage Service. + * @throws StorageNotFoundException The object could not be found in the Storage Service. */ byte[] getBytes(String key) throws StorageUnavailableException, StorageNotFoundException; @@ -35,8 +35,8 @@ public interface StorageService { * @param bucket The bucket name. * @param key The object key. * @return The byte array. + * @throws StorageNotFoundException The object could not be found in the Storage Service. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. - * @throws StorageNotFoundException The object could not be found in the Storage Service. */ byte[] getBytes(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/TableService.java new file mode 100644 index 0000000000..b024698362 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/TableService.java @@ -0,0 +1,140 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; + +import java.security.Principal; +import java.util.UUID; + +public interface TableService { + + /** + * Find a table in the metadata database by database and table id. + * + * @param database The database. + * @param tableId The table id. + * @return The table, if successful. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + */ + Table findById(Database database, UUID tableId) throws TableNotFoundException, DatabaseNotFoundException; + + /** + * Find a table in the metadata database by database id and table name. + * + * @param database The database. + * @param internalName The table name. + * @return The table, if successful. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + */ + Table findByName(Database database, String internalName) throws TableNotFoundException, DatabaseNotFoundException; + + + /** + * + * Creates a table for a database id with given schema as data + * + * @param database The database. + * @param createDto The schema (as data). + * @param principal The principal. + * @return The created table. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws UserNotFoundException The user with this username was not found in the metadata database. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws TableExistsException The table with this name exists in the target database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws OntologyNotFoundException The ontology was not found in the metadata database. + * @throws SemanticEntityNotFoundException The semantic entity was not found in the metadata database. + */ + Table createTable(Database database, CreateTableDto createDto, Principal principal) throws TableNotFoundException, + DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, + OntologyNotFoundException, SemanticEntityNotFoundException; + + /** + * Deletes a given table from the database in the metadata database and data database. + * + * @param table The table. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + void deleteTable(Table table) throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException; + + /** + * Updates a given table from the database in the metadata database. + * + * @param table The table. + * @param data The update data. + * @return The updated table, if successful. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + Table updateTable(Table table, TableUpdateDto data) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Updates a given table column in the metadata database. + * + * @param column The table column. + * @param updateDto The update data. + * @return The updated table column, if successful. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws OntologyNotFoundException The ontology was not found in the metadata database. + * @throws SemanticEntityNotFoundException The semantic entity was not found in the metadata database. + */ + TableColumn update(TableColumn column, ColumnSemanticsUpdateDto updateDto) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException, MalformedException, OntologyNotFoundException, + SemanticEntityNotFoundException; + + /** + * Find a table column by given table and column id. + * + * @param table The table. + * @param columnId The column id. + * @return The column, if found. + * @throws MalformedException The table column was not found. + */ + TableColumn findColumnById(Table table, UUID columnId) throws MalformedException; + + /** + * Updates the table statistics by given table. + * + * @param table The table. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + * @throws MalformedException The table is malformed, e.g. a column of a primary key constraint could not be found. + * @throws TableNotFoundException The table was not found in the metadata service. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + */ + void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException, MalformedException, TableNotFoundException, DataServiceException, + DataServiceConnectionException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UnitService.java similarity index 63% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UnitService.java index 93824eeb62..fcf37fbe5a 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UnitService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UnitService.java @@ -1,13 +1,19 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.entities.database.table.columns.TableColumnUnit; -import at.tuwien.exception.UnitNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.exception.UnitNotFoundException; import org.springframework.transaction.annotation.Transactional; import java.util.List; public interface UnitService { + /** + * Creates a table column unit in the metadata database. + * + * @param unit The table column unit. + * @return The saved table column unit, if successful. + */ TableColumnUnit create(TableColumnUnit unit); /** diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UserService.java similarity index 68% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UserService.java index f38268c000..3e244e8e8b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/UserService.java @@ -1,12 +1,10 @@ -package at.tuwien.service; +package at.ac.tuwien.ifs.dbrepo.service; -import at.tuwien.api.auth.CreateUserDto; -import at.tuwien.api.user.UserPasswordDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserExistsException; -import at.tuwien.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.CreateUserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; import java.util.List; import java.util.UUID; @@ -29,6 +27,11 @@ public interface UserService { */ User findByUsername(String username) throws UserNotFoundException; + /** + * Filters all users where they are marked as service account ({@link User#isInternal}). + * + * @return List of users. + */ List<User> findAllInternalUsers(); /** @@ -54,8 +57,8 @@ public interface UserService { * @param user The user. * @param data The user information. * @return The user if successful. False otherwise. + * @throws UserNotFoundException The user was not found. + * @throws AuthServiceException The auth service responded with an unexpected error code. */ User modify(User user, UserUpdateDto data) throws UserNotFoundException, AuthServiceException; - - String getMariaDbPassword(String password); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ViewService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ViewService.java new file mode 100644 index 0000000000..eda8cdd443 --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/ViewService.java @@ -0,0 +1,69 @@ +package at.ac.tuwien.ifs.dbrepo.service; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; + +import java.util.UUID; + +public interface ViewService { + + /** + * Find a view of a database with id. + * + * @param database The database. + * @param viewId The view id. + * @return The view, if successful. + * @throws ViewNotFoundException The view with given id was not found in the metadata database. + */ + View findById(Database database, UUID viewId) throws ViewNotFoundException; + + /** + * Delete view in the container with the given id and database with id and the given view id. + * + * @param view The view. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws ViewNotFoundException The view was not found in the metadata database. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + void delete(View view) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, + ViewNotFoundException, SearchServiceException, SearchServiceConnectionException; + + /** + * Creates a view in the container with given id and database with id with the given query. + * + * @param database The database. + * @param user The user. + * @param data The given query. + * @return The view that was created. + * @throws MalformedException The query was malformed in the data service. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + View create(Database database, User user, CreateViewDto data) throws MalformedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException; + + /** + * Updates the view in the metadata database and search service. + * + * @param view The view. + * @param data The update data. + * @return The view, if successful. + * @throws DataServiceConnectionException The connection with the data service could not be established. + * @throws DatabaseNotFoundException The database was not found in the metadata service. + * @throws SearchServiceException The search service responded with an unexpected error code. + * @throws SearchServiceConnectionException The connection with the search service could not be established. + */ + View update(View view, ViewUpdateDto data) throws DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException; +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AccessServiceImpl.java similarity index 87% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AccessServiceImpl.java index e5b59ebda8..7d3120bba2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AccessServiceImpl.java @@ -1,16 +1,16 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.service.AccessService; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AuthenticationServiceImpl.java similarity index 62% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AuthenticationServiceImpl.java index e6bb056bfe..b2b4853271 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/AuthenticationServiceImpl.java @@ -1,10 +1,10 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.service.AuthenticationService; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.service.AuthenticationService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BannerMessageServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BannerMessageServiceImpl.java similarity index 82% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BannerMessageServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BannerMessageServiceImpl.java index d75d384b3c..8b8766401a 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BannerMessageServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BannerMessageServiceImpl.java @@ -1,12 +1,12 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.exception.MessageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.BannerMessageRepository; -import at.tuwien.service.BannerMessageService; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.exception.MessageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.repository.BannerMessageRepository; +import at.ac.tuwien.ifs.dbrepo.service.BannerMessageService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BrokerServiceRabbitMqImpl.java similarity index 88% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BrokerServiceRabbitMqImpl.java index 2800c96bc9..709e7cebde 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/BrokerServiceRabbitMqImpl.java @@ -1,13 +1,13 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.amqp.GrantExchangePermissionsDto; -import at.tuwien.api.amqp.GrantVirtualHostPermissionsDto; -import at.tuwien.config.RabbitConfig; -import at.tuwien.entities.database.AccessType; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.BrokerServiceGateway; -import at.tuwien.service.BrokerService; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantExchangePermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantVirtualHostPermissionsDto; +import at.ac.tuwien.ifs.dbrepo.config.RabbitConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.AccessType; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.gateway.BrokerServiceGateway; +import at.ac.tuwien.ifs.dbrepo.service.BrokerService; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ConceptServiceImpl.java similarity index 80% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ConceptServiceImpl.java index 647d4fe198..93f64a16ea 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ConceptServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ConceptServiceImpl.java @@ -1,9 +1,9 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.entities.database.table.columns.TableColumnConcept; -import at.tuwien.exception.ConceptNotFoundException; -import at.tuwien.repository.ConceptRepository; -import at.tuwien.service.ConceptService; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.exception.ConceptNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.ConceptRepository; +import at.ac.tuwien.ifs.dbrepo.service.ConceptService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ContainerServiceImpl.java similarity index 84% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ContainerServiceImpl.java index d92b6c17dc..27daf63487 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ContainerServiceImpl.java @@ -1,15 +1,15 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ContainerAlreadyExistsException; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.ContainerRepository; -import at.tuwien.repository.ImageRepository; -import at.tuwien.service.ContainerService; +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ContainerNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.repository.ContainerRepository; +import at.ac.tuwien.ifs.dbrepo.repository.ImageRepository; +import at.ac.tuwien.ifs.dbrepo.service.ContainerService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/CredentialServiceImpl.java similarity index 85% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/CredentialServiceImpl.java index 7cf7d1eff4..65597ec056 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/CredentialServiceImpl.java @@ -1,8 +1,8 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.service.CredentialService; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.service.CredentialService; import com.github.benmanes.caffeine.cache.Cache; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DashboardServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DashboardServiceImpl.java new file mode 100644 index 0000000000..af76ee2d4f --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DashboardServiceImpl.java @@ -0,0 +1,51 @@ +package at.ac.tuwien.ifs.dbrepo.service.impl; + +import at.ac.tuwien.ifs.dbrepo.core.api.database.AccessTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceConnectionException; +import at.ac.tuwien.ifs.dbrepo.core.exception.DashboardServiceException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DashboardServiceGateway; +import at.ac.tuwien.ifs.dbrepo.service.DashboardService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Log4j2 +@Service +public class DashboardServiceImpl implements DashboardService { + + private final MetadataMapper metadataMapper; + private final DashboardServiceGateway dashboardServiceGateway; + + @Autowired + public DashboardServiceImpl(MetadataMapper metadataMapper, DashboardServiceGateway dashboardServiceGateway) { + this.metadataMapper = metadataMapper; + this.dashboardServiceGateway = dashboardServiceGateway; + } + + @Override + public void update(Database database) throws DashboardServiceException, DashboardServiceConnectionException { + if (!database.getIsDashboardEnabled()) { + log.trace("database does not manage their dashboard, skip"); + return; + } + dashboardServiceGateway.update(metadataMapper.databaseToDatabaseDto(database)); + } + + @Override + public CreateDashboardResponseDto create(Database database) throws DashboardServiceException, + DashboardServiceConnectionException { + return dashboardServiceGateway.create(metadataMapper.databaseToCreateDashboardDto(database)); + } + + @Override + public void updateAccess(Database database, User user, AccessTypeDto access) throws DashboardServiceException, + DashboardServiceConnectionException { + dashboardServiceGateway.updateAccess(database.getDashboardUid(), user.getUsername(), + metadataMapper.accessTypeDtoToPermissionTypeDto(access)); + } + +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DataCiteIdentifierServiceImpl.java similarity index 83% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DataCiteIdentifierServiceImpl.java index 5ab9cc26a2..5c10963318 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DataCiteIdentifierServiceImpl.java @@ -1,24 +1,24 @@ -package at.tuwien.service.impl; - -import at.tuwien.api.datacite.DataCiteBody; -import at.tuwien.api.datacite.DataCiteData; -import at.tuwien.api.datacite.doi.DataCiteCreateDoi; -import at.tuwien.api.datacite.doi.DataCiteDoi; -import at.tuwien.api.datacite.doi.DataCiteDoiEvent; -import at.tuwien.api.identifier.BibliographyTypeDto; -import at.tuwien.api.identifier.CreateIdentifierDto; -import at.tuwien.api.identifier.IdentifierSaveDto; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.config.DataCiteConfig; -import at.tuwien.config.EndpointConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierStatusType; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.service.IdentifierService; +package at.ac.tuwien.ifs.dbrepo.service.impl; + +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.DataCiteBody; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.DataCiteData; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.DataCiteCreateDoi; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.DataCiteDoi; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.DataCiteDoiEvent; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.CreateIdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.config.DataCiteConfig; +import at.ac.tuwien.ifs.dbrepo.config.EndpointConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierStatusType; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.service.IdentifierService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; @@ -107,9 +107,8 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional(rollbackFor = {Exception.class}) public Identifier create(Database database, User user, CreateIdentifierDto data) throws DataServiceException, - DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, - DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, - SearchServiceConnectionException, ExternalServiceException { + DataServiceConnectionException, MalformedException, ViewNotFoundException, DatabaseNotFoundException, + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { data.setDoi(remoteSave(identifierService.create(database, user, data), DataCiteDoiEvent.REGISTER)); return identifierService.create(database, user, data); } @@ -198,8 +197,7 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional - public void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, + public void delete(Identifier identifier) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { identifierService.delete(identifier); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java similarity index 85% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java index d01e5c0b6e..6cfa0180a8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java @@ -1,28 +1,28 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.database.CreateDatabaseDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.DatabaseModifyVisibilityDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.database.ViewColumn; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference; -import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; -import at.tuwien.entities.database.table.constraints.unique.Unique; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateDatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.ViewColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKeyReference; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey.PrimaryKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique.Unique; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.service.DatabaseService; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -72,11 +72,6 @@ public class DatabaseServiceImpl implements DatabaseService { return databaseRepository.findAllPublicOrSchemaPublicOrReadAccessByInternalNameDesc(userId, internalName); } - @Override - public List<Database> findAllAtLestReadAccess(UUID userId) { - return databaseRepository.findAllAtLestReadAccessDesc(userId); - } - @Override public List<Database> findAllPublicOrSchemaPublicOrReadAccess(UUID userId) { return databaseRepository.findAllPublicOrSchemaPublicOrReadAccessDesc(userId); @@ -101,11 +96,13 @@ public class DatabaseServiceImpl implements DatabaseService { @Override @Transactional public Database create(Container container, CreateDatabaseDto data, User user, List<User> internalUsers) - throws UserNotFoundException, ContainerNotFoundException, DataServiceException, SearchServiceException, - DataServiceConnectionException, DatabaseNotFoundException, SearchServiceConnectionException { + throws DataServiceException, SearchServiceException, DataServiceConnectionException, + DatabaseNotFoundException, SearchServiceConnectionException, DashboardServiceException, + DashboardServiceConnectionException { final Database entity = Database.builder() .isPublic(data.getIsPublic()) .isSchemaPublic(data.getIsSchemaPublic()) + .isDashboardEnabled(true) .name(data.getName()) .internalName(metadataMapper.nameToInternalName(data.getName()) + "_" + RandomStringUtils.randomAlphabetic(4).toLowerCase()) .cid(data.getCid()) @@ -120,13 +117,15 @@ public class DatabaseServiceImpl implements DatabaseService { .identifiers(new LinkedList<>()) .build(); /* create in data database */ - final at.tuwien.api.database.internal.CreateDatabaseDto payload = at.tuwien.api.database.internal.CreateDatabaseDto.builder() + final at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto payload = at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto.builder() .containerId(data.getCid()) .userId(user.getId()) .username(user.getUsername()) .password(user.getMariadbPassword()) .privilegedUsername(container.getPrivilegedUsername()) .privilegedPassword(container.getPrivilegedPassword()) + .readonlyUsername(container.getReadonlyUsername()) + .readonlyPassword(container.getReadonlyPassword()) .internalName(entity.getInternalName()) .build(); final DatabaseDto dto = dataServiceGateway.createDatabase(payload); @@ -135,10 +134,6 @@ public class DatabaseServiceImpl implements DatabaseService { final Database entity1 = databaseRepository.save(entity); entity1.getAccesses() .add(metadataMapper.userToWriteAllAccess(entity1, user)); -// entity1.getAccesses() -// .addAll(internalUsers.stream() -// .map(internalUser -> metadataMapper.userToWriteAllAccess(entity1, internalUser)) -// .toList()); final Database database = databaseRepository.save(entity1); /* create in search service */ searchServiceGateway.update(database); @@ -170,6 +165,7 @@ public class DatabaseServiceImpl implements DatabaseService { /* update in metadata database */ database.setIsPublic(data.getIsPublic()); database.setIsSchemaPublic(data.getIsSchemaPublic()); + database.setIsDashboardEnabled(data.getIsDashboardEnabled()); log.debug("visibility change affects {} table(s)", database.getTables().stream().filter(t -> !t.getIsSchemaPublic().equals(data.getIsSchemaPublic())).count()); database.getTables() .forEach(table -> table.setIsSchemaPublic(data.getIsSchemaPublic())); @@ -209,6 +205,19 @@ public class DatabaseServiceImpl implements DatabaseService { return database; } + @Override + @Transactional + public Database modifyDashboard(Database database, String uid) throws DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException { + /* update in metadata database */ + database.setDashboardUid(uid); + database = databaseRepository.save(database); + /* save in search service */ + searchServiceGateway.update(database); + log.info("Updated database dashboard uid of database with id {} & search database", database.getId()); + return database; + } + @Override @Transactional(rollbackFor = {Exception.class}) public Database updateTableMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/EntityServiceImpl.java similarity index 91% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/EntityServiceImpl.java index dba30481f5..60001b92ac 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/EntityServiceImpl.java @@ -1,15 +1,15 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.config.JenaConfig; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; -import at.tuwien.mapper.SparqlMapper; -import at.tuwien.service.EntityService; -import at.tuwien.service.OntologyService; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.TableColumnEntityDto; +import at.ac.tuwien.ifs.dbrepo.config.JenaConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.mapper.SparqlMapper; +import at.ac.tuwien.ifs.dbrepo.service.EntityService; +import at.ac.tuwien.ifs.dbrepo.service.OntologyService; import lombok.extern.log4j.Log4j2; import org.apache.jena.query.*; import org.apache.jena.rdf.model.RDFNode; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java similarity index 90% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java index 8af7023c8c..f8b2c273e8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java @@ -1,25 +1,25 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.identifier.BibliographyTypeDto; -import at.tuwien.api.identifier.CreateIdentifierDto; -import at.tuwien.api.identifier.IdentifierSaveDto; -import at.tuwien.api.identifier.IdentifierTypeDto; -import at.tuwien.config.MetadataConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.LanguageType; -import at.tuwien.entities.database.View; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierStatusType; -import at.tuwien.entities.identifier.IdentifierTitle; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.service.IdentifierService; -import at.tuwien.service.ViewService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.CreateIdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto; +import at.ac.tuwien.ifs.dbrepo.config.MetadataConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.LanguageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierStatusType; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.IdentifierTitle; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.service.IdentifierService; +import at.ac.tuwien.ifs.dbrepo.service.ViewService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springframework.core.io.InputStreamResource; @@ -226,8 +226,8 @@ public class IdentifierServiceImpl implements IdentifierService { @Transactional public Identifier create(Database database, User user, CreateIdentifierDto data) throws SearchServiceException, DataServiceException, QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { - final Identifier identifier = metadataMapper.identifierCreateDtoToIdentifier(data); + SearchServiceConnectionException, ViewNotFoundException { + final Identifier identifier = metadataMapper.createIdentifierDtoToIdentifier(data); identifier.setDatabase(database); identifier.setOwnedBy(user.getId()); identifier.setOwner(user); @@ -278,8 +278,8 @@ public class IdentifierServiceImpl implements IdentifierService { @Transactional public Identifier save(Identifier identifier) throws DataServiceException, DataServiceConnectionException, - IdentifierNotFoundException, ViewNotFoundException, DatabaseNotFoundException, QueryNotFoundException, - SearchServiceException, SearchServiceConnectionException { + ViewNotFoundException, DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, + SearchServiceConnectionException { /* save identifier */ switch (identifier.getType()) { case SUBSET -> { @@ -357,8 +357,7 @@ public class IdentifierServiceImpl implements IdentifierService { @Override @Transactional - public void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, - IdentifierNotFoundException, DatabaseNotFoundException, SearchServiceException, + public void delete(Identifier identifier) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete in metadata database */ identifierRepository.deleteById(identifier.getId()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ImageServiceImpl.java similarity index 85% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ImageServiceImpl.java index b82c8ca382..470fd9c3a8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ImageServiceImpl.java @@ -1,14 +1,14 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.container.image.ImageChangeDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.ImageAlreadyExistsException; -import at.tuwien.exception.ImageInvalidException; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.ImageRepository; -import at.tuwien.service.ImageService; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageChangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageAlreadyExistsException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageInvalidException; +import at.ac.tuwien.ifs.dbrepo.core.exception.ImageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.repository.ImageRepository; +import at.ac.tuwien.ifs.dbrepo.service.ImageService; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/LicenseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/LicenseServiceImpl.java similarity index 76% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/LicenseServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/LicenseServiceImpl.java index de5018f8c7..41765fb36a 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/LicenseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/LicenseServiceImpl.java @@ -1,9 +1,9 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.entities.database.License; -import at.tuwien.exception.LicenseNotFoundException; -import at.tuwien.repository.LicenseRepository; -import at.tuwien.service.LicenseService; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; +import at.ac.tuwien.ifs.dbrepo.core.exception.LicenseNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.LicenseRepository; +import at.ac.tuwien.ifs.dbrepo.service.LicenseService; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/MetadataServiceImpl.java similarity index 87% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/MetadataServiceImpl.java index 1b6051f543..b4aa80fca3 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/MetadataServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/MetadataServiceImpl.java @@ -1,22 +1,22 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.api.ror.RorDto; -import at.tuwien.api.user.external.ExternalMetadataDto; -import at.tuwien.config.MetadataConfig; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.exception.*; -import at.tuwien.gateway.CrossrefGateway; -import at.tuwien.gateway.OrcidGateway; -import at.tuwien.gateway.RorGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.oaipmh.OaiErrorType; -import at.tuwien.oaipmh.OaiListIdentifiersParameters; -import at.tuwien.oaipmh.OaiRecordParameters; -import at.tuwien.repository.IdentifierRepository; -import at.tuwien.service.IdentifierService; -import at.tuwien.service.MetadataService; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalMetadataDto; +import at.ac.tuwien.ifs.dbrepo.config.MetadataConfig; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.CrossrefGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.OrcidGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.RorGateway; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiErrorType; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiListIdentifiersParameters; +import at.ac.tuwien.ifs.dbrepo.oaipmh.OaiRecordParameters; +import at.ac.tuwien.ifs.dbrepo.repository.IdentifierRepository; +import at.ac.tuwien.ifs.dbrepo.service.IdentifierService; +import at.ac.tuwien.ifs.dbrepo.service.MetadataService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -117,10 +117,9 @@ public class MetadataServiceImpl implements MetadataService { @Override public String listMetadataFormats() { - final StringBuilder builder = new StringBuilder("<ListMetadataFormats>"); - builder.append(templateEngine.process("metadata-format.xml", new Context())); - builder.append("</ListMetadataFormats>"); - return parseResponse("verb=\"ListMetadataFormats\"", builder.toString()); + String builder = "<ListMetadataFormats>" + templateEngine.process("metadata-format.xml", new Context()) + + "</ListMetadataFormats>"; + return parseResponse("verb=\"ListMetadataFormats\"", builder); } @Override diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/OntologyServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/OntologyServiceImpl.java similarity index 84% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/OntologyServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/OntologyServiceImpl.java index d40239a06e..182f1eb5c9 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/OntologyServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/OntologyServiceImpl.java @@ -1,13 +1,12 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.semantics.OntologyCreateDto; -import at.tuwien.api.semantics.OntologyModifyDto; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.OntologyNotFoundException; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.mapper.SparqlMapper; -import at.tuwien.repository.OntologyRepository; -import at.tuwien.service.OntologyService; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyModifyDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.exception.OntologyNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.repository.OntologyRepository; +import at.ac.tuwien.ifs.dbrepo.service.OntologyService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -23,14 +22,12 @@ import java.util.UUID; @Service public class OntologyServiceImpl implements OntologyService { - private final SparqlMapper sparqlMapper; private final MetadataMapper metadataMapper; private final OntologyRepository ontologyRepository; @Autowired - public OntologyServiceImpl(SparqlMapper ontologyMapper, MetadataMapper metadataMapper, + public OntologyServiceImpl(MetadataMapper metadataMapper, OntologyRepository ontologyRepository) { - this.sparqlMapper = ontologyMapper; this.metadataMapper = metadataMapper; this.ontologyRepository = ontologyRepository; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java similarity index 88% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java index aef3213ccf..10e04eb291 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java @@ -1,9 +1,9 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.config.S3Config; -import at.tuwien.exception.StorageNotFoundException; -import at.tuwien.exception.StorageUnavailableException; -import at.tuwien.service.StorageService; +import at.ac.tuwien.ifs.dbrepo.config.S3Config; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException; +import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException; +import at.ac.tuwien.ifs.dbrepo.service.StorageService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; 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/ac/tuwien/ifs/dbrepo/service/impl/TableServiceImpl.java similarity index 89% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/TableServiceImpl.java index 3b0a530e52..520f84b401 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/TableServiceImpl.java @@ -1,29 +1,32 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableStatisticDto; -import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.config.RabbitConfig; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.*; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.service.*; +import at.ac.tuwien.ifs.dbrepo.config.RabbitConfig; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.CreateTableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.service.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.security.Principal; -import java.util.*; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; @Log4j2 @Service @@ -296,18 +299,21 @@ public class TableServiceImpl implements TableService { DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, DataServiceException, DataServiceConnectionException { final TableStatisticDto statistic = dataServiceGateway.getTableStatistics(table.getTdbid(), table.getId()); - table.setNumRows(statistic.getRows()); + if (statistic == null) { + log.warn("Table statistic is empty (no column can be analysed), skip."); + return; + } + table.setNumRows(statistic.getTotalRows()); table.setDataLength(statistic.getDataLength()); table.setAvgRowLength(statistic.getAvgRowLength()); table.setMaxDataLength(statistic.getMaxDataLength()); - for (Map.Entry<String, ColumnStatisticDto> entry : statistic.getColumns().entrySet()) { - final Optional<TableColumn> optional = table.getColumns().stream().filter(c -> c.getInternalName().equals(entry.getKey())).findFirst(); + for (ColumnStatisticDto columnStatistic : statistic.getColumns()) { + final Optional<TableColumn> optional = table.getColumns().stream().filter(c -> c.getInternalName().equals(columnStatistic.getName())).findFirst(); if (optional.isEmpty()) { - log.error("Failed to assign table column statistic: column {} does not exist in table {}.{}", entry.getKey(), table.getDatabase().getInternalName(), table.getInternalName()); + log.error("Failed to assign table column statistic: column {} does not exist in table {}.{}", columnStatistic.getName(), table.getDatabase().getInternalName(), table.getInternalName()); throw new MalformedException("Failed to assign table column statistic: column does not exist"); } final TableColumn column = optional.get(); - final ColumnStatisticDto columnStatistic = statistic.getColumns().get(entry.getKey()); column.setMean(columnStatistic.getMean()); column.setMedian(columnStatistic.getMedian()); column.setMin(columnStatistic.getMin()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UnitServiceImpl.java similarity index 80% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UnitServiceImpl.java index 03270abcd5..ae24d0342f 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UnitServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UnitServiceImpl.java @@ -1,9 +1,9 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.entities.database.table.columns.TableColumnUnit; -import at.tuwien.exception.UnitNotFoundException; -import at.tuwien.repository.UnitRepository; -import at.tuwien.service.UnitService; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.exception.UnitNotFoundException; +import at.ac.tuwien.ifs.dbrepo.repository.UnitRepository; +import at.ac.tuwien.ifs.dbrepo.service.UnitService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UserServiceImpl.java similarity index 79% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UserServiceImpl.java index ad05c4fd46..f93dacc21c 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/UserServiceImpl.java @@ -1,13 +1,13 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.auth.CreateUserDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.UserNotFoundException; -import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.repository.UserRepository; -import at.tuwien.service.UserService; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.CreateUserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.AuthServiceException; +import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException; +import at.ac.tuwien.ifs.dbrepo.gateway.KeycloakGateway; +import at.ac.tuwien.ifs.dbrepo.repository.UserRepository; +import at.ac.tuwien.ifs.dbrepo.service.UserService; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.RandomStringUtils; @@ -65,12 +65,15 @@ public class UserServiceImpl implements UserService { @Override public User create(CreateUserDto data) { /* create at authentication service */ + final String passwordHash = "*" + DigestUtils.sha1Hex(DigestUtils.sha1(RandomStringUtils.randomAlphabetic(40) + .getBytes(StandardCharsets.UTF_8))) + .toUpperCase(); final User entity = User.builder() .id(data.getLdapId()) .keycloakId(data.getId()) .username(data.getUsername()) .theme("light") - .mariadbPassword(getMariaDbPassword(RandomStringUtils.randomAlphabetic(10))) + .mariadbPassword(passwordHash) .language("en") .firstname(data.getGivenName()) .lastname(data.getFamilyName()) @@ -97,10 +100,4 @@ public class UserServiceImpl implements UserService { log.info("Modified user with id: {}", user.getId()); return user; } - - @Override - public String getMariaDbPassword(String password) { - final byte[] utf8 = password.getBytes(StandardCharsets.UTF_8); - return "*" + DigestUtils.sha1Hex(DigestUtils.sha1(utf8)).toUpperCase(); - } } 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/ac/tuwien/ifs/dbrepo/service/impl/ViewServiceImpl.java similarity index 67% rename from dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java rename to dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ViewServiceImpl.java index 51c9832e26..e952e25e42 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/ViewServiceImpl.java @@ -1,17 +1,17 @@ -package at.tuwien.service.impl; +package at.ac.tuwien.ifs.dbrepo.service.impl; -import at.tuwien.api.database.CreateViewDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.ViewUpdateDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.service.ViewService; +import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.View; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.exception.*; +import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper; +import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway; +import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway; +import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository; +import at.ac.tuwien.ifs.dbrepo.service.ViewService; import com.google.common.hash.Hashing; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -20,7 +20,6 @@ import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.util.LinkedList; -import java.util.List; import java.util.Optional; import java.util.UUID; @@ -55,25 +54,10 @@ public class ViewServiceImpl implements ViewService { return optional.get(); } - @Override - @Transactional(readOnly = true) - public List<View> findAll(Database database, User user) { - if (user == null) { - return database.getViews() - .stream() - .filter(View::getIsPublic) - .toList(); - } - return database.getViews() - .stream() - .filter(v -> v.getIsPublic() || v.getOwnedBy().equals(user.getId())) - .toList(); - } - @Override @Transactional - public void delete(View view) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { + public void delete(View view) throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete in data service */ dataServiceGateway.deleteView(view.getDatabase().getId(), view.getId()); /* delete in metadata database */ @@ -90,7 +74,7 @@ public class ViewServiceImpl implements ViewService { @Transactional public View create(Database database, User creator, CreateViewDto data) throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException { + SearchServiceConnectionException { /* create in metadata database */ final View view = View.builder() .database(database) @@ -136,24 +120,15 @@ public class ViewServiceImpl implements ViewService { @Override @Transactional - public View update(Database database, View view, ViewUpdateDto data) throws DataServiceConnectionException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, ViewNotFoundException { - final Optional<View> optional = database.getViews() - .stream() - .filter(v -> v.getInternalName().equals(view.getInternalName())) - .findFirst(); - if (optional.isEmpty()) { - log.error("Failed to find view"); - throw new ViewNotFoundException("Failed to find view"); - } - final View tmpView = optional.get(); - tmpView.setIsPublic(data.getIsPublic()); - tmpView.setIsSchemaPublic(data.getIsSchemaPublic()); - database = databaseRepository.save(database); + public View update(View view, ViewUpdateDto data) throws DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException { + view.setIsPublic(data.getIsPublic()); + view.setIsSchemaPublic(data.getIsSchemaPublic()); + final Database database = databaseRepository.save(view.getDatabase()); /* update in search service */ searchServiceGateway.update(database); - log.info("Updated view with id {}", tmpView.getId()); - return optional.get(); + log.info("Updated view with id {}", view.getId()); + return view; } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java deleted file mode 100644 index 2642574f27..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java +++ /dev/null @@ -1,70 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; - -import java.security.Principal; -import java.util.List; - -public interface AccessService { - - /** - * Loads all database access definitions for a database with id. - * - * @param database The database. - * @return The list of database access definitions. - */ - List<DatabaseAccess> list(Database database); - - /** - * Finds database access by given database and user, where the access is determined by the username (needed since {@link Principal#getName()} embeds the username). - * - * @param database The database. - * @param user The user. - * @return The database access, if successful. - * @throws AccessNotFoundException The access was not found in the metadata database. - */ - DatabaseAccess find(Database database, User user) throws AccessNotFoundException; - - /** - * Give somebody access to a database of container. - * - * @param database The database. - * @param access The access. - * @param user The user. - * @return The database access, if successful. - * @throws DataServiceException The data service responded with unexpected behavior. - * @throws DataServiceConnectionException The connection with the data service could not be established. - * @throws DatabaseNotFoundException The database was not found in the metadata/search database. - */ - DatabaseAccess create(Database database, User user, AccessTypeDto access) throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - - /** - * Update access to a database. - * - * @param database The database. - * @param user The user. - * @param access The updated access. - * @throws DataServiceException The data service responded with unexpected behavior. - * @throws DataServiceConnectionException The connection with the data service could not be established. - * @throws DatabaseNotFoundException The database was not found in the metadata/search database. - */ - void update(Database database, User user, AccessTypeDto access) throws at.tuwien.exception.DataServiceException, DataServiceConnectionException, - AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - - /** - * Revokes access to a database of container. - * - * @param database The database. - * @param user The user. - * @throws DataServiceException The data service responded with unexpected behavior. - * @throws DataServiceConnectionException The connection with the data service could not be established. - * @throws DatabaseNotFoundException The database was not found in the search database. - */ - void delete(Database database, User user) throws AccessNotFoundException, DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java deleted file mode 100644 index f93e81b69f..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java +++ /dev/null @@ -1,22 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceConnectionException; -import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.CredentialsInvalidException; -import at.tuwien.exception.UserNotFoundException; - -public interface AuthenticationService { - - /** - * Deletes a user at the Authentication Service with given user id. - * - * @param user The user. - * @throws AuthServiceException The auth service responded with unexpected behavior. - * @throws AuthServiceConnectionException The connection with the auth service could not be established. - * @throws UserNotFoundException The user was not found after creation in the auth database. - */ - void delete(User user) throws AuthServiceException, AuthServiceConnectionException, UserNotFoundException, - CredentialsInvalidException; - -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java deleted file mode 100644 index f249f7a2cf..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; - -public interface BrokerService { - - /** - * Updates the virtual host permissions in the Broker Service for a user with given principal. - * - * @param user The user. - */ - void setVirtualHostPermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; - - /** - * Sets topic exchange permissions for a user. - * - * @param user The user. - */ - void setTopicExchangePermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java deleted file mode 100644 index 2f6aa6f372..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ /dev/null @@ -1,124 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.CreateDatabaseDto; -import at.tuwien.api.database.DatabaseModifyVisibilityDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.UUID; - -@Service -public interface DatabaseService { - - /** - * Finds all databases stored in the metadata database. - * - * @return List of databases. - */ - List<Database> findAll(); - - List<Database> findAllPublicOrSchemaPublic(); - - List<Database> findByInternalName(String internalName); - - List<Database> findAllPublicOrSchemaPublicOrReadAccessByInternalName(UUID userId, String internalName); - - /** - * Finds all databases stored in the metadata database. - * - * @param userId The user id. - * @return List of databases. - */ - List<Database> findAllAtLestReadAccess(UUID userId); - - /** - * Finds all databases stored in the metadata database. - * - * @param userId The user id. - * @return List of databases. - */ - List<Database> findAllPublicOrSchemaPublicOrReadAccess(UUID userId); - - /** - * @param internalName The database internal name. - * @return The databases if found. - */ - List<Database> findAllPublicOrSchemaPublicByInternalName(String internalName); - - /** - * Find a database by id, only used in the authentication service - * - * @param databaseId the database id. - * @return The database, if successful. - * @throws DatabaseNotFoundException The database was not found in the metadata database. - */ - Database findById(UUID databaseId) throws DatabaseNotFoundException; - - /** - * Creates a new database with minimal metadata in the metadata database and creates a new database on the container. - * - * @param container The container. - * @param createDto The metadata. - * @param user The user. - * @param internalUsers The list of internal users. - * @return The database, if successful. - * @throws UserNotFoundException If the container/user was not found in the metadata database. - * @throws DataServiceException If the data service returned non-successfully. - * @throws DataServiceConnectionException If failing to connect to the data service/search service. - */ - Database create(Container container, CreateDatabaseDto createDto, User user, List<User> internalUsers) throws UserNotFoundException, - ContainerNotFoundException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException; - - /** - * Updates the user's password. - * - * @param database The database. - * @param user The user. - * @throws DataServiceException If the data service returned non-successfully. - * @throws DataServiceConnectionException If failing to connect to the data service. - */ - void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException; - - /** - * Updates the visibility of the database. - * - * @param database The database. - * @param data The visibility - * @return The database, if successful. - * @throws NotFoundException The database was not found in the metadata database. - * @throws DataServiceConnectionException If failing to connect to the search service. - */ - Database modifyVisibility(Database database, DatabaseModifyVisibilityDto data) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - - /** - * Transfer ownership of a database - * - * @param database The database. - * @param user The payload with the new owner. - * @return The database, if successful. - * @throws DatabaseNotFoundException The database was not found in the metadata database. - */ - Database modifyOwner(Database database, User user) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - - /** - * Modify image of database with given id. - * - * @param database The database. - * @param image The image. - * @return The database, if successful. - */ - Database modifyImage(Database database, byte[] image) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - - Database updateTableMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, - SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - DataServiceConnectionException, MalformedException, TableNotFoundException; - - Database updateViewMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, - SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - DataServiceConnectionException, ViewNotFoundException; -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java deleted file mode 100644 index 2edea6ebeb..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java +++ /dev/null @@ -1,64 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.table.CreateTableDto; -import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.exception.*; - -import java.security.Principal; -import java.util.UUID; - -public interface TableService { - - /** - * Find a table in the metadata database by database and table id. - * - * @param database The database. - * @param tableId The table id. - * @return The table, if successful. - */ - Table findById(Database database, UUID tableId) throws TableNotFoundException, DatabaseNotFoundException; - - /** - * Find a table in the metadata database by database id and table name. - * - * @param database The database. - * @param internalName The table name. - * @return The table, if successful. - */ - Table findByName(Database database, String internalName) throws TableNotFoundException, DatabaseNotFoundException; - - - /** - * Creates a table for a database id with given schema as data - * - * @param database The database. - * @param createDto The schema (as data). - * @param principal The principal. - * @return The created table. - */ - Table createTable(Database database, CreateTableDto createDto, Principal principal) - throws TableNotFoundException, DataServiceException, DataServiceConnectionException, UserNotFoundException, - DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; - - /** - * Deletes a table from the database in the metadata database and data database. - * - * @param table The table. - */ - void deleteTable(Table table) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException; - - Table updateTable(Table table, TableUpdateDto data) throws DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, - SearchServiceConnectionException; - - TableColumn update(TableColumn column, ColumnSemanticsUpdateDto updateDto) throws DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; - - TableColumn findColumnById(Table table, UUID columnId) throws MalformedException; - - void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, DataServiceException, DataServiceConnectionException; -} 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 deleted file mode 100644 index 54c9dd80bf..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java +++ /dev/null @@ -1,72 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.database.CreateViewDto; -import at.tuwien.api.database.ViewUpdateDto; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; - -import java.util.List; -import java.util.UUID; - -public interface ViewService { - - /** - * Find a view of a database with id. - * - * @param database The database. - * @param viewId The view id. - * @return The view, if successful. - */ - View findById(Database database, UUID viewId) throws ViewNotFoundException; - - /** - * Find all views by database id. - * - * @param database The database. - * @param user The user. - * @return A list of views. - */ - List<View> findAll(Database database, User user); - - /** - * Delete view in the container with the given id and database with id and the given view id. - * - * @param view The view. - */ - void delete(View view) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - ViewNotFoundException, SearchServiceException, SearchServiceConnectionException; - - /** - * Creates a view in the container with given id and database with id with the given query. - * - * @param database The database. - * @param user The user. - * @param data The given query. - * @return The view that was created. - * @throws MalformedException - * @throws DataServiceException - * @throws DataServiceConnectionException - * @throws DatabaseNotFoundException - * @throws SearchServiceException - * @throws SearchServiceConnectionException - */ - View create(Database database, User user, CreateViewDto data) throws MalformedException, DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException; - - /** - * @param database - * @param view - * @param data - * @return - * @throws DataServiceConnectionException - * @throws DatabaseNotFoundException - * @throws SearchServiceException - * @throws SearchServiceConnectionException - * @throws ViewNotFoundException - */ - View update(Database database, View view, ViewUpdateDto data) throws DataServiceConnectionException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, ViewNotFoundException; -} 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 deleted file mode 100644 index 230aada37a..0000000000 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ /dev/null @@ -1,160 +0,0 @@ -package at.tuwien.test; - -import at.tuwien.entities.database.AccessType; -import at.tuwien.entities.identifier.IdentifierStatusType; -import org.springframework.test.context.TestPropertySource; - -import java.util.LinkedList; -import java.util.List; - -@TestPropertySource(locations = "classpath:application.properties") -public abstract class AbstractUnitTest extends BaseTest { - - public void genesis() { - IMAGE_1_DTO.setOperators(IMAGE_1_OPERATORS_DTO); - CONTAINER_1_DTO.setImage(IMAGE_1_DTO); - IMAGE_1.setOperators(new LinkedList<>(IMAGE_1_OPERATORS)); - CONTAINER_1.setDatabases(new LinkedList<>(List.of(DATABASE_1, DATABASE_2, DATABASE_3))); - CONTAINER_4.setDatabases(new LinkedList<>(List.of(DATABASE_4))); - /* USER_1 */ - USER_1.setAccesses(new LinkedList<>()); - USER_1.setTheme(USER_1_THEME); - /* USER_2 */ - USER_2.setAccesses(new LinkedList<>()); - /* USER_3 */ - USER_3.setAccesses(new LinkedList<>()); - /* USER_4 */ - USER_4.setAccesses(new LinkedList<>()); - /* USER_4 */ - USER_5.setAccesses(new LinkedList<>()); - /* DATABASE 1 */ - TABLE_1_COLUMNS.get(0).setUnit(null); - TABLE_1_COLUMNS.get(0).setConcept(null); - DATABASE_1.setOwner(USER_1); - DATABASE_1.setSubsets(new LinkedList<>()); - DATABASE_1.setIsPublic(DATABASE_1_PUBLIC); - DATABASE_1.setIsSchemaPublic(DATABASE_1_SCHEMA_PUBLIC); - DATABASE_1_USER_1_READ_ACCESS.setType(AccessType.READ); - DATABASE_1.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS, DATABASE_1_USER_2_WRITE_OWN_ACCESS, DATABASE_1_USER_3_WRITE_ALL_ACCESS))); - DATABASE_1_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS_DTO, DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO, DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO))); - DATABASE_1_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS_DTO, DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO, DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO))); - UNIT_1.setId(UNIT_1_ID); - TABLE_1.setDatabase(DATABASE_1); - TABLE_1.setColumns(new LinkedList<>(TABLE_1_COLUMNS)); - TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); - VIEW_1_DTO.setIdentifiers(VIEW_1_DTO_IDENTIFIERS); - 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); - IDENTIFIER_3.setDatabase(DATABASE_1); - IDENTIFIER_4.setDatabase(DATABASE_1); - DATABASE_1.setTables(new LinkedList<>(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_4))); - DATABASE_1.setViews(new LinkedList<>(List.of(VIEW_1, VIEW_2, VIEW_3))); - DATABASE_1_DTO.setContainer(CONTAINER_1_DTO); - DATABASE_1_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))); - DATABASE_1_DTO.setTables(new LinkedList<>(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO))); - 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_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_3.setDatabase(DATABASE_1); - TABLE_3.setColumns(new LinkedList<>(TABLE_3_COLUMNS)); - TABLE_3.setConstraints(TABLE_3_CONSTRAINTS); - TABLE_3_DTO.setColumns(new LinkedList<>(TABLE_3_COLUMNS_DTO)); - TABLE_3_DTO.setConstraints(TABLE_3_CONSTRAINTS_DTO); - TABLE_4.setDatabase(DATABASE_1); - TABLE_4.setColumns(new LinkedList<>(TABLE_4_COLUMNS)); - TABLE_4.setConstraints(TABLE_4_CONSTRAINTS); - TABLE_4_DTO.setColumns(TABLE_4_COLUMNS_DTO); - TABLE_4_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_2.setDatabase(DATABASE_1); - VIEW_2.setColumns(new LinkedList<>(VIEW_2_COLUMNS)); - VIEW_3.setDatabase(DATABASE_1); - VIEW_3.setColumns(new LinkedList<>(VIEW_3_COLUMNS)); - IDENTIFIER_1.setDatabase(DATABASE_1); - IDENTIFIER_2.setDatabase(DATABASE_1); - IDENTIFIER_3.setDatabase(DATABASE_1); - IDENTIFIER_4.setDatabase(DATABASE_1); - /* 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.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); - TABLE_5_DTO.setColumns(new LinkedList<>(TABLE_5_COLUMNS_DTO)); - TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); - TABLE_6.setDatabase(DATABASE_2); - TABLE_6.setColumns(new LinkedList<>(TABLE_6_COLUMNS)); - TABLE_6.setConstraints(TABLE_6_CONSTRAINTS); - TABLE_7.setDatabase(DATABASE_2); - TABLE_7.setColumns(new LinkedList<>(TABLE_7_COLUMNS)); - TABLE_7.setConstraints(TABLE_7_CONSTRAINTS); - TABLE_7_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(0)); - TABLE_7_CONSTRAINTS.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(1)); - TABLE_7_DTO.setColumns(TABLE_7_COLUMNS_DTO); - TABLE_7_DTO.setConstraints(TABLE_7_CONSTRAINTS_DTO); - TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO); - TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO); - VIEW_4.setDatabase(DATABASE_2); - IDENTIFIER_5.setDatabase(DATABASE_2); - /* DATABASE 3 */ - DATABASE_3.setSubsets(new LinkedList<>()); - DATABASE_3.setTables(new LinkedList<>(List.of(TABLE_8))); - DATABASE_3.setViews(new LinkedList<>(List.of(VIEW_5))); - DATABASE_3.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_6))); - DATABASE_3.setAccesses(new LinkedList<>(List.of(DATABASE_3_USER_1_WRITE_ALL_ACCESS))); - DATABASE_3_DTO.setTables(new LinkedList<>(List.of(TABLE_8_DTO))); - DATABASE_3_DTO.setViews(new LinkedList<>(List.of(VIEW_5_DTO))); - 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); - TABLE_8_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); - TABLE_8_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); - VIEW_5.setDatabase(DATABASE_3); - VIEW_5.setColumns(VIEW_5_COLUMNS); - VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO); - IDENTIFIER_6.setDatabase(DATABASE_3); - /* 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))); - 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); - TABLE_9_DTO.setColumns(TABLE_9_COLUMNS_DTO); - TABLE_9_DTO.setConstraints(TABLE_9_CONSTRAINTS_DTO); - IDENTIFIER_7.setStatus(IdentifierStatusType.DRAFT); - IDENTIFIER_7.setDatabase(DATABASE_4); - } - -} diff --git a/dbrepo-metric-db/prometheus.yml b/dbrepo-metric-db/prometheus.yml index ce0a6eb43c..333420ee55 100644 --- a/dbrepo-metric-db/prometheus.yml +++ b/dbrepo-metric-db/prometheus.yml @@ -16,4 +16,4 @@ scrape_configs: - job_name: 'metrics scrape' metrics_path: '/metrics' static_configs: - - targets: ['ui:3000', 'auth-service:9000', 'analyse-service:8080', 'search-service:8080', 'storage-service:9090', 'upload-service:8080', 'dashboard-service:3000', 'broker-service:15692'] + - targets: ['ui:3000', 'auth-service:9000', 'analyse-service:8080', 'search-service:8080', 'storage-service:9090', 'dashboard-service:8080', 'dashboard-ui:3000', 'broker-service:15692'] diff --git a/dbrepo-search-service/.gitignore b/dbrepo-search-service/.gitignore index 726e588cd1..e4a1bfbd16 100644 --- a/dbrepo-search-service/.gitignore +++ b/dbrepo-search-service/.gitignore @@ -38,12 +38,6 @@ MANIFEST *.manifest *.spec -# generate -/friendly_names_overrides.json -/test/rsa -/test/test_keycloak_client.py -/test/test_opensearch_client.py - # Installer logs pip-log.txt pip-delete-this-directory.txt diff --git a/dbrepo-search-service/.testpickle b/dbrepo-search-service/.testpickle deleted file mode 100644 index 8588dbe4ae53420fa89daf9e6c52728afad63086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100 zcmZo*nX1kJ0ku;!dRPkbi%O>Suo@egn_EojVadoZE}7E9nUkNKm;+{)>fzC0fL#Xw D-3=fM diff --git a/dbrepo-search-service/Dockerfile b/dbrepo-search-service/Dockerfile index 3e46d8fc90..8b7356470d 100644 --- a/dbrepo-search-service/Dockerfile +++ b/dbrepo-search-service/Dockerfile @@ -13,12 +13,12 @@ RUN pip install pipenv && \ pipenv install gunicorn && \ pipenv install --system --deploy -USER 1001 +RUN adduser -D dbrepo --uid 1001 WORKDIR /app -COPY --chown=1001 ./init/clients ./clients -COPY --chown=1001 ./init/omlib ./omlib +USER 1001 + COPY --chown=1001 ./init/friendly_names_overrides.json ./friendly_names_overrides.json COPY --chown=1001 ./os-yml ./os-yml COPY --chown=1001 ./app.py ./app.py diff --git a/dbrepo-search-service/Pipfile b/dbrepo-search-service/Pipfile index 2c5f2a319a..2b5da5a36a 100644 --- a/dbrepo-search-service/Pipfile +++ b/dbrepo-search-service/Pipfile @@ -18,7 +18,7 @@ jwt = "~=1.3" testcontainers-opensearch = "*" pytest = "*" rdflib = "*" -dbrepo = {path = "./lib/dbrepo-1.7.3.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.8.0.tar.gz"} gunicorn = "*" [dev-packages] diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index 23c64796a6..148cff5662 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7996ac8acc7350e2485cccbdc5226347f8590634130778a023c0efb67932f296" + "sha256": "a7d8317562380fbd723e1775727df4d4a51ef7804cf52ea774ecbd99bccacd86" }, "pipfile-spec": 6, "requires": { @@ -373,9 +373,9 @@ }, "dbrepo": { "hashes": [ - "sha256:ad01d6dc5d99f3c0c9caf3fb11b51502bec5390c72ff28b6b725e2755f5a2f7c" + "sha256:7b9a70cf1bd9d623e52ada74d5585df53716353d509f5d905f1b431dd91c28d6" ], - "path": "./lib/dbrepo-1.7.3.tar.gz" + "path": "./lib/dbrepo-1.8.0.tar.gz" }, "docker": { "hashes": [ @@ -637,11 +637,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "itsdangerous": { "hashes": [ @@ -752,109 +752,109 @@ }, "mistune": { "hashes": [ - "sha256:4b47731332315cdca99e0ded46fc0004001c1299ff773dfb48fbe1fd226de319", - "sha256:733bf018ba007e8b5f2d3a9eb624034f6ee26c4ea769a98ec533ee111d504dff" + "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", + "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0" ], "markers": "python_version >= '3.8'", - "version": "==3.1.2" + "version": "==3.1.3" }, "multidict": { "hashes": [ - "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", - "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056", - "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", - "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", - "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", - "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", - "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748", - "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", - "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f", - "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", - "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6", - "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada", - "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", - "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2", - "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d", - "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", - "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef", - "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", - "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", - "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60", - "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6", - "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", - "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478", - "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", - "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7", - "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56", - "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", - "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", - "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30", - "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", - "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", - "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0", - "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", - "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c", - "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", - "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", - "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", - "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", - "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", - "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2", - "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", - "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", - "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", - "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", - "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657", - "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581", - "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492", - "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43", - "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", - "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", - "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", - "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057", - "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc", - "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", - "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255", - "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1", - "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972", - "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53", - "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1", - "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", - "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a", - "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160", - "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c", - "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd", - "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", - "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5", - "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", - "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", - "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", - "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", - "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4", - "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", - "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", - "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28", - "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d", - "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a", - "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", - "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", - "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429", - "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", - "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", - "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", - "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392", - "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167", - "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c", - "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", - "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", - "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76", - "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875", - "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd", - "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", - "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db" + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" ], - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.0" }, "numpy": { "hashes": [ @@ -1016,107 +1016,107 @@ }, "propcache": { "hashes": [ - "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e", - "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe", - "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc", - "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829", - "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863", - "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f", - "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649", - "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6", - "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c", - "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a", - "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c", - "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545", - "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e", - "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe", - "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075", - "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57", - "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf", - "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d", - "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc", - "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0", - "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1", - "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64", - "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340", - "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db", - "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b", - "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641", - "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626", - "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7", - "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92", - "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07", - "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e", - "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787", - "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a", - "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810", - "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d", - "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0", - "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b", - "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043", - "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3", - "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7", - "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d", - "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf", - "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138", - "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c", - "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d", - "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46", - "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6", - "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa", - "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e", - "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05", - "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663", - "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f", - "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c", - "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f", - "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7", - "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f", - "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7", - "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9", - "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667", - "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86", - "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51", - "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0", - "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a", - "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c", - "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568", - "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af", - "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25", - "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5", - "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe", - "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf", - "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9", - "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf", - "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767", - "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90", - "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c", - "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d", - "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929", - "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e", - "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32", - "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14", - "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8", - "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b", - "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc", - "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa", - "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce", - "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b", - "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e", - "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf", - "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9", - "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac", - "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f", - "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374", - "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e", - "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d", - "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e", - "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121", - "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5", - "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54" + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" ], "markers": "python_version >= '3.9'", - "version": "==0.3.0" + "version": "==0.3.1" }, "pycparser": { "hashes": [ @@ -1128,117 +1128,116 @@ }, "pydantic": { "hashes": [ - "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", - "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236" + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" ], - "markers": "python_version >= '3.8'", - "version": "==2.10.6" + "markers": "python_version >= '3.9'", + "version": "==2.11.1" }, "pydantic-core": { "hashes": [ - "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278", - "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", - "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", - "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f", - "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", - "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", - "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54", - "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630", - "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", - "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", - "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", - "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", - "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", - "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", - "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", - "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", - "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", - "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd", - "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", - "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", - "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", - "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", - "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", - "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", - "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", - "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", - "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", - "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", - "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", - "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", - "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", - "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf", - "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", - "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", - "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76", - "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362", - "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", - "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", - "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320", - "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118", - "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96", - "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", - "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046", - "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", - "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", - "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", - "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", - "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67", - "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", - "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", - "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35", - "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", - "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", - "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b", - "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", - "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", - "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", - "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145", - "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", - "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", - "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", - "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", - "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", - "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", - "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5", - "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", - "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", - "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", - "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", - "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da", - "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", - "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", - "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993", - "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656", - "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4", - "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", - "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb", - "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d", - "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", - "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e", - "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", - "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc", - "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a", - "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9", - "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506", - "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b", - "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1", - "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", - "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", - "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", - "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", - "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", - "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", - "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", - "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308", - "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2", - "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228", - "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b", - "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", - "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad" + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" ], - "markers": "python_version >= '3.8'", - "version": "==2.27.2" + "markers": "python_version >= '3.9'", + "version": "==2.33.0" }, "pyjwt": { "hashes": [ @@ -1250,11 +1249,11 @@ }, "pyparsing": { "hashes": [ - "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", - "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a" + "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", + "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be" ], "markers": "python_version >= '3.9'", - "version": "==3.2.1" + "version": "==3.2.3" }, "pytest": { "hashes": [ @@ -1275,19 +1274,19 @@ }, "python-dotenv": { "hashes": [ - "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", - "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.0.1" + "markers": "python_version >= '3.9'", + "version": "==1.1.0" }, "pytz": { "hashes": [ - "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", - "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e" + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" ], - "version": "==2025.1" + "version": "==2025.2" }, "pyyaml": { "hashes": [ @@ -1350,12 +1349,12 @@ }, "rdflib": { "hashes": [ - "sha256:5402310a9f0f3c07d453d73fd0ad6ba35616286fe95d3670db2b725f3f539673", - "sha256:f3dcb4c106a8cd9e060d92f43d593d09ebc3d07adc244f4c7315856a12e383ee" + "sha256:72f4adb1990fa5241abd22ddaf36d7cafa5d91d9ff2ba13f3086d339b213d997", + "sha256:fed46e24f26a788e2ab8e445f7077f00edcf95abb73bcef4b86cefa8b62dd174" ], "index": "pypi", "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==7.1.3" + "version": "==7.1.4" }, "referencing": { "hashes": [ @@ -1375,112 +1374,123 @@ }, "rpds-py": { "hashes": [ - "sha256:09cd7dbcb673eb60518231e02874df66ec1296c01a4fcd733875755c02014b19", - "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c", - "sha256:0fced9fd4a07a1ded1bac7e961ddd9753dd5d8b755ba8e05acba54a21f5f1522", - "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31", - "sha256:11dd60b2ffddba85715d8a66bb39b95ddbe389ad2cfcf42c833f1bcde0878eaf", - "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4", - "sha256:1b08027489ba8fedde72ddd233a5ea411b85a6ed78175f40285bd401bde7466d", - "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b", - "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e", - "sha256:1eedaaccc9bb66581d4ae7c50e15856e335e57ef2734dbc5fd8ba3e2a4ab3cb6", - "sha256:243241c95174b5fb7204c04595852fe3943cc41f47aa14c3828bc18cd9d3b2d6", - "sha256:26bb3e8de93443d55e2e748e9fd87deb5f8075ca7bc0502cfc8be8687d69a2ec", - "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122", - "sha256:28358c54fffadf0ae893f6c1050e8f8853e45df22483b7fff2f6ab6152f5d8bf", - "sha256:285019078537949cecd0190f3690a0b0125ff743d6a53dfeb7a4e6787af154f5", - "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93", - "sha256:2a54027554ce9b129fc3d633c92fa33b30de9f08bc61b32c053dc9b537266fed", - "sha256:2c6ae11e6e93728d86aafc51ced98b1658a0080a7dd9417d24bfb955bb09c3c2", - "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd", - "sha256:35d5631ce0af26318dba0ae0ac941c534453e42f569011585cb323b7774502a5", - "sha256:3614d280bf7aab0d3721b5ce0e73434acb90a2c993121b6e81a1c15c665298ac", - "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c", - "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70", - "sha256:3d8abf7896a91fb97e7977d1aadfcc2c80415d6dc2f1d0fca5b8d0df247248f3", - "sha256:3e77febf227a1dc3220159355dba68faa13f8dca9335d97504abf428469fb18b", - "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5", - "sha256:3ee9d6f0b38efb22ad94c3b68ffebe4c47865cdf4b17f6806d6c674e1feb4246", - "sha256:4233df01a250b3984465faed12ad472f035b7cd5240ea3f7c76b7a7016084495", - "sha256:4263320ed887ed843f85beba67f8b2d1483b5947f2dc73a8b068924558bfeace", - "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f", - "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935", - "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64", - "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad", - "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957", - "sha256:5c9ff044eb07c8468594d12602291c635da292308c8c619244e30698e7fc455a", - "sha256:5e9c206a1abc27e0588cf8b7c8246e51f1a16a103734f7750830a1ccb63f557a", - "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6", - "sha256:633462ef7e61d839171bf206551d5ab42b30b71cac8f10a64a662536e057fdef", - "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba", - "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722", - "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10", - "sha256:721f9c4011b443b6e84505fc00cc7aadc9d1743f1c988e4c89353e19c4a968ee", - "sha256:72e680c1518733b73c994361e4b06441b92e973ef7d9449feec72e8ee4f713da", - "sha256:75307599f0d25bf6937248e5ac4e3bde5ea72ae6618623b86146ccc7845ed00b", - "sha256:754fba3084b70162a6b91efceee8a3f06b19e43dac3f71841662053c0584209a", - "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731", - "sha256:7938c7b0599a05246d704b3f5e01be91a93b411d0d6cc62275f025293b8a11ce", - "sha256:7b77e07233925bd33fc0022b8537774423e4c6680b6436316c5075e79b6384f4", - "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b", - "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707", - "sha256:7f9682a8f71acdf59fd554b82b1c12f517118ee72c0f3944eda461606dfe7eb9", - "sha256:8d67beb6002441faef8251c45e24994de32c4c8686f7356a1f601ad7c466f7c3", - "sha256:9441af1d25aed96901f97ad83d5c3e35e6cd21a25ca5e4916c82d7dd0490a4fa", - "sha256:98b257ae1e83f81fb947a363a274c4eb66640212516becaff7bef09a5dceacaa", - "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a", - "sha256:a1c66e71ecfd2a4acf0e4bd75e7a3605afa8f9b28a3b497e4ba962719df2be57", - "sha256:a1e17d8dc8e57d8e0fd21f8f0f0a5211b3fa258b2e444c2053471ef93fe25a00", - "sha256:a20cb698c4a59c534c6701b1c24a968ff2768b18ea2991f886bd8985ce17a89f", - "sha256:a970bfaf130c29a679b1d0a6e0f867483cea455ab1535fb427566a475078f27f", - "sha256:a98f510d86f689fcb486dc59e6e363af04151e5260ad1bdddb5625c10f1e95f8", - "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057", - "sha256:ad76f44f70aac3a54ceb1813ca630c53415da3a24fd93c570b2dfb4856591017", - "sha256:ae28144c1daa61366205d32abd8c90372790ff79fc60c1a8ad7fd3c8553a600e", - "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165", - "sha256:b5a96fcac2f18e5a0a23a75cd27ce2656c66c11c127b0318e508aab436b77428", - "sha256:b5ef909a37e9738d146519657a1aab4584018746a18f71c692f2f22168ece40c", - "sha256:b79f5ced71efd70414a9a80bbbfaa7160da307723166f09b69773153bf17c590", - "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4", - "sha256:b92f5654157de1379c509b15acec9d12ecf6e3bc1996571b6cb82a4302060447", - "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e", - "sha256:c1f8afa346ccd59e4e5630d5abb67aba6a9812fddf764fd7eb11f382a345f8cc", - "sha256:c5334a71f7dc1160382d45997e29f2637c02f8a26af41073189d79b95d3321f1", - "sha256:c617d7453a80e29d9973b926983b1e700a9377dbe021faa36041c78537d7b08c", - "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6", - "sha256:c6760211eee3a76316cf328f5a8bd695b47b1626d21c8a27fb3b2473a884d597", - "sha256:c698d123ce5d8f2d0cd17f73336615f6a2e3bdcedac07a1291bb4d8e7d82a05a", - "sha256:c76b32eb2ab650a29e423525e84eb197c45504b1c1e6e17b6cc91fcfeb1a4b1d", - "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8", - "sha256:c9e799dac1ffbe7b10c1fd42fe4cd51371a549c6e108249bde9cd1200e8f59b4", - "sha256:cafa48f2133d4daa028473ede7d81cd1b9f9e6925e9e4003ebdf77010ee02f35", - "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5", - "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5", - "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc", - "sha256:d6adb81564af0cd428910f83fa7da46ce9ad47c56c0b22b50872bc4515d91966", - "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d", - "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef", - "sha256:d9f75a06ecc68f159d5d7603b734e1ff6daa9497a929150f794013aa9f6e3f12", - "sha256:db7707dde9143a67b8812c7e66aeb2d843fe33cc8e374170f4d2c50bd8f2472d", - "sha256:e0397dd0b3955c61ef9b22838144aa4bef6f0796ba5cc8edfc64d468b93798b4", - "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149", - "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35", - "sha256:e5963ea87f88bddf7edd59644a35a0feecf75f8985430124c253612d4f7d27ae", - "sha256:e768267cbe051dd8d1c5305ba690bb153204a09bf2e3de3ae530de955f5b5580", - "sha256:e9cb79ecedfc156c0692257ac7ed415243b6c35dd969baa461a6888fc79f2f07", - "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219", - "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7", - "sha256:f35eff113ad430b5272bbfc18ba111c66ff525828f24898b4e146eb479a2cdda", - "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013", - "sha256:f7356a6da0562190558c4fcc14f0281db191cdf4cb96e7604c06acfcee96df15", - "sha256:f88626e3f5e57432e6191cd0c5d6d6b319b635e70b40be2ffba713053e5147dd", - "sha256:fad784a31869747df4ac968a351e070c06ca377549e4ace94775aaa3ab33ee06", - "sha256:fc869af5cba24d45fb0399b0cfdbcefcf6910bf4dee5d74036a57cf5264b3ff4", - "sha256:fee513135b5a58f3bb6d89e48326cd5aa308e4bcdf2f7d59f67c861ada482bf8" + "sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046", + "sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724", + "sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33", + "sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc", + "sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032", + "sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a", + "sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7", + "sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c", + "sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718", + "sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc", + "sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d", + "sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272", + "sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f", + "sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d", + "sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b", + "sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb", + "sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef", + "sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b", + "sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45", + "sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4", + "sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796", + "sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3", + "sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c", + "sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9", + "sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f", + "sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029", + "sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9", + "sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399", + "sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586", + "sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda", + "sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91", + "sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b", + "sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a", + "sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c", + "sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405", + "sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5", + "sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143", + "sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a", + "sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c", + "sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78", + "sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0", + "sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350", + "sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7", + "sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba", + "sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664", + "sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a", + "sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56", + "sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e", + "sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d", + "sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1", + "sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964", + "sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791", + "sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124", + "sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e", + "sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120", + "sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad", + "sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc", + "sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c", + "sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e", + "sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba", + "sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797", + "sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149", + "sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5", + "sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240", + "sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034", + "sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25", + "sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7", + "sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d", + "sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793", + "sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba", + "sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d", + "sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d", + "sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391", + "sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e", + "sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f", + "sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7", + "sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd", + "sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f", + "sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb", + "sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea", + "sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e", + "sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052", + "sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd", + "sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47", + "sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d", + "sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9", + "sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8", + "sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875", + "sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65", + "sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e", + "sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114", + "sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44", + "sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9", + "sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a", + "sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205", + "sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164", + "sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58", + "sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3", + "sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6", + "sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97", + "sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6", + "sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae", + "sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727", + "sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098", + "sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c", + "sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1", + "sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8", + "sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d", + "sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103", + "sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30", + "sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d", + "sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5", + "sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07", + "sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83" ], "markers": "python_version >= '3.9'", - "version": "==0.23.1" + "version": "==0.24.0" }, "six": { "hashes": [ @@ -1492,66 +1502,66 @@ }, "sqlalchemy": { "hashes": [ - "sha256:018ee97c558b499b58935c5a152aeabf6d36b3d55d91656abeb6d93d663c0c4c", - "sha256:01da15490c9df352fbc29859d3c7ba9cd1377791faeeb47c100832004c99472c", - "sha256:04545042969833cb92e13b0a3019549d284fd2423f318b6ba10e7aa687690a3c", - "sha256:06205eb98cb3dd52133ca6818bf5542397f1dd1b69f7ea28aa84413897380b06", - "sha256:08cf721bbd4391a0e765fe0fe8816e81d9f43cece54fdb5ac465c56efafecb3d", - "sha256:0d7e3866eb52d914aea50c9be74184a0feb86f9af8aaaa4daefe52b69378db0b", - "sha256:125a7763b263218a80759ad9ae2f3610aaf2c2fbbd78fff088d584edf81f3782", - "sha256:23c5aa33c01bd898f879db158537d7e7568b503b15aad60ea0c8da8109adf3e7", - "sha256:2600a50d590c22d99c424c394236899ba72f849a02b10e65b4c70149606408b5", - "sha256:2d7332868ce891eda48896131991f7f2be572d65b41a4050957242f8e935d5d7", - "sha256:2ed107331d188a286611cea9022de0afc437dd2d3c168e368169f27aa0f61338", - "sha256:3395e7ed89c6d264d38bea3bfb22ffe868f906a7985d03546ec7dc30221ea980", - "sha256:344cd1ec2b3c6bdd5dfde7ba7e3b879e0f8dd44181f16b895940be9b842fd2b6", - "sha256:34d5c49f18778a3665d707e6286545a30339ad545950773d43977e504815fa70", - "sha256:35e72518615aa5384ef4fae828e3af1b43102458b74a8c481f69af8abf7e802a", - "sha256:3eb14ba1a9d07c88669b7faf8f589be67871d6409305e73e036321d89f1d904e", - "sha256:412c6c126369ddae171c13987b38df5122cb92015cba6f9ee1193b867f3f1530", - "sha256:4600c7a659d381146e1160235918826c50c80994e07c5b26946a3e7ec6c99249", - "sha256:463ecfb907b256e94bfe7bcb31a6d8c7bc96eca7cbe39803e448a58bb9fcad02", - "sha256:4a06e6c8e31c98ddc770734c63903e39f1947c9e3e5e4bef515c5491b7737dde", - "sha256:4b2de1523d46e7016afc7e42db239bd41f2163316935de7c84d0e19af7e69538", - "sha256:4dabd775fd66cf17f31f8625fc0e4cfc5765f7982f94dc09b9e5868182cb71c0", - "sha256:4eff9c270afd23e2746e921e80182872058a7a592017b2713f33f96cc5f82e32", - "sha256:52607d0ebea43cf214e2ee84a6a76bc774176f97c5a774ce33277514875a718e", - "sha256:533e0f66c32093a987a30df3ad6ed21170db9d581d0b38e71396c49718fbb1ca", - "sha256:5493a8120d6fc185f60e7254fc056a6742f1db68c0f849cfc9ab46163c21df47", - "sha256:5d2d1fe548def3267b4c70a8568f108d1fed7cbbeccb9cc166e05af2abc25c22", - "sha256:5dfbc543578058c340360f851ddcecd7a1e26b0d9b5b69259b526da9edfa8875", - "sha256:66a40003bc244e4ad86b72abb9965d304726d05a939e8c09ce844d27af9e6d37", - "sha256:67de057fbcb04a066171bd9ee6bcb58738d89378ee3cabff0bffbf343ae1c787", - "sha256:6827f8c1b2f13f1420545bd6d5b3f9e0b85fe750388425be53d23c760dcf176b", - "sha256:6b35e07f1d57b79b86a7de8ecdcefb78485dab9851b9638c2c793c50203b2ae8", - "sha256:7399d45b62d755e9ebba94eb89437f80512c08edde8c63716552a3aade61eb42", - "sha256:788b6ff6728072b313802be13e88113c33696a9a1f2f6d634a97c20f7ef5ccce", - "sha256:78f1b79132a69fe8bd6b5d91ef433c8eb40688ba782b26f8c9f3d2d9ca23626f", - "sha256:79f4f502125a41b1b3b34449e747a6abfd52a709d539ea7769101696bdca6716", - "sha256:7a8517b6d4005facdbd7eb4e8cf54797dbca100a7df459fdaff4c5123265c1cd", - "sha256:7bd5c5ee1448b6408734eaa29c0d820d061ae18cb17232ce37848376dcfa3e92", - "sha256:7f5243357e6da9a90c56282f64b50d29cba2ee1f745381174caacc50d501b109", - "sha256:805cb481474e111ee3687c9047c5f3286e62496f09c0e82e8853338aaaa348f8", - "sha256:871f55e478b5a648c08dd24af44345406d0e636ffe021d64c9b57a4a11518304", - "sha256:87a1ce1f5e5dc4b6f4e0aac34e7bb535cb23bd4f5d9c799ed1633b65c2bcad8c", - "sha256:8a10ca7f8a1ea0fd5630f02feb055b0f5cdfcd07bb3715fc1b6f8cb72bf114e4", - "sha256:995c2bacdddcb640c2ca558e6760383dcdd68830160af92b5c6e6928ffd259b4", - "sha256:9f03143f8f851dd8de6b0c10784363712058f38209e926723c80654c1b40327a", - "sha256:a1c6b0a5e3e326a466d809b651c63f278b1256146a377a528b6938a279da334f", - "sha256:a28f9c238f1e143ff42ab3ba27990dfb964e5d413c0eb001b88794c5c4a528a9", - "sha256:b2cf5b5ddb69142511d5559c427ff00ec8c0919a1e6c09486e9c32636ea2b9dd", - "sha256:b761a6847f96fdc2d002e29e9e9ac2439c13b919adfd64e8ef49e75f6355c548", - "sha256:bf555f3e25ac3a70c67807b2949bfe15f377a40df84b71ab2c58d8593a1e036e", - "sha256:c08a972cbac2a14810463aec3a47ff218bb00c1a607e6689b531a7c589c50723", - "sha256:c457a38351fb6234781d054260c60e531047e4d07beca1889b558ff73dc2014b", - "sha256:c4c433f78c2908ae352848f56589c02b982d0e741b7905228fad628999799de4", - "sha256:d9f119e7736967c0ea03aff91ac7d04555ee038caf89bb855d93bbd04ae85b41", - "sha256:e6b0a1c7ed54a5361aaebb910c1fa864bae34273662bb4ff788a527eafd6e14d", - "sha256:f2bcb085faffcacf9319b1b1445a7e1cfdc6fb46c03f2dce7bc2d9a4b3c1cdc5", - "sha256:fe193d3ae297c423e0e567e240b4324d6b6c280a048e64c77a3ea6886cc2aa87" + "sha256:00a494ea6f42a44c326477b5bee4e0fc75f6a80c01570a32b57e89cf0fbef85a", + "sha256:0bb933a650323e476a2e4fbef8997a10d0003d4da996aad3fd7873e962fdde4d", + "sha256:110179728e442dae85dd39591beb74072ae4ad55a44eda2acc6ec98ead80d5f2", + "sha256:15d08d5ef1b779af6a0909b97be6c1fd4298057504eb6461be88bd1696cb438e", + "sha256:16d325ea898f74b26ffcd1cf8c593b0beed8714f0317df2bed0d8d1de05a8f26", + "sha256:1abb387710283fc5983d8a1209d9696a4eae9db8d7ac94b402981fe2fe2e39ad", + "sha256:1ffdf9c91428e59744f8e6f98190516f8e1d05eec90e936eb08b257332c5e870", + "sha256:2be94d75ee06548d2fc591a3513422b873490efb124048f50556369a834853b0", + "sha256:2cbafc8d39ff1abdfdda96435f38fab141892dc759a2165947d1a8fffa7ef596", + "sha256:2ee5f9999a5b0e9689bed96e60ee53c3384f1a05c2dd8068cc2e8361b0df5b7a", + "sha256:32587e2e1e359276957e6fe5dad089758bc042a971a8a09ae8ecf7a8fe23d07a", + "sha256:35904d63412db21088739510216e9349e335f142ce4a04b69e2528020ee19ed4", + "sha256:37a5c21ab099a83d669ebb251fddf8f5cee4d75ea40a5a1653d9c43d60e20867", + "sha256:37f7a0f506cf78c80450ed1e816978643d3969f99c4ac6b01104a6fe95c5490a", + "sha256:46628ebcec4f23a1584fb52f2abe12ddb00f3bb3b7b337618b80fc1b51177aff", + "sha256:4a4c5a2905a9ccdc67a8963e24abd2f7afcd4348829412483695c59e0af9a705", + "sha256:4aeb939bcac234b88e2d25d5381655e8353fe06b4e50b1c55ecffe56951d18c2", + "sha256:50f5885bbed261fc97e2e66c5156244f9704083a674b8d17f24c72217d29baf5", + "sha256:519624685a51525ddaa7d8ba8265a1540442a2ec71476f0e75241eb8263d6f51", + "sha256:5434223b795be5c5ef8244e5ac98056e290d3a99bdcc539b916e282b160dda00", + "sha256:55028d7a3ebdf7ace492fab9895cbc5270153f75442a0472d8516e03159ab364", + "sha256:5654d1ac34e922b6c5711631f2da497d3a7bffd6f9f87ac23b35feea56098011", + "sha256:574aea2c54d8f1dd1699449f332c7d9b71c339e04ae50163a3eb5ce4c4325ee4", + "sha256:5cfa124eda500ba4b0d3afc3e91ea27ed4754e727c7f025f293a22f512bcd4c9", + "sha256:5ea9181284754d37db15156eb7be09c86e16e50fbe77610e9e7bee09291771a1", + "sha256:641ee2e0834812d657862f3a7de95e0048bdcb6c55496f39c6fa3d435f6ac6ad", + "sha256:650490653b110905c10adac69408380688cefc1f536a137d0d69aca1069dc1d1", + "sha256:6959738971b4745eea16f818a2cd086fb35081383b078272c35ece2b07012716", + "sha256:6cfedff6878b0e0d1d0a50666a817ecd85051d12d56b43d9d425455e608b5ba0", + "sha256:7e0505719939e52a7b0c65d20e84a6044eb3712bb6f239c6b1db77ba8e173a37", + "sha256:8b6b28d303b9d57c17a5164eb1fd2d5119bb6ff4413d5894e74873280483eeb5", + "sha256:8bb131ffd2165fae48162c7bbd0d97c84ab961deea9b8bab16366543deeab625", + "sha256:915866fd50dd868fdcc18d61d8258db1bf9ed7fbd6dfec960ba43365952f3b01", + "sha256:9408fd453d5f8990405cc9def9af46bfbe3183e6110401b407c2d073c3388f47", + "sha256:957f8d85d5e834397ef78a6109550aeb0d27a53b5032f7a57f2451e1adc37e98", + "sha256:9c7a80ed86d6aaacb8160a1caef6680d4ddd03c944d985aecee940d168c411d1", + "sha256:9d3b31d0a1c44b74d3ae27a3de422dfccd2b8f0b75e51ecb2faa2bf65ab1ba0d", + "sha256:a669cbe5be3c63f75bcbee0b266779706f1a54bcb1000f302685b87d1b8c1500", + "sha256:a8aae085ea549a1eddbc9298b113cffb75e514eadbb542133dd2b99b5fb3b6af", + "sha256:ae9597cab738e7cc823f04a704fb754a9249f0b6695a6aeb63b74055cd417a96", + "sha256:afe63b208153f3a7a2d1a5b9df452b0673082588933e54e7c8aac457cf35e758", + "sha256:b5a5bbe29c10c5bfd63893747a1bf6f8049df607638c786252cb9243b86b6706", + "sha256:baf7cee56bd552385c1ee39af360772fbfc2f43be005c78d1140204ad6148438", + "sha256:bb19e30fdae77d357ce92192a3504579abe48a66877f476880238a962e5b96db", + "sha256:bece9527f5a98466d67fb5d34dc560c4da964240d8b09024bb21c1246545e04e", + "sha256:c0cae71e20e3c02c52f6b9e9722bca70e4a90a466d59477822739dc31ac18b4b", + "sha256:c268b5100cfeaa222c40f55e169d484efa1384b44bf9ca415eae6d556f02cb08", + "sha256:c7b927155112ac858357ccf9d255dd8c044fd9ad2dc6ce4c4149527c901fa4c3", + "sha256:c884de19528e0fcd9dc34ee94c810581dd6e74aef75437ff17e696c2bfefae3e", + "sha256:cd2f75598ae70bcfca9117d9e51a3b06fe29edd972fdd7fd57cc97b4dbf3b08a", + "sha256:cf0e99cdb600eabcd1d65cdba0d3c91418fee21c4aa1d28db47d095b1064a7d8", + "sha256:d827099289c64589418ebbcaead0145cd19f4e3e8a93919a0100247af245fa00", + "sha256:e8040680eaacdce4d635f12c55c714f3d4c7f57da2bc47a01229d115bd319191", + "sha256:f0fda83e113bb0fb27dc003685f32a5dcb99c9c4f41f4fa0838ac35265c23b5c", + "sha256:f1ea21bef99c703f44444ad29c2c1b6bd55d202750b6de8e06a955380f4725d7", + "sha256:f6bacab7514de6146a1976bc56e1545bee247242fab030b89e5f70336fc0003e", + "sha256:fe147fcd85aaed53ce90645c91ed5fca0cc88a797314c70dfd9d35925bd5d106" ], "markers": "python_version >= '3.7'", - "version": "==2.0.39" + "version": "==2.0.40" }, "sqlalchemy-utils": { "hashes": [ @@ -1595,19 +1605,27 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" }, "tzdata": { "hashes": [ - "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", - "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639" + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" ], "markers": "python_version >= '2'", - "version": "==2025.1" + "version": "==2025.2" }, "urllib3": { "hashes": [ @@ -1908,73 +1926,73 @@ }, "coverage": { "hashes": [ - "sha256:056d3017ed67e7ddf266e6f57378ece543755a4c9231e997789ab3bd11392c94", - "sha256:0ce8cf59e09d31a4915ff4c3b94c6514af4c84b22c4cc8ad7c3c546a86150a92", - "sha256:104bf640f408f4e115b85110047c7f27377e1a8b7ba86f7db4fa47aa49dc9a8e", - "sha256:1393e5aa9441dafb0162c36c8506c648b89aea9565b31f6bfa351e66c11bcd82", - "sha256:1586ad158523f4133499a4f322b230e2cfef9cc724820dbd58595a5a236186f4", - "sha256:180e3fc68ee4dc5af8b33b6ca4e3bb8aa1abe25eedcb958ba5cff7123071af68", - "sha256:1b336d06af14f8da5b1f391e8dec03634daf54dfcb4d1c4fb6d04c09d83cef90", - "sha256:1c8fbce80b2b8bf135d105aa8f5b36eae0c57d702a1cc3ebdea2a6f03f6cdde5", - "sha256:2d673e3add00048215c2cc507f1228a7523fd8bf34f279ac98334c9b07bd2656", - "sha256:316f29cc3392fa3912493ee4c83afa4a0e2db04ff69600711f8c03997c39baaa", - "sha256:33c1394d8407e2771547583b66a85d07ed441ff8fae5a4adb4237ad39ece60db", - "sha256:37cbc7b0d93dfd133e33c7ec01123fbb90401dce174c3b6661d8d36fb1e30608", - "sha256:39abcacd1ed54e2c33c54bdc488b310e8ef6705833f7148b6eb9a547199d375d", - "sha256:3ab7090f04b12dc6469882ce81244572779d3a4b67eea1c96fb9ecc8c607ef39", - "sha256:3b0e6e54591ae0d7427def8a4d40fca99df6b899d10354bab73cd5609807261c", - "sha256:416e2a8845eaff288f97eaf76ab40367deafb9073ffc47bf2a583f26b05e5265", - "sha256:4545485fef7a8a2d8f30e6f79ce719eb154aab7e44217eb444c1d38239af2072", - "sha256:4c124025430249118d018dcedc8b7426f39373527c845093132196f2a483b6dd", - "sha256:4fbb7a0c3c21908520149d7751cf5b74eb9b38b54d62997b1e9b3ac19a8ee2fe", - "sha256:52fc89602cde411a4196c8c6894afb384f2125f34c031774f82a4f2608c59d7d", - "sha256:55143aa13c49491f5606f05b49ed88663446dce3a4d3c5d77baa4e36a16d3573", - "sha256:57f3bd0d29bf2bd9325c0ff9cc532a175110c4bf8f412c05b2405fd35745266d", - "sha256:5b2f144444879363ea8834cd7b6869d79ac796cb8f864b0cfdde50296cd95816", - "sha256:5efdeff5f353ed3352c04e6b318ab05c6ce9249c25ed3c2090c6e9cadda1e3b2", - "sha256:60e6347d1ed882b1159ffea172cb8466ee46c665af4ca397edbf10ff53e9ffaf", - "sha256:693d921621a0c8043bfdc61f7d4df5ea6d22165fe8b807cac21eb80dd94e4bbd", - "sha256:708f0a1105ef2b11c79ed54ed31f17e6325ac936501fc373f24be3e6a578146a", - "sha256:70f0925c4e2bfc965369f417e7cc72538fd1ba91639cf1e4ef4b1a6b50439b3b", - "sha256:7789e700f33f2b133adae582c9f437523cd5db8de845774988a58c360fc88253", - "sha256:7b6c96d69928a3a6767fab8dc1ce8a02cf0156836ccb1e820c7f45a423570d98", - "sha256:7d2a65876274acf544703e943c010b60bd79404e3623a1e5d52b64a6e2728de5", - "sha256:7f18d47641282664276977c604b5a261e51fefc2980f5271d547d706b06a837f", - "sha256:89078312f06237417adda7c021c33f80f7a6d2db8572a5f6c330d89b080061ce", - "sha256:8c938c6ae59be67ac19a7204e079efc94b38222cd7d0269f96e45e18cddeaa59", - "sha256:8e336b56301774ace6be0017ff85c3566c556d938359b61b840796a0202f805c", - "sha256:a0a207c87a9f743c8072d059b4711f8d13c456eb42dac778a7d2e5d4f3c253a7", - "sha256:a2454b12a3f12cc4698f3508912e6225ec63682e2ca5a96f80a2b93cef9e63f3", - "sha256:a538a23119d1e2e2ce077e902d02ea3d8e0641786ef6e0faf11ce82324743944", - "sha256:aa4dff57fc21a575672176d5ab0ef15a927199e775c5e8a3d75162ab2b0c7705", - "sha256:ad0edaa97cb983d9f2ff48cadddc3e1fb09f24aa558abeb4dc9a0dbacd12cbb4", - "sha256:ae8006772c6b0fa53c33747913473e064985dac4d65f77fd2fdc6474e7cd54e4", - "sha256:b0fac2088ec4aaeb5468b814bd3ff5e5978364bfbce5e567c44c9e2854469f6c", - "sha256:b3e212a894d8ae07fde2ca8b43d666a6d49bbbddb10da0f6a74ca7bd31f20054", - "sha256:b54a1ee4c6f1905a436cbaa04b26626d27925a41cbc3a337e2d3ff7038187f07", - "sha256:b667b91f4f714b17af2a18e220015c941d1cf8b07c17f2160033dbe1e64149f0", - "sha256:b8c36093aca722db73633cf2359026ed7782a239eb1c6db2abcff876012dc4cf", - "sha256:bb356e7ae7c2da13f404bf8f75be90f743c6df8d4607022e759f5d7d89fe83f8", - "sha256:bce730d484038e97f27ea2dbe5d392ec5c2261f28c319a3bb266f6b213650135", - "sha256:c075d167a6ec99b798c1fdf6e391a1d5a2d054caffe9593ba0f97e3df2c04f0e", - "sha256:c4e09534037933bf6eb31d804e72c52ec23219b32c1730f9152feabbd7499463", - "sha256:c5f8a5364fc37b2f172c26a038bc7ec4885f429de4a05fc10fdcb53fb5834c5c", - "sha256:cb203c0afffaf1a8f5b9659a013f8f16a1b2cad3a80a8733ceedc968c0cf4c57", - "sha256:cc41374d2f27d81d6558f8a24e5c114580ffefc197fd43eabd7058182f743322", - "sha256:cd879d4646055a573775a1cec863d00c9ff8c55860f8b17f6d8eee9140c06166", - "sha256:d013c07061751ae81861cae6ec3a4fe04e84781b11fd4b6b4201590234b25c7b", - "sha256:d8c7524779003d59948c51b4fcbf1ca4e27c26a7d75984f63488f3625c328b9b", - "sha256:d9710521f07f526de30ccdead67e6b236fe996d214e1a7fba8b36e2ba2cd8261", - "sha256:e1ffde1d6bc2a92f9c9207d1ad808550873748ac2d4d923c815b866baa343b3f", - "sha256:e7f559c36d5cdc448ee13e7e56ed7b6b5d44a40a511d584d388a0f5d940977ba", - "sha256:f2a1e18a85bd066c7c556d85277a7adf4651f259b2579113844835ba1a74aafd", - "sha256:f32b165bf6dfea0846a9c9c38b7e1d68f313956d60a15cde5d1709fddcaf3bee", - "sha256:f5a2f71d6a91238e7628f23538c26aa464d390cbdedf12ee2a7a0fb92a24482a", - "sha256:f81fe93dc1b8e5673f33443c0786c14b77e36f1025973b85e07c70353e46882b" + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==7.7.0" + "version": "==7.7.1" }, "idna": { "hashes": [ @@ -1986,11 +2004,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "packaging": { "hashes": [ diff --git a/dbrepo-search-service/app.py b/dbrepo-search-service/app.py index 8e26546532..1ee06add21 100644 --- a/dbrepo-search-service/app.py +++ b/dbrepo-search-service/app.py @@ -4,15 +4,13 @@ import os from json import dumps from typing import List, Any -import requests -from clients.keycloak_client import User, KeycloakClient -from clients.opensearch_client import OpenSearchClient, flatten from dbrepo.api.dto import Database, ApiError +from dbrepo.core.client.auth import User, AuthServiceClient +from dbrepo.core.client.search import SearchServiceClient, flatten from flasgger import LazyJSONEncoder, Swagger, swag_from from flask import Flask, request, Response from flask_cors import CORS from flask_httpauth import HTTPTokenAuth, HTTPBasicAuth, MultiAuth -from jwt.exceptions import JWTDecodeError from opensearchpy import NotFoundError from prometheus_flask_exporter import PrometheusMetrics from pydantic import ValidationError @@ -135,7 +133,24 @@ template = { "type": "object" } } - } + }, + "ApiError": { + "properties": { + "message": { + "example": "Message", + "type": "string" + }, + "status": { + "example": "BAD_REQUEST", + "type": "string" + }, + "code": { + "example": "error.dashboard.create", + "type": "string" + } + }, + "type": "object" + }, }, "securitySchemes": { "bearerAuth": { @@ -154,7 +169,7 @@ template = { "info": { "title": "Database Repository Search Service API", "description": "Service that searches the search database", - "version": "1.5", + "version": "1.8.0", "contact": { "name": "Prof. Andreas Rauber", "email": "andreas.rauber@tuwien.ac.at" @@ -166,7 +181,7 @@ template = { }, "externalDocs": { "description": "Sourcecode Documentation", - "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/" + "url": "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" }, "servers": [ { @@ -185,7 +200,7 @@ app.config["METADATA_SERVICE_ENDPOINT"] = os.getenv("METADATA_SERVICE_ENDPOINT", app.config["JWT_ALGORITHM"] = "HS256" app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKEY", "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB") + '\n-----END PUBLIC KEY-----' -app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://auth-service:8080") +app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost:8080") app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") app.config["OPENSEARCH_HOST"] = os.getenv('OPENSEARCH_HOST', 'search-db') @@ -195,41 +210,31 @@ app.config["OPENSEARCH_PASSWORD"] = os.getenv('OPENSEARCH_PASSWORD', 'admin') app.json_encoder = LazyJSONEncoder +auth_client = AuthServiceClient(app.config["AUTH_SERVICE_ENDPOINT"], app.config["AUTH_SERVICE_CLIENT"], + app.config["AUTH_SERVICE_CLIENT_SECRET"], app.config["JWT_PUBKEY"]) + @token_auth.verify_token def verify_token(token: str) -> bool | User: - if token is None or token == "": - return False - try: - client = KeycloakClient() - return client.verify_jwt(access_token=token) - except JWTDecodeError: - return False + return auth_client.is_valid_token(token) @basic_auth.verify_password def verify_password(username: str, password: str) -> Any: - if username is None or username == "" or password is None or password == "": - return False - client = KeycloakClient() - try: - return client.verify_jwt(access_token=client.obtain_user_token(username=username, password=password)) - except AssertionError as error: - logging.error(error) - return False - except requests.exceptions.ConnectionError as error: - logging.error(f"Failed to connect to Authentication Service {error}") - return False + return auth_client.is_valid_password(username, password) @token_auth.get_user_roles def get_user_roles(user: User) -> List[str]: - return user.roles + return auth_client.get_user_roles(user) @basic_auth.get_user_roles def get_user_roles(user: User) -> List[str]: - return user.roles + return auth_client.get_user_roles(user) + + +headers = {'Content-Type': 'application/json'} def general_filter(index, results): @@ -264,9 +269,14 @@ def general_filter(index, results): return results +def search_client(): + return SearchServiceClient(app.config["OPENSEARCH_HOST"], int(app.config["OPENSEARCH_PORT"]), + app.config["OPENSEARCH_USERNAME"], app.config["OPENSEARCH_PASSWORD"]) + + @app.route("/health", methods=["GET"], endpoint="actuator_health") def health(): - return dict({"status": "UP"}), 200 + return dict({"status": "UP"}), 200, headers @app.route("/api/search/<string:index>", methods=["GET"], endpoint="search_get_index") @@ -279,7 +289,7 @@ def get_index(index: str): :return: list of the results """ logging.debug(f'endpoint get search type: {index}') - results = OpenSearchClient().query_index_by_term_opensearch("*", "contains") + results = search_client().query_index_by_term_opensearch("*", "contains") try: results = general_filter(index, results) @@ -287,10 +297,10 @@ def get_index(index: str): max_pages = math.ceil(len(results) / results_per_page) page = min(request.args.get("page", 1, type=int), max_pages) results = results[(results_per_page * (page - 1)): (results_per_page * page)] - return Response(dumps(results, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} + return Response(dumps(results, default=pydantic_encoder)), 200, headers except KeyError: return ApiError(status='NOT_FOUND', message=f'Failed to find get index: {index}', - code='search.index.missing').model_dump(), 404 + code='search.index.missing').model_dump(), 404, headers @app.route("/api/search/<string:field_type>/fields", methods=["GET"], endpoint="search_get_index_fields") @@ -304,12 +314,12 @@ def get_fields(field_type: str): """ logging.debug(f'endpoint get search type fields: {field_type}') try: - fields = OpenSearchClient().get_fields_for_index(field_type) + fields = search_client().get_fields_for_index(field_type) logging.debug(f'get fields for field_type {field_type} resulted in {len(fields)} field(s)') - return Response(dumps(fields, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} + return Response(dumps(fields, default=pydantic_encoder)), 200, headers except NotFoundError: return ApiError(status='NOT_FOUND', message=f'Failed to find fields for search type {field_type}', - code='search.type.missing').model_dump(), 404 + code='search.type.missing').model_dump(), 404, headers @app.route("/api/search", methods=["GET"], endpoint="search_fuzzy_search") @@ -326,13 +336,13 @@ def get_fuzzy_search(): return ApiError(status='BAD_REQUEST', message='Provide a search term with ?q=term', code='search.fuzzy.invalid').model_dump(), 400 logging.debug(f"search request query: {search_term}") - user_id, error, status = KeycloakClient().userId(request.headers.get('Authorization')) + user_id, error, status = auth_client.get_user_id(request.headers.get('Authorization')) if error is not None and status is not None: - return error, status - results: [Database] = OpenSearchClient().fuzzy_search(search_term=search_term, - user_id=user_id, - user_token=request.headers.get('Authorization')) - return Response(dumps(results, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} + return error, status, headers + results = search_client().fuzzy_search(search_term=search_term, + user_id=user_id, + user_token=request.headers.get('Authorization')) + return Response(dumps(results, default=pydantic_encoder)), 200, headers @app.route("/api/search/<string:field_type>", methods=["POST"], endpoint="search_post_general_search") @@ -354,16 +364,16 @@ def post_general_search(field_type): t2 = request.args.get("t2") if not str(t2).isdigit(): t2 = None - user_id, error, status = KeycloakClient().userId(request.headers.get('Authorization')) + user_id, error, status = auth_client.get_user_id(request.headers.get('Authorization')) if error is not None and status is not None: return error, status if t1 is not None and t2 is not None and "unit.uri" in value_pairs and "concept.uri" in value_pairs: - response: [Database] = OpenSearchClient().unit_independent_search(t1, t2, value_pairs, user_id) + response = search_client().unit_independent_search(t1, t2, value_pairs, user_id) else: - response: [Database] = OpenSearchClient().general_search(field_type=field_type, - field_value_pairs=value_pairs, - user_id=user_id, - user_token=request.headers.get('Authorization')) + response = search_client().general_search(field_type=field_type, + field_value_pairs=value_pairs, + user_id=user_id, + user_token=request.headers.get('Authorization')) # filter by type tables = [table for table in flatten([database.tables for database in response]) if table.is_public or table.is_schema_public or (user_id is not None and table.owner.id == user_id)] @@ -408,34 +418,34 @@ def post_general_search(field_type): response = tmp elif field_type == 'view': response = views - return Response(dumps(response, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} + return Response(dumps(response, default=pydantic_encoder)), 200, headers -@app.route("/api/search/database/<string:database_id>", methods=["PUT"], endpoint="search_put_database") -@metrics.gauge(name='dbrepo_search_update_database', +@app.route("/api/search/database/<string:database_id>", methods=["PUT"], endpoint="search_save_database") +@metrics.gauge(name='dbrepo_search_save_database', description='Time needed to update a database in the search database') @auth.login_required(role=['update-search-index']) -def update_database(database_id: str): - logging.debug(f"updating database with id: {database_id}") +def save_database(database_id: str): + logging.debug(f"save database with id: {database_id}") try: - payload: Database = Database.model_validate(request.json) + payload = Database.model_validate(request.json) except ValidationError as e: logging.error(f"Failed to validate: {e}") return ApiError(status='BAD_REQUEST', message=f'Malformed payload: {e}', code='search.general.missing').model_dump(), 400 - database = OpenSearchClient().update_database(database_id, payload) - logging.info(f"Updated database with id: {database_id}") - return database.model_dump(), 202 + search_client().save_database(database_id, payload) + return Response(), 202, headers @app.route("/api/search/database/<string:database_id>", methods=["DELETE"], endpoint="database_delete_database") @metrics.gauge(name='dbrepo_search_delete_database', description='Time needed to delete a database in the search database') -@auth.login_required(role=['admin']) +@auth.login_required(role=['system']) def delete_database(database_id: str): + logging.debug(f"delete database with id: {database_id}") try: - OpenSearchClient().delete_database(database_id) - return Response(dumps({})), 202 + search_client().delete_database(database_id) + return Response(dumps({})), 202, headers except NotFoundError: return ApiError(status='NOT_FOUND', message='Failed to find database', code='search.database.missing').model_dump(), 404 diff --git a/dbrepo-search-service/examples/database/fields_response_payload.json b/dbrepo-search-service/examples/database/fields_response_payload.json deleted file mode 100644 index 2eab729543..0000000000 --- a/dbrepo-search-service/examples/database/fields_response_payload.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "fields": [ - { - "attribute_name": "_class", - "type": "keyword" - }, - { - "attribute_name": "container", - "type": "nested" - }, - { - "attribute_name": "container.properties._class", - "type": "keyword" - }, - { - "attribute_name": "container.properties.created", - "type": "date" - }, - { - "attribute_name": "created", - "type": "date" - }, - { - "attribute_name": "creator", - "type": "nested" - }, - { - "attribute_name": "creator.properties._class", - "type": "keyword" - }, - { - "attribute_name": "description", - "type": "text" - }, - { - "attribute_name": "exchange_name", - "type": "keyword" - }, - { - "attribute_name": "id", - "type": "keyword" - }, - { - "attribute_name": "internal_name", - "type": "keyword" - }, - { - "attribute_name": "is_public", - "type": "boolean" - }, - { - "attribute_name": "name", - "type": "keyword" - }, - { - "attribute_name": "owner", - "type": "nested" - }, - { - "attribute_name": "owner.properties._class", - "type": "keyword" - } - ], - "status": 200 -} \ No newline at end of file diff --git a/dbrepo-search-service/examples/database/search_request_payload.json b/dbrepo-search-service/examples/database/search_request_payload.json deleted file mode 100644 index de7101b1b2..0000000000 --- a/dbrepo-search-service/examples/database/search_request_payload.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "database.created": "2022-05-27", - "database.description": "Some description", - "database.is_public": true, - "id": "5", - "internal_name": "test_db", - "name": "Test DB", - "search_term": "free text here", - "type": "database" -} \ No newline at end of file diff --git a/dbrepo-search-service/examples/unit/fields_response_payload.json b/dbrepo-search-service/examples/unit/fields_response_payload.json deleted file mode 100644 index e6bca5a6fe..0000000000 --- a/dbrepo-search-service/examples/unit/fields_response_payload.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "fields": [ - { - "attribute_name": "_class", - "type": "keyword" - }, - { - "attribute_name": "created", - "type": "date" - }, - { - "attribute_name": "description", - "type": "text" - }, - { - "attribute_name": "id", - "type": "keyword" - }, - { - "attribute_name": "name", - "type": "keyword" - }, - { - "attribute_name": "uri", - "type": "keyword" - } - ], - "status": 200 -} \ No newline at end of file diff --git a/dbrepo-search-service/examples/unit/search_request_payload.json b/dbrepo-search-service/examples/unit/search_request_payload.json deleted file mode 100644 index 28356ec8db..0000000000 --- a/dbrepo-search-service/examples/unit/search_request_payload.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "7", - "name": "Test DB", - "search_term": "free text here", - "type": "unit", - "unit.uri": "some uri" -} \ No newline at end of file diff --git a/dbrepo-search-service/friendly_names_overrides.json b/dbrepo-search-service/friendly_names_overrides.json new file mode 100644 index 0000000000..8aca718186 --- /dev/null +++ b/dbrepo-search-service/friendly_names_overrides.json @@ -0,0 +1,18 @@ +{ + "tables.name": "Table Name", + "owner.id": "Owner ID", + "owner.username": "Owner Username", + "owner.attributes.orcid": "Owner ORCID", + "creator.orcid": "Creator ORCID", + "identifiers.doi": "DOI", + "identifiers.licenses.uri": "License URI", + "identifiers.funders.funder_identifier": "Funder PID", + "identifiers.table_id": "Table ID", + "identifiers.query_id": "Subset ID", + "identifiers.view_id": "View ID", + "identifiers.database_id": "Database ID", + "identifiers.creator.username": "Creator Username", + "is_public": "Public", + "tables.columns.concept.uri": "URI", + "tables.columns.unit.uri": "URI" +} \ No newline at end of file diff --git a/dbrepo-search-service/init/Dockerfile b/dbrepo-search-service/init/Dockerfile index b3874230bc..e61e29e080 100644 --- a/dbrepo-search-service/init/Dockerfile +++ b/dbrepo-search-service/init/Dockerfile @@ -1,9 +1,10 @@ FROM python:3.11-alpine3.21 LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" -RUN apk add --no-cache curl bash jq - -WORKDIR /home/alpine +RUN apk add --no-cache \ + curl \ + bash \ + jq COPY Pipfile Pipfile.lock ./ @@ -13,12 +14,12 @@ RUN pip install pipenv && \ pipenv install gunicorn && \ pipenv install --system --deploy -USER 1001 +RUN adduser -D dbrepo --uid 1001 WORKDIR /app -COPY --chown=1001 ./clients ./clients -COPY --chown=1001 ./omlib ./omlib +USER 1001 + COPY --chown=1001 ./app.py ./app.py COPY --chown=1001 ./database.json ./database.json diff --git a/dbrepo-search-service/init/Pipfile b/dbrepo-search-service/init/Pipfile index 9f970d4c87..36d0587c30 100644 --- a/dbrepo-search-service/init/Pipfile +++ b/dbrepo-search-service/init/Pipfile @@ -9,7 +9,7 @@ opensearch-py = "~=2.2" python-dotenv = "~=1.0" testcontainers-opensearch = "*" pytest = "*" -dbrepo = {path = "./lib/dbrepo-1.7.3.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.8.0.tar.gz"} rdflib = "*" [dev-packages] diff --git a/dbrepo-search-service/init/Pipfile.lock b/dbrepo-search-service/init/Pipfile.lock index 55997adfc4..c0c002e035 100644 --- a/dbrepo-search-service/init/Pipfile.lock +++ b/dbrepo-search-service/init/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "902ab105fecae6a9ffa50c6db24de91d2f41d0494033ffd7f3284049a9ba4add" + "sha256": "cea14bf77b1c52707b14b369fe1efbc89e42de3c12380256481dd1b08b57ebdf" }, "pipfile-spec": 6, "requires": { @@ -259,9 +259,9 @@ }, "dbrepo": { "hashes": [ - "sha256:ad01d6dc5d99f3c0c9caf3fb11b51502bec5390c72ff28b6b725e2755f5a2f7c" + "sha256:7b9a70cf1bd9d623e52ada74d5585df53716353d509f5d905f1b431dd91c28d6" ], - "path": "./lib/dbrepo-1.7.3.tar.gz" + "path": "./lib/dbrepo-1.8.0.tar.gz" }, "docker": { "hashes": [ @@ -394,11 +394,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "itsdangerous": { "hashes": [ @@ -485,101 +485,101 @@ }, "multidict": { "hashes": [ - "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", - "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056", - "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", - "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", - "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", - "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", - "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748", - "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", - "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f", - "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", - "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6", - "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada", - "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", - "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2", - "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d", - "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", - "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef", - "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", - "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", - "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60", - "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6", - "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", - "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478", - "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", - "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7", - "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56", - "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", - "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", - "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30", - "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", - "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", - "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0", - "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", - "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c", - "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", - "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", - "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", - "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", - "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", - "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2", - "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", - "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", - "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", - "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", - "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657", - "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581", - "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492", - "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43", - "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", - "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", - "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", - "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057", - "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc", - "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", - "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255", - "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1", - "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972", - "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53", - "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1", - "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", - "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a", - "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160", - "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c", - "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd", - "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", - "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5", - "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", - "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", - "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", - "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", - "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4", - "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", - "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", - "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28", - "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d", - "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a", - "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", - "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", - "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429", - "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", - "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", - "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", - "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392", - "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167", - "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c", - "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", - "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", - "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76", - "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875", - "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd", - "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", - "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db" + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" ], - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.0" }, "numpy": { "hashes": [ @@ -725,229 +725,228 @@ }, "propcache": { "hashes": [ - "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e", - "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe", - "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc", - "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829", - "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863", - "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f", - "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649", - "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6", - "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c", - "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a", - "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c", - "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545", - "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e", - "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe", - "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075", - "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57", - "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf", - "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d", - "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc", - "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0", - "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1", - "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64", - "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340", - "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db", - "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b", - "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641", - "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626", - "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7", - "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92", - "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07", - "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e", - "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787", - "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a", - "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810", - "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d", - "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0", - "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b", - "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043", - "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3", - "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7", - "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d", - "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf", - "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138", - "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c", - "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d", - "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46", - "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6", - "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa", - "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e", - "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05", - "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663", - "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f", - "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c", - "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f", - "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7", - "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f", - "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7", - "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9", - "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667", - "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86", - "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51", - "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0", - "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a", - "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c", - "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568", - "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af", - "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25", - "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5", - "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe", - "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf", - "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9", - "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf", - "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767", - "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90", - "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c", - "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d", - "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929", - "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e", - "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32", - "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14", - "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8", - "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b", - "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc", - "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa", - "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce", - "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b", - "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e", - "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf", - "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9", - "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac", - "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f", - "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374", - "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e", - "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d", - "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e", - "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121", - "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5", - "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54" + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" ], "markers": "python_version >= '3.9'", - "version": "==0.3.0" + "version": "==0.3.1" }, "pydantic": { "hashes": [ - "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", - "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236" + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" ], - "markers": "python_version >= '3.8'", - "version": "==2.10.6" + "markers": "python_version >= '3.9'", + "version": "==2.11.1" }, "pydantic-core": { "hashes": [ - "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278", - "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", - "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", - "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f", - "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", - "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", - "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54", - "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630", - "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", - "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", - "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", - "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", - "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", - "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", - "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", - "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", - "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", - "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd", - "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", - "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", - "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", - "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", - "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", - "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", - "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", - "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", - "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", - "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", - "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", - "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", - "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", - "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf", - "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", - "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", - "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76", - "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362", - "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", - "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", - "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320", - "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118", - "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96", - "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", - "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046", - "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", - "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", - "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", - "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", - "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67", - "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", - "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", - "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35", - "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", - "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", - "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b", - "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", - "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", - "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", - "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145", - "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", - "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", - "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", - "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", - "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", - "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", - "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5", - "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", - "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", - "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", - "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", - "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da", - "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", - "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", - "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993", - "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656", - "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4", - "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", - "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb", - "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d", - "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", - "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e", - "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", - "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc", - "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a", - "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9", - "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506", - "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b", - "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1", - "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", - "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", - "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", - "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", - "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", - "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", - "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", - "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308", - "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2", - "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228", - "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b", - "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", - "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad" + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" ], - "markers": "python_version >= '3.8'", - "version": "==2.27.2" + "markers": "python_version >= '3.9'", + "version": "==2.33.0" }, "pyparsing": { "hashes": [ - "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", - "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a" + "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", + "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be" ], "markers": "python_version >= '3.9'", - "version": "==3.2.1" + "version": "==3.2.3" }, "pytest": { "hashes": [ @@ -968,28 +967,28 @@ }, "python-dotenv": { "hashes": [ - "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", - "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" + "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", + "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.0.1" + "markers": "python_version >= '3.9'", + "version": "==1.1.0" }, "pytz": { "hashes": [ - "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", - "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e" + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" ], - "version": "==2025.1" + "version": "==2025.2" }, "rdflib": { "hashes": [ - "sha256:5402310a9f0f3c07d453d73fd0ad6ba35616286fe95d3670db2b725f3f539673", - "sha256:f3dcb4c106a8cd9e060d92f43d593d09ebc3d07adc244f4c7315856a12e383ee" + "sha256:72f4adb1990fa5241abd22ddaf36d7cafa5d91d9ff2ba13f3086d339b213d997", + "sha256:fed46e24f26a788e2ab8e445f7077f00edcf95abb73bcef4b86cefa8b62dd174" ], "index": "pypi", "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==7.1.3" + "version": "==7.1.4" }, "requests": { "hashes": [ @@ -1040,19 +1039,27 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" }, "tzdata": { "hashes": [ - "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", - "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639" + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" ], "markers": "python_version >= '2'", - "version": "==2025.1" + "version": "==2025.2" }, "urllib3": { "hashes": [ @@ -1426,73 +1433,73 @@ }, "coverage": { "hashes": [ - "sha256:056d3017ed67e7ddf266e6f57378ece543755a4c9231e997789ab3bd11392c94", - "sha256:0ce8cf59e09d31a4915ff4c3b94c6514af4c84b22c4cc8ad7c3c546a86150a92", - "sha256:104bf640f408f4e115b85110047c7f27377e1a8b7ba86f7db4fa47aa49dc9a8e", - "sha256:1393e5aa9441dafb0162c36c8506c648b89aea9565b31f6bfa351e66c11bcd82", - "sha256:1586ad158523f4133499a4f322b230e2cfef9cc724820dbd58595a5a236186f4", - "sha256:180e3fc68ee4dc5af8b33b6ca4e3bb8aa1abe25eedcb958ba5cff7123071af68", - "sha256:1b336d06af14f8da5b1f391e8dec03634daf54dfcb4d1c4fb6d04c09d83cef90", - "sha256:1c8fbce80b2b8bf135d105aa8f5b36eae0c57d702a1cc3ebdea2a6f03f6cdde5", - "sha256:2d673e3add00048215c2cc507f1228a7523fd8bf34f279ac98334c9b07bd2656", - "sha256:316f29cc3392fa3912493ee4c83afa4a0e2db04ff69600711f8c03997c39baaa", - "sha256:33c1394d8407e2771547583b66a85d07ed441ff8fae5a4adb4237ad39ece60db", - "sha256:37cbc7b0d93dfd133e33c7ec01123fbb90401dce174c3b6661d8d36fb1e30608", - "sha256:39abcacd1ed54e2c33c54bdc488b310e8ef6705833f7148b6eb9a547199d375d", - "sha256:3ab7090f04b12dc6469882ce81244572779d3a4b67eea1c96fb9ecc8c607ef39", - "sha256:3b0e6e54591ae0d7427def8a4d40fca99df6b899d10354bab73cd5609807261c", - "sha256:416e2a8845eaff288f97eaf76ab40367deafb9073ffc47bf2a583f26b05e5265", - "sha256:4545485fef7a8a2d8f30e6f79ce719eb154aab7e44217eb444c1d38239af2072", - "sha256:4c124025430249118d018dcedc8b7426f39373527c845093132196f2a483b6dd", - "sha256:4fbb7a0c3c21908520149d7751cf5b74eb9b38b54d62997b1e9b3ac19a8ee2fe", - "sha256:52fc89602cde411a4196c8c6894afb384f2125f34c031774f82a4f2608c59d7d", - "sha256:55143aa13c49491f5606f05b49ed88663446dce3a4d3c5d77baa4e36a16d3573", - "sha256:57f3bd0d29bf2bd9325c0ff9cc532a175110c4bf8f412c05b2405fd35745266d", - "sha256:5b2f144444879363ea8834cd7b6869d79ac796cb8f864b0cfdde50296cd95816", - "sha256:5efdeff5f353ed3352c04e6b318ab05c6ce9249c25ed3c2090c6e9cadda1e3b2", - "sha256:60e6347d1ed882b1159ffea172cb8466ee46c665af4ca397edbf10ff53e9ffaf", - "sha256:693d921621a0c8043bfdc61f7d4df5ea6d22165fe8b807cac21eb80dd94e4bbd", - "sha256:708f0a1105ef2b11c79ed54ed31f17e6325ac936501fc373f24be3e6a578146a", - "sha256:70f0925c4e2bfc965369f417e7cc72538fd1ba91639cf1e4ef4b1a6b50439b3b", - "sha256:7789e700f33f2b133adae582c9f437523cd5db8de845774988a58c360fc88253", - "sha256:7b6c96d69928a3a6767fab8dc1ce8a02cf0156836ccb1e820c7f45a423570d98", - "sha256:7d2a65876274acf544703e943c010b60bd79404e3623a1e5d52b64a6e2728de5", - "sha256:7f18d47641282664276977c604b5a261e51fefc2980f5271d547d706b06a837f", - "sha256:89078312f06237417adda7c021c33f80f7a6d2db8572a5f6c330d89b080061ce", - "sha256:8c938c6ae59be67ac19a7204e079efc94b38222cd7d0269f96e45e18cddeaa59", - "sha256:8e336b56301774ace6be0017ff85c3566c556d938359b61b840796a0202f805c", - "sha256:a0a207c87a9f743c8072d059b4711f8d13c456eb42dac778a7d2e5d4f3c253a7", - "sha256:a2454b12a3f12cc4698f3508912e6225ec63682e2ca5a96f80a2b93cef9e63f3", - "sha256:a538a23119d1e2e2ce077e902d02ea3d8e0641786ef6e0faf11ce82324743944", - "sha256:aa4dff57fc21a575672176d5ab0ef15a927199e775c5e8a3d75162ab2b0c7705", - "sha256:ad0edaa97cb983d9f2ff48cadddc3e1fb09f24aa558abeb4dc9a0dbacd12cbb4", - "sha256:ae8006772c6b0fa53c33747913473e064985dac4d65f77fd2fdc6474e7cd54e4", - "sha256:b0fac2088ec4aaeb5468b814bd3ff5e5978364bfbce5e567c44c9e2854469f6c", - "sha256:b3e212a894d8ae07fde2ca8b43d666a6d49bbbddb10da0f6a74ca7bd31f20054", - "sha256:b54a1ee4c6f1905a436cbaa04b26626d27925a41cbc3a337e2d3ff7038187f07", - "sha256:b667b91f4f714b17af2a18e220015c941d1cf8b07c17f2160033dbe1e64149f0", - "sha256:b8c36093aca722db73633cf2359026ed7782a239eb1c6db2abcff876012dc4cf", - "sha256:bb356e7ae7c2da13f404bf8f75be90f743c6df8d4607022e759f5d7d89fe83f8", - "sha256:bce730d484038e97f27ea2dbe5d392ec5c2261f28c319a3bb266f6b213650135", - "sha256:c075d167a6ec99b798c1fdf6e391a1d5a2d054caffe9593ba0f97e3df2c04f0e", - "sha256:c4e09534037933bf6eb31d804e72c52ec23219b32c1730f9152feabbd7499463", - "sha256:c5f8a5364fc37b2f172c26a038bc7ec4885f429de4a05fc10fdcb53fb5834c5c", - "sha256:cb203c0afffaf1a8f5b9659a013f8f16a1b2cad3a80a8733ceedc968c0cf4c57", - "sha256:cc41374d2f27d81d6558f8a24e5c114580ffefc197fd43eabd7058182f743322", - "sha256:cd879d4646055a573775a1cec863d00c9ff8c55860f8b17f6d8eee9140c06166", - "sha256:d013c07061751ae81861cae6ec3a4fe04e84781b11fd4b6b4201590234b25c7b", - "sha256:d8c7524779003d59948c51b4fcbf1ca4e27c26a7d75984f63488f3625c328b9b", - "sha256:d9710521f07f526de30ccdead67e6b236fe996d214e1a7fba8b36e2ba2cd8261", - "sha256:e1ffde1d6bc2a92f9c9207d1ad808550873748ac2d4d923c815b866baa343b3f", - "sha256:e7f559c36d5cdc448ee13e7e56ed7b6b5d44a40a511d584d388a0f5d940977ba", - "sha256:f2a1e18a85bd066c7c556d85277a7adf4651f259b2579113844835ba1a74aafd", - "sha256:f32b165bf6dfea0846a9c9c38b7e1d68f313956d60a15cde5d1709fddcaf3bee", - "sha256:f5a2f71d6a91238e7628f23538c26aa464d390cbdedf12ee2a7a0fb92a24482a", - "sha256:f81fe93dc1b8e5673f33443c0786c14b77e36f1025973b85e07c70353e46882b" + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==7.7.0" + "version": "==7.7.1" }, "cryptography": { "hashes": [ @@ -1545,11 +1552,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "jwt": { "hashes": [ diff --git a/dbrepo-search-service/init/app.py b/dbrepo-search-service/init/app.py index f8f671bade..48a59538e0 100644 --- a/dbrepo-search-service/init/app.py +++ b/dbrepo-search-service/init/app.py @@ -4,10 +4,9 @@ import os from logging.config import dictConfig from typing import List -import opensearchpy.exceptions from dbrepo.RestClient import RestClient from dbrepo.api.dto import Database -from opensearchpy import OpenSearch +from dbrepo.core.client.search import SearchServiceClient level = os.getenv("LOG_LEVEL", "DEBUG").upper() logging.basicConfig(level=level) @@ -34,84 +33,35 @@ dictConfig({ } }) +search_client = SearchServiceClient(host=os.getenv("OPENSEARCH_HOST", "search-db"), + port=int(os.getenv("OPENSEARCH_PORT", "9200")), + username=os.getenv("OPENSEARCH_USERNAME", "admin"), + password=os.getenv("OPENSEARCH_PASSWORD", "admin")) -class App: - """ - The client to communicate with the OpenSearch database. - """ - metadata_service_endpoint: str = None - search_host: str = None - search_port: int = None - search_username: str = None - search_password: str = None - search_instance: OpenSearch = None - system_username: str = None - system_password: str = None +rest_client = RestClient(endpoint=os.getenv("METADATA_SERVICE_ENDPOINT", "http://metadata-service:8080"), + username=os.getenv("SYSTEM_USERNAME", "admin"), + password=os.getenv("SYSTEM_PASSWORD", "admin")) - def __init__(self): - self.metadata_service_endpoint = os.getenv("METADATA_SERVICE_ENDPOINT", "http://metadata-service:8080") - self.search_host = os.getenv("OPENSEARCH_HOST", "search-db") - self.search_port = int(os.getenv("OPENSEARCH_PORT", "9200")) - self.search_username = os.getenv("OPENSEARCH_USERNAME", "admin") - self.search_password = os.getenv("OPENSEARCH_PASSWORD", "admin") - self.system_username = os.getenv("SYSTEM_USERNAME", "admin") - self.system_password = os.getenv("SYSTEM_PASSWORD", "admin") - def _instance(self) -> OpenSearch: - """ - Wrapper method to get the instance singleton. +def fetch_databases() -> List[Database]: + databases = [] + for index, database in enumerate(rest_client.get_databases()): + database = rest_client.get_database(database_id=database.id) + logging.debug(f'fetch database details with id: {database.id}') + databases.append(database) + logging.debug(f'fetched {len(databases)} database(s)') + return databases - @returns: The opensearch instance singleton, if successful. - """ - if self.search_instance is None: - self.search_instance = OpenSearch(hosts=[{"host": self.search_host, "port": self.search_port}], - http_compress=True, - http_auth=(self.search_username, self.search_password)) - logging.debug(f"create instance {self.search_host}:{self.search_port}") - return self.search_instance - def database_exists(self, database_id: int): - try: - self._instance().get(index="database", id=database_id) - return True - except opensearchpy.exceptions.NotFoundError: - return False - - def index_update(self) -> None: - if self._instance().indices.exists(index="database"): - logging.debug(f"index 'database' exists, removing...") - self._instance().indices.delete(index="database") - with open('./database.json', 'r') as f: - self._instance().indices.create(index="database", body=json.load(f)) - logging.info(f"Created index 'database'") - - def fetch_databases(self) -> List[Database]: - logging.debug(f"fetching database from endpoint: {self.metadata_service_endpoint}") - client = RestClient(endpoint=self.metadata_service_endpoint, username=self.system_username, - password=self.system_password) - databases = [] - for index, database in enumerate(client.get_databases()): - logging.debug(f"fetching database {index}/{len(databases)} details for database id: {database.id}") - databases.append(client.get_database(database_id=database.id)) - logging.debug(f"fetched {len(databases)} database(s)") - return databases - - def save_databases(self, databases: List[Database]): - index = f'database' - logging.debug(f"save {len(databases)} database(s) in index: {index}") - for doc in databases: - doc: Database = doc - try: - self._instance().delete(index=index, id=doc.id) - logging.debug(f"truncated database with id {doc.id} in index: {index}") - except opensearchpy.NotFoundError: - pass - self._instance().create(index=index, id=doc.id, body=doc.model_dump()) - logging.info(f"Saved database with id {doc.id} in index: {index}") +def save_databases(databases: List[Database]): + logging.debug(f"save {len(databases)} database(s)") + for doc in databases: + search_client.save_database(database_id=doc.id, data=doc) + logging.info(f"Saved database with id {doc.id}") if __name__ == "__main__": - app = App() - update = app.index_update() - app.save_databases(databases=app.fetch_databases()) + with open('./database.json', 'r') as f: + search_client.index_update(mapping=json.load(f)) + save_databases(databases=fetch_databases()) logging.info("Finished. Exiting.") diff --git a/dbrepo-search-service/init/clients/keycloak_client.py b/dbrepo-search-service/init/clients/keycloak_client.py deleted file mode 100644 index e8c277601b..0000000000 --- a/dbrepo-search-service/init/clients/keycloak_client.py +++ /dev/null @@ -1,56 +0,0 @@ -import logging -import os -from dataclasses import dataclass -from typing import List - -import requests -from dbrepo.api.dto import ApiError -from jwt import jwk_from_pem, JWT -from jwt.exceptions import JWTDecodeError - - -@dataclass(init=True, eq=True) -class User: - id: str - username: str - roles: List[str] - - -class KeycloakClient: - - def obtain_user_token(self, username: str, password: str) -> str: - response = requests.post( - f"{os.getenv('AUTH_SERVICE_ENDPOINT', 'http://auth-service:8080')}/realms/dbrepo/protocol/openid-connect/token", - data={ - "username": username, - "password": password, - "grant_type": "password", - "client_id": os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client"), - "client_secret": os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") - }) - body = response.json() - if "access_token" not in body: - raise AssertionError("Failed to obtain user token(s)") - return response.json()["access_token"] - - def verify_jwt(self, access_token: str) -> ApiError | User: - public_key = jwk_from_pem(str('-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKEY", - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB") + '\n-----END PUBLIC KEY-----').encode( - 'utf-8')) - payload = JWT().decode(message=access_token, key=public_key, do_time_check=True) - return User(id=payload.get('uid'), username=payload.get('client_id'), - roles=payload.get('realm_access')["roles"]) - - def userId(self, auth_header: str | None) -> (str | None, ApiError, int): - if auth_header is None: - return None, None, None - try: - user = self.verify_jwt(auth_header.split(" ")[1]) - logging.debug(f'mapped JWT to user.id {user.id}') - return user.id, None, None - except JWTDecodeError as e: - logging.error(f'Failed to decode JWT: {e}') - if str(e) == 'JWT Expired': - return None, ApiError(status='UNAUTHORIZED', message=f'Token expired', - code='search.user.unauthorized').model_dump(), 401 - return None, ApiError(status='FORBIDDEN', message=str(e), code='search.user.forbidden').model_dump(), 403 diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.3-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.7.3-py3-none-any.whl deleted file mode 100644 index c1a74fe8c7e3f602651db9b6c30a5f7dcf17d97b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32568 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 diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.3.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.7.3.tar.gz deleted file mode 100644 index 7c13793a4936d21d621548c512ca88cfbf914716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49697 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 diff --git a/dbrepo-search-service/init/lib/dbrepo-1.8.0-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.8.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..86bf040fdef558afb682d4aa0d41e2cbf4958787 GIT binary patch literal 88162 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≀rW;DlsxaORk-=Roq6-IYrZGs z&rY`d_Hf;N*A7+I<QUNzcf@8sdllI_vrJ*rg4#=&GQYX!s%_=}q4hK3ANzCX1iJ<I z4hn32_iys^@E1p9AFjAs75EapGS~Vgt{KC?zyO*bk-=S=hkLlX`f#83@I8Bx7c%p) zImqCO@q;4&v);O1Iw$ov1!?%{YU*m7Jbzv@?1I7e3(TjoiddgMpZ=ms>^0jIv8B&a z)FL&fh)i8p)T**9T2mxM>h-gy&zHVZdlp($$cWa&NQ`Ex<78l9U}s=pP{Hl0lKg`B zoYb<^9KDi?5^ql}FWnQ*nb3?n6Io%v%*Mc=$IHMVi`%FmS7-kqm#x>1&syvz!gk@W z4fmM|hYxYPxG5<Mn$@Uyc4$m$Sib#O+4h%`Tf^V#b{DVySG~H+<lUxiKM#g{pQihH zjoiNN+!x}NS=9eoM7m6zm;1SE&P8KY*|TkxTXc`F>U_OXOmI$7-{W65A3tSs$e8hK z+P~hF-xGiEe!iaU|6Hxk<kKgWlzrN_C*7J^Q6<Vh@!`g)lh=Kjm-arL$032E_VAiD z|7D%Cel6*Z)O?j)T=MSjrPf&+xw&3@C>7smJ2<a#xAMccg**+4lNP-&*W>wYC4Z=( zIZ@^K?6<v>%F0;U`eJq}tlMxiBP}fO;jCL)c?yfdt3~=4zC3fu{kJsC%0yai@|%UP zbEXttwLG>W^`VaILMO}Jy{VfgZ-~3#dCPwXb19<$)3J}bQ?GhXPP^N7`KMxCMDRWz zS+0X?kND21+^=s`nSQ-NM@jebu`hG{6||T&9BU6eQ^{`Mv+{SZ`GuOD557)~KJY+D z+uFh-@%&sr)l3czi9nyQ7svmWlq^dBqtcXnP%G;;e|PXzQMo5B!c(lawU?<~77<=L zt$xmi%+TzU>8}HHcvksUHZ-jGer3|K)BD!2)+ff_yj=bvIoUOo|JkPJ$`?1U`ptYY z;YeA&$RgE@oKEGPeSSd#6T;QbKM@f6-CKQ=|L8$(&%Wi47M89#f9aKv+<}6^zB19Y zH%D#mSVc@_n{wwXgKxdT<o$iuuIK%hH<oIDz3u!9gOnRH)dS;ID#hRB9!^(OlNb1{ zSD<mn{N%|=Ds0vw3|$XSXdCtZ%D&?gyQ}c0@Y1zmuOr!)MH@Qq`E2q!oGs_Ut|{L& zQYPO#^0MmcS<Z$9NAzd@WBwj_MfLX8IIm}~)ZG7^cyi{H?oyLo-)&l2m=4a|GyByw zi__B;oOf6=A2=`k!{};V#;zBWa&K^6R=6bfQe^(EdlnbETEe(yHy>sZ^b3A?`IOdY z8ym61ECw?i>{q<s{r^_k-_vfMlfK?QxNC`DsYB#xmx%kH3vO36{QFr`l9nmt^tw{% zXRuq$9wmVl^B;57KiZcy`}y3h$3Lq5Hm&c=T&boxN4BhXt4Q{Yc@H)};nuJY(tSG9 z{&?fRmb}GQ+U9FYIVKv2UAl0D>#*ir_q*r5Mkaq^d;USM;MeU(`VTa@g1_E0pY=n+ zHF#>}pRF(d`Kp~~ws!gY;o+4<$-x@0n>S9f+Z!&Lt60~{S{?AFMl_Z^rv32Tu%{`N zECy4K#Ba!qOD+Ashu2I;F8SV1K~=T7>3N~Mvo>2M$IV*S{4Oed-{GAuSCw}^+4FpL z@4_S8+fFU2d$X-rI-*U*NaV&9pTnKD*Wc$Q_pRg-yM8e!%SunNS2XkK(I<=&%5leT zg{%*<DEiGL6n;bPEL&Dpa=Z5CH3n-c?!Nc=x@VbHV^pK#BqinrCQOR!i(X7#aYrxQ zW6DdWdk+P3Pdt}iRbnf({P#XTuGI~ev;Af;&R<;k(Nu1M;EWnazUzDT<<z&8EuYMm z#aOyXtMZx5S??WlHuXv`oOonT@%2r%g`Y2MxbgYPqYK(aHGWsauFO@`ng061Dud~9 zayd0#H=PV*rwD)WF6nkI3v*2~a%MYV&{4JZWBvT*|H)bAzkV;-TYuZn-8f)l@w_#0 zC$HowxEMQp4@!K`l^=S&WYL7J3S8HN^*((r=lT8K%Rab@@6?pi`BSxnOQz4t+;qsr z;p-2^vp#$0Moq91(b><H$=+|w@k`vX((lLVXa9oq{O4~kwbNPO)yeNv^0A7ocxh$C z_RDow9WQ)c$Jbs|tDfQFWBz#G+A}eAV$Sg*uP=QLH)U_xAAEn|`^<a%332mh%cst> zxjpHtJ)hC(Y_tDuyJwZyw(mIVc5_Gh^y(e%FIQ$|GA`u%yzhQu+3gU1YX?37hQk_u zbzu%qW!sWvp8YNRIANuY)yu|<Pj_p7Gd}ph`q?a>&Ea1dHMx=vS1x+@UPAJK2G8#^ zrK<Dn_bklW%3&08ree~kRmCSt&u&S&Saaveu_oo4_a{o8o^j(|fI>r?y>k09-qSf% zcI=03_WYL>m>J_3Q`(>W>)L@66MHrbxkRsFGE~0Yv-N(X=eoDC^BL`U4?c>#`-tJe z?fC)Tj7%cTA`A=+91M4+R!6ZYxL9ssW?)F;W?%q`g66wHcu6COgdXGIm|IxjoRgWF z2imZQZUXNc-41zX1_pBubQ7L2!w-V+Ei5U)X~GkkjJKE785jzeGNQS`oE>gLP--!5 z6F_c-&C&~jI8eN#(MBI`LVP@Yc?Y^5K+0kI#XuY=UecI{(4Sb4sgK8uiR#;hWJDPl zw9^<E1flvt)RM*}sAi;;<m(kwqC4U3#oW2K7#J7|7#SEuLHeM0N#lDLxEDZ9NX<*m zPf0DpVnpt_#v=zA85s7kF)&C#wS%Z7jelHGjexIt!D7nnsqf2IvNA9n5J!*C&+aIu z<R%srV7Q~osRp#R1HR}+9OM8fUeb8Z7j6RhXb>F1X^LiuG}HhPwWN{N57iJ*px`j* z?u@#qs|8IWxr_`9zgQR;P~+ACi$R!?!<t+jHTmm@!=U9q$qbNI7RVtWyrl7=Kc-{g z>r{%-g4YtwUveNbpm<4RMgXc&$>1D^E6F*`tBv}3Hh8lp3j@Oz9>{)ns8I|{8kb== zE3vdB1I<lUku_0Am$ck!5@2Acih&GyA<SV9#p<S%#Nv#k{KTRZG{XX#>!JdRMADcA z7#QU385lrKZiHdSQn4CVoSImajP9(Qz?vxe9-(`xEDQ|J0_dU6T!!7GlKi5?bkHd? z$hpe^E!08Fco2?Cu0k~m?loKi|IDf;N_hL8RB<K-hVLxs0k#CEaf!*vsm16i;*(WP z)S5F(rZKQEFzn`GU{HcNjDdk+N#l<iTyBHA5-kEiiS_LKmA~1z85kU#7#L7fm_;Kl z^9mC4QghJE0<C)kIR{oSg1Q$VJ_s*qtm;8ED?c|UGYMCiZTF~+;^jUX@5{o#ATEgR ztnFBhO3u$KE=kNQK@T#JSu1?{X7@5NFtl)@o8>SOo3m12EAr612r{eJvFM8xI|GA@ zC3<@0oPy1)+|<P4(jxRk1~SQI9$Tz%J_AGKZ&n5cP$)t1lE&KE*i6dL#pg%#BbA_r zF)V33$Hj=}fF<Ol4~jzcLoX2Kln7!o2X+JovN<5%q3`HNm~&qQn>nDBhG@YJat=rv zEJcA<WP<o0yreNr8=EnR!W38H0-1`wJ`-dj2rp?|N61uo+JM`H#ntF*EJ0?2@RCL^ z9RjWfg+nsd6_>~%4Dy5=+QLYX1t7en@fR_cU|S}MZUx9VSm>jcgUfZX`2%fnBeHRz zxf1lnjUeMecuC_6xN!uRI-(njJ^=$V5QLXB&a{QO5yMc}bPT#-=mS6?gFtvmW11^Y z!@$Eq=q8~L+JH;}VNmM|r%5P7IOry#kKKSw1K}-=?ru0ugpA|_c(byBlxi?&FdXM* MU}*JWWME(b0It$gO#lD@ literal 0 HcmV?d00001 diff --git a/dbrepo-search-service/init/lib/dbrepo-1.8.0.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b0c21d94d641cdddaede16449367638abc78d5e8 GIT binary patch literal 97755 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±N%zn*Czgikg|`$Cvti@^D&j$nhspf5Y#( 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 A+W-In literal 0 HcmV?d00001 diff --git a/dbrepo-search-service/init/tests/test_app.py b/dbrepo-search-service/init/tests/test_app.py deleted file mode 100644 index 118ccf99c1..0000000000 --- a/dbrepo-search-service/init/tests/test_app.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -from app import App -from clients.opensearch_client import OpenSearchClient - - -class AppTest(unittest.TestCase): - - def test_index_update_succeeds(self): - # test - app = App() - app.index_update() - - def test_index_update_not_exists_succeeds(self): - # mock - client = OpenSearchClient() - client._instance().indices.delete(index="database") - - # test - app = App() - app.index_update() diff --git a/dbrepo-search-service/init/tests/test_unit_app.py b/dbrepo-search-service/init/tests/test_unit_app.py new file mode 100644 index 0000000000..1f8ee06980 --- /dev/null +++ b/dbrepo-search-service/init/tests/test_unit_app.py @@ -0,0 +1,50 @@ +import unittest + +import requests_mock +from dbrepo.api.dto import UserBrief, DatabaseBrief, Database, ContainerBrief, ImageBrief + +from app import fetch_databases + +exp = DatabaseBrief( + id="6bd39359-b154-456d-b9c2-caa516a45732", + name='test', + owner_id='8638c043-5145-4be8-a3e4-4b79991b0a16', + contact=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + internal_name='test_abcd', + is_public=True, + is_schema_public=True +) + + +class AppIntegrationTest(unittest.TestCase): + + def test_fetch_databases_succeeds(self): + db = Database( + id="6bd39359-b154-456d-b9c2-caa516a45732", + name='test', + owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', 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, + is_dashboard_enabled=True, + 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) + ) + ) + with requests_mock.Mocker() as mock: + # mock + mock.get('/api/database', json=[exp.model_dump()]) + mock.get(f'/api/database/{exp.id}', json=db.model_dump()) + # test + response = fetch_databases() + self.assertEqual(1, len(response)) + self.assertEqual(db, response[0]) diff --git a/dbrepo-search-service/lib/dbrepo-1.7.3-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.7.3-py3-none-any.whl deleted file mode 100644 index c1a74fe8c7e3f602651db9b6c30a5f7dcf17d97b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32568 zcmWIWW@Zs#U|`^2XzU7$Vo`9h+``PjkjBlx01{0}DoQQL*LTb<EO5@rOwB9NE2x|r zmfL;XLg3%KctaL184uR*9dbH5CcImA=TPb7wC&-1d_772GIvi+(mt8_{r-HF+aFJB zKD-vc=uD5?S>t>mZS9pj9<m$LLN})0TKn~M<e&a&i=vAoMSMg8O9D2v)U4kysU@uE z!Fe9-!%Hq)n6)me*d;N-ZEnTdDItMZ-l<owiY(JU+9>+ban+<*DgV@#SsAZ6(%NRe zaY5O~Z_~^3&VFp!Be<vhzxS0{V%PHav8?yDy7Rl;e|9QMqrY_P79Sn`MZS93n>!Y1 zJPyf@n0kM8^tm;g&Ffz0n0?;w?=JIVf#J4$PHLw&iOrj-@qpdfeM8K{caP7tF^A3H zpOd(CFT3*Yh$mM9n6%F=Ty*M_!3vX<kOOj#iy2RCZQ1{Kp}HI6(N0ZGuku%&T5jKE zz6wncIWl|k3GI_>F3IQi$L5>A{Pi$z_s;qXr4Q5B*zT}d7^LI=J|-<VIb^Qn>;DHj zpItC+eQ;9clbd;+^qZ+QZd2u!nwk4{Sncz3NqBs^p@^xxVu9)QFk?OAQ**1_m;&@% zgf-N;oc{j$x4rx{LtE+XD^uF<WQB&`$$nMwCVFk)&PlTyN*^&^C<ssWe$pQDbBdq# zymzm(az%n?t9d+d<dS(cOJU~{bvq8{yEFcz)cdC_dQmH@u}AGV^Ab(rGfOhpOq6HR z6)mW&^ZWegQ=4Z0>1m2#pVdMY{|KCKi0t^vbg%A1_w3DklYQA_)-JuWB$q#ELFaS5 z-7C-L{rdgv<4M0ojbD{I9=jhDo%1%${6OI~TR!WUd*7e`efRS9tNvsCtOmSJvpDCk z)Ia<n?sH~OZJYDD|MnFQR(<}{cV+k0)W*D*3!8u4%wg_Nl~b{4>)R^6{`ir*dG}_G zxjz@J|GDa3@v?s3lg*o^x6FP2(s<vGq{v@}^PcD!mx=v9(-$IQp?k(bv()$9zT9G_ ztp2BY99*o{3oV$xZQe0)dtAfUMS+1gZrfFt8ChRuP0L%bMfq0kTNSCw_iYy$I(&NP z8uw1!zjE2Dd25U<t8bk-$emnr>W<h4i|gBbV&@#V=l=N1)~>=z%~K|A_e4G>e(N;q z+sU2QdTOtl!^7`Vcdsm1%o}%3<k{wZC2Zx1kK!Gke3QBQHd1`|BHv}si7(%;Ou6;= zA^VA``8Om_E_JIi%}VREdiSkxVnq@&<ISQ|M{@N$+)q}1ja>iR?PuJVoiASRJbm=| zwkyBq9H~9TCY|fZ^`z|j0@bL*Kk}QOeVti$_ukdwOS*1r=kr`EGdul9wU9q)()HA( z$=CH9nN%JJEw=p~kDAMQ-{^M8Gcz!lbD-pM-@=j-crLFE&CR}T0LtZsEM77NM|U}D zHu7vTOZ|I6#oOpuLW0QeM;TL9!zW$-df$K2+arZ{pLwU;y<2>KZ`ae-5Vj?J5v7;b zAAcOL>stKG==6*ev(7iYQ$0DqSCKPagC~IZoiRt5*Ru(EqGFRSGztEho{%_0L@Mic zX6CnREvi>y&rg}8#gSFBY3VH0?LluM#NI7AwQ?qpzSAn<!$mTgJ2+Ukwx3>o{@t06 z4SRO&D7$Z&<!ij!yyw7aHQslJ|I`VxUif_3P4TR{S>7UFEpKD4CWVI~*%ey^@BaF6 z>|Tk1#E<`H<)V#NOwo<@NSQbNkh_{uMPeGiS=f%>+cv#yI4(b%*JnC^LdxXsDN<eu zr*@uQv8hlZL`q02p?kr_WmB^`>-St{Ufl5Lz!Z_4pQ{#hUDS1#Wt`MgQ7V$DI8(Ih z`n9(?J3G=p?|%9yai8Lc=xK5>asist7O79aaY-Un?bxUMi7V#FIluVo!?fPyTiS-u zPn@B9rr+vWEn@m{mo^jkeYPpWI}Xe0?z}2hFf-uY5#~$GPlK*B7KQH(2sby6Uu5RC zGH~a$7YruXbth~KP4xb$6nd*PI=+1EtUinGyUT>t45l;P-lQcFKBrUtb*lO#*~P;B z(++qC-EovLKIkLUF7<QW^0n13c=}h$?aROL^v2?w$9K4|?f=iAxBu7SA1mJfm@F2( zTGMpp?B0}&Lkm|s=41=h$FDIjTNiz6ah!~Og!}^?@zr8|m)|`wQLJP6RBRi4c6q-s z_mvgp0ke2&JW_YX{f}DnPRDDpomJ>gjqP(@)`q48l$qXKD`fw0wSU%=>Bm)4J70R{ zT%Pf6`<jA)YVPf|8YyoYnBElK3!eBe^W5s+x5Ojjr*<5=_U-)S-J5?qB|K_dAou^; zmpO$c%vYF{VpH9hUHTNgVY=1rQm;c>_(k4qvN~U+D=~lTqD4N*_nU>^v3;LX=o4$k z74mK+W9xa<U7ZWl+5XMb^kHAlb$$K4BlcBGs@M;$`*FfbFD_~Kyu+IV7JX*8Cvm-! zZ@040-pp?t>+JU$J`WPxXcqGILzdL)&~+#Fe^b%@?9{$aZt-`4)I`Sr%!my2$R#gI zRQlDL9CZc;-Fb}2)n-s?F(N~~waqTRePZJMui65kKRseIPVGMV^i@dvl9cG`!lT*w zI=OPsccgSkbe(8o5NBALTJrC``Q6WKYzhpM7*vBp%{&v9Rm<7lwY9x#d$2}OeWviS z?b{toszo-;FVxz%boG~vSx1W1J7oX8c&erRa`t!kMIKIdag$6QKNX96QoT~+_pQ@= z-V5dX{Wv}Ky=$a_;QIAp+(qxIyL(jJ*R<46p5SWpP3+)}^D3w6_4lak_c@`&{m5g{ zFNaI4e?8-l+U@k1WFcw!{?VI9(;Lis|NlEa(fR+r?#Z(ceD^#uzwUkOWs8}@@mCg| zHC^?$(sR<)R55j?cSrTN9GoZ~x9(EU8QuraPv^KT=$13-+rLQSd7N8xaouy)h2_GN z1atNJr1T3tC+$vfIupPCk%p2m=W+wK;{1&YoiF~Mzi{fc&OX2C=9(wn`uvaAaV7Kf z8y~28J2_K;mEq%y4*#D&j(In8x|;IlwFl>{u&yxs64X`U=NI(+rokcuzj^hab!+%f z%5vUpzJKt&rDyQ_Y15>8WNMys?a04Z`@OCudD4IH%`Fwh(<fcCIQyq!=3E(BSzjl8 z-$bF!;fW6JA9z;F$;&@}ezhm#y-e7QZP#WV`TW!9(8IpGxxW==Tb3}*xvp=2A+X3U zCMM4Ex&0nV>*t9cp2BX;ezC87_MF(M$S13Qocr>Po!mC<F6E9w?!^uV)IOi{W|G)m z@?^rtw-VixPsAT#)NR_qaM0AXp!Vatul(=t@7XP7d0HeR*{_JTZqJ?{AKv}>&CR7X zyJznH<K8(gHSUvCK5!oA$ekacb#Btr7NI%!Qf`{>ox7>^vGSVwHqjL2^EVEB44lw^ z{9JX6b(}?6+~k$pc`{Evj+~}@&d)!8Z_l0T)z3AR4<*a4dlAjIu42u>tJ%6QQtlq_ zoWELCZu%9klPNO;eCn6J=5(L8sabQb&aScq5ti$PhaRYXoFpnMZ*?@#=Xi_C!IIWi zn~hS<IZuxSr;F+fKY#W1>C2~2qdjK{Pf9r`;?c3>+=NZjHWu?+OxK(c;&tfdXOkVh z9r;siF1Ee<9J)zm{&BXWt27r(ez{|cxGPKi3d1vd0}fBAR&;x$*5~|DCjP?HH!<;t zyY}sqb8^;wt$V+ZasD%dc@+<J{5Cf(owT-hTGBSL=&q-?_?t@~+5EQ^v$qafdgx`u zI=$(q78ox7@=^C>Tl1ly#WL<9_J#{js75flt~uTqwb4>zQF&-UoyGn=e_sFQU#}?= z7~{yf?5U`}e%#+550eTWv1kgdwG`XLoAY8-lmg?<lDxzWb|J2X-AlRDek*Zv9D6%? z_S3f)R+!5!xbfl8gZL6jm6E%GVm)&tc21hX_Wj_DBl=kxciBJo+NE%RvGR3Z!I1mI z$l{{LFFVJB$24v&e3LI`EVTH;qzU!TY7^&K%C~>`{A99%{jVg^WAol`iZ_1rb4v9* z%Q}OTr#z>0P2$|iR;GCJi}kVWWsFbPxs@)7Jy>_l>8-`(<*|*$E3BUI_^w(K%vbPX zs%Pe(vz?aNo#IQ5EQ{n>e*Au5Ym*=6)83LJ4mI7==4w7`7yVE<LEwLcpoXmPt>rHj z%yap_{G9H{8SBHI<Ro`Pe8%ogi!5S!=4{lt@nq`dI=Q|XZ`i*r<yx9x#xJ$@`G(?I zEBfPvE;9dL#;mi>i1EJbD#>{vhx(Et=W*@)W1y%x-8@93;OO>`bF%h7+`4~`zR4bs zj#&;5A4mr*m9@?PaXfj!Sqsj8ty9W)vJ0#JOse3#>L<?=5#OiHp4^nBG1pLj>TZh< z>dVb}_`V#JD2--!F`ix0#NW5m%{}eyE6p=or9`vZKMEcF&+{RE%8r6|<2yZbGUj@F zZ1Yh%n*3wBVswGtZ-=xOm+F;|JUvw3w0)P<$J?a^f8Wo~l-W6_LFIVK&*cxc=>2}c zbMfeZ(`B{x-Fqt=nmhgoiZuN{-McNI_rd#imL)bXGJ+~?Ch4EQ!LY<9F{HRDcwX;X zhSet&w`VYzrq11|X=$cD^L%6AGY$Snv1_i>-r5u|EB@?4$h8$O_O)@Xlv=U9Wbx0B z?!Vro3Qc&a{yXC@|GQu(muXS#Tn8H3x>av@=&B3vvYf5wyqM|4q%Aul?TYVR&@!AL zmbWBeTX3%P?cl(eEuG~~zUQ|Ga!d~1Wop}+#<OK(!i|9E3m$8#+Ni%sw$eL3X&$eb z#;Qwm7fsi_{F*b@V1?EFeHDr4UirRRuTc{z*HM)*H|XpOgEPJVPR=OPUm%@cv^V17 zGFNAY)xKI@j}AQulw0t`;BMmY9I105#~0oVsku@0*)`x*!ds`gd>Py4KKyMz_r(UI zPu^)70UoI#@!A2BwPD?-7OeXmEOOudg5r#7t3bIM!WULJNY1I<>ZQcOQ0>sNMY6x0 z<LQ%}evU+`D%C?FSsy=qwMxjc2~yG7#btDaE9X{zv-O?c=9Q<{PZ63saSlWJETQZJ zpGsU;a-27bP_j`}lC@XM>Ef8O;$*YG{Eq|mH?OxclpNR^=J?IBYW;!Vx5f8w%$<5B zb7S#yV;S#L?;ce@;?GL@y_R>jWoGD&Wgm?$6`BgE*Xllb$`l!RGRiGk#$2R#&V}y0 z>G#(Du;iU&qJ3jxhUV$u?BczeSB;rtbksO@?dRj!Jo$;{3Fo&xPu<^mM)mL1XjU%^ z-5?Rgr7|aG>diB!=ah))JInK&%GvOzP>xT2iFRo3f}K<HLN&HLHrO%u;4JHJd!MNP zIKqDZ<uN7i7YUu_uN)a0r7Am}ZHg{jQLpGb;;F>q-L+v$rgOp?|C$v!WpRsTx2+1^ zWzG@)`jyn?wc*#}E_`I4eavJ*%wicKb$;1nzxmhS+oQK~??ey7{(hD7V$q+g^_Oyg zpP$0iyCX3zGcW4Cf90mm6)DYoy>D)b$l8>-MDkY5hT3)aUweI4NM<`=*tSC=_D}pq zgYcS*H)d$>zv__kQ@H!EXuO+M=I&eN=N`uV`M+ct&%ZKZ$)1{GX2(B=)TGXCO*~=h zrWLbE^r*k?9N*UcZNb*NUpVj^SarX+y^5J_iL3_8eXGNt!`JK8?bubZH*P<B;S<)t zi}OBu?OCz;Zb*QZ`P5Yr|E;}mPOH7Tiu?BIJ3TqM{VUU!p6^|j!+Jg7X@2r)&EpHQ z?rW}o^(*n@zRkRu(>hXG%fyRzissI@dvSQjc4-gG)zTd6m;ISj7H~G=_ug1OpZeGC z5nn&m{4uSMYwz`znCk61?bZCw?qzSZ6U8fbSV~7HKP>Y4*2JXQmpVn$il;?8qE0W~ zai`Rj<ELIOnZA6FyF*2R#CFZ6g`1itYe%-re_H5&@}vIw!Z-c?a@K-{x(<I#rZ8;m zSXIK{s=3sPVY9J>#DNqAxsb?Jt~1paXm_leW0#@4ar>;M8Nb$@J)4xX%h+<ZMD*;r zqBH8QeNj<VxL0&KYF3|am0fJ`%dbh5!fe8a?{Byh=X`qkWXYM;+p<h8j%nvCK4{Xk zB1e9q+^rp*n`SR^W;8cmEqpzuaP#MIwq%YjwT#?^1#e;}u$eoakWFS?WcZ2wS<dW> zj1%-{RKMjdl;|lq%FuG;mG>I!BeQ%@^lsg&x@Lk+$u={s@MW>T&7NK8zwjeEzUs*% zxvVW5$pSB|mV|aacoWE*y}&Oe^I_KnA^n+WPPGT}FO6Wf+1EI+!JNUOBjN}1JR_H_ z1#cHF+tG1ZH}ZsJy6_$T#SSrPTdrC5ul|4G#(M4jTQ^TV96v99$4~ZB-N*O8tS~Y$ z?J-`s{N%m9p2w_vWHq!|=X6=#6q)XI=YQ(qxygxFPb~i#E@jQ!mtf&=HTzoq6aLhQ z&2QFh$b0R<buq?q*7H8K?W=A(XwQA&v*qCe*1$^VR~hqId8{wk?k{XxZx=IXz3r0+ zTp9QFtjSy;;HYeJerLJ&6s27rP1d)TM?Z>}erR$`TDfUiQ=n7J{h5cEl4r0VG1@V0 z$Jh3slS*~&%b(DVo&O+Z?dl1FviCEbR+KrYdGoCQ+?A#CrIN>cjzKtw*7u;L5k4(N zI@v4i?&%n-_pMkot*U&1NxIVuu^Qe+t-KFsPP-d=o!<CkU!mV?U*jG|<s<%;vey{m zmCmMl?%6YUW5K@jbv8dc!@Q>nzCIE8?5@@Mzvn|&?L4;dLZ)T-gtMKI0`nrdwYyGc zzW;D%+2QESQ)^atZD@9T8W+oVn&*OcyQ=axt_>4j6irps_{wIn<HDT;8Lc^HDz3NP z&wp$#5v<a_CE=%WMqYhUi}hEvGS~TBZ&cqcv16X`sLw@D!u$5^2fyEJ&gb}QtdOR? zBxm`;Ye%o|y?WwkjB?8%IjKtSNloIHN_|T$TBd!gaJ#lRNw0F(x|z&VcYl~K<i765 zr8xfWA7!t9%CVM6N$GidlVkca?*F+BJ;hSf>%Dfq{B(Y9zV^1lw3|io3+I}b?cR7| z?)0+Fn=eertInR79Qk#lxMYMiZ{>FN<E5b~@8ope{y#M<yof8<;9{Rw&IZ$-^@kRR zZ=d|^P3J7Bm6A!`=Q3Z-dG&<r{i!v(#J62uf5|~By?XAYB7+RG;$K_mi_O!LdUu%r z$L|~b%U18#SeLpvA@97<&0Fr<*}YZ1n{G9@w$8R}t?!F-`P)TmnROS<RNdgPzchNQ zeAuBX-6u<LN$~XF>hV?9Jz3Ja?o!30>QqS`E$h|;$Hk<0lU_K@T*+15b;36Lgrl}a z2J7zYTobNrTQ2bA$=~Xj&5iGiy6ijNNBLTGyqEd3TzTL23s2OQ&d-dCKi<B@ZOukS zD+5mTXKK5+SC~xw{XW*?n~<dLp+x>oRo$DU)He!y#`dn{x76+UA<|i$&9r-MclAz% zyepCs^O?0@^!~oQ#s5RN^ZA5alak(fPE}7|CHHJGPjz1K-tppv!1wKw6r;Ax|JIoF zde;S2mTPTQEX6U~cW^4Q>zJ}+@Hv?BJ8TiTm##Irsx$Yp`b!l~v7;fH2VMs5)U4VT z@7O$B%W$rw@|$-b?ksM985DmrvnSQWvXtT5d7ZES(!cJBa8?(RssDPw?!eP`R#LGm z{S1%)3M_PK&Jfb8ed^78ZHZ0Wt$#lyy%+9Z_)N+s>FCvW`iH-X^VX*FSs5r-CeNFd zb<px@xlsG*$|-#ndiA&F^IT@E7Bx5Gc^YlonQ`3DRYS0(eNox+MBUnAle{Nc_uZ3h zVsG!*b?f_G%Xb@=KFw0v9JTS8Z-CDx10{=vZ{G1aa&Ng4psXGKJFePAQX^_+;dM4s z)xSHv8ZIa*-YgaP`DFUT&Z`?bGs-s4e^95_u`oMdwQq~HzbbE{`aVw?`Ni2HBCPRC zVvm^?e0jZH*=qa!Ob_RUuD^;U|7{HPVRpZ`c)OU($z<(ITEErOW(Um4^L^Csv%i7u z->qBfu6+}F?(f{}xBs^J(lzrlejjVwUN?D0M#@&b=96JRt)ARUY`MxAe*K~+(=8SM z2@Kcb%X+guw_UIn5kEL{o!91tx#3*fm~B)at|<?8ZpxZ<$HvY`?8vP>=l?wa;@I=) z-m?D=Rd1}myO&p`$i=>1BftA{P?mv|m1W9W&8;W0Pw7il_A-3$zHJlsIplA}y5_*n zz)#QImX`HQ)m?n{eE8?xHcyu9zWH{uTKS&a<`c^fEbZnfFSCp2E3@ZgJbmlP{QOz& z2UzwqXNFma8comqI_b)~$tjtxeYY-I)EJ7T9Wiuy@LNV>&mte4$ig;_jbi!#BBe{_ zPpGVM|1(iCb^Y}Y@pEUq)925;Ggt6vP}kDQmfF!Gr(X*t)P@R`A6Lraj%<`)@AJwo zZCl3<>zi9zj~sLLsQnb5xo5{RAH(j+pH74%CmR-BdJymOB<Sa}qufu<%l|)-5F+7v zwQug@!!`n2GCj*qxvMSXX0~)p-krIw;AWn3c+XdsTFq&nrJwCzxb<Keo4@rRm52=6 z+b8SZtCl4!wS2neC%XdgcgBDB<4^nE>(IIOz)kGQvO^A0iAOiR^O1@$D9=1(w$bd? zdXw9N5eDmSu6n>VQ7dbAZxd^Fy<1s<O<cX%ck!sKvlnB!4B0ZLZ)8<8pQrptefC|e z=hFM0&j|`V<+f+jR70tk3C_tT?HAuS>0A|mxOAgc;*QmQdko$!KQ}2P&`DZ)NviV9 z?kvV78`~cKy(d#`%N17e>i~O2{#A8_Q|r#}P4L-e{VnK*S(1ru{Klx+S53SZs<<9_ zoZz$5Da!wC-m?h7tM*p9x-#Fj7ZjbZ(Z0j{|IOt3YrWsn1$8zst*NZNruV@2->>tM zD&ckQcjmK4mLB`h{ljcWXmPsHf^91&xlao9V$z+!BRpmPMxE#DQ&k)TZ6c&^#-*IF z_LsQaSH;KL944~r!@@=@o!;GDTLiwY{mOTJ$rZlCmyZ8m-FIx)57lOt9S@&sojq}f z#fbgjQByU+^dp*+%4S~JB-lB9clYV4H<c~dG9-)ob}UPXVGbAaUYz2*YfmHV<4v56 zD|EiOT$9mUF~co#pM>|_tTRS6!5ikt&o>EctU9CAyK17?`&Qe6n;JPE&8Gj$FS^;L zcg3iobEW9rWBR4b>P0`8cE<g>cFUUETG##L&uoE*EnFM#XKgU&%SzI{#s7ZQB(;O7 z(zkalN=<)NbT>ooUBuNhF44yiuG$uNd+E$?8&?H>T`N%fRpa6Ik_(G>mAL2SuBqJ9 z7eCi4k2$^kU0keJ9&@T+(dY6VORS69@2OYDURtvDL^gBT{dpB991N~H?p@r+8gu68 z+z)Y2YCok|x%u>l)E#Kt#&2`)hWy2O+DCp>wnpD8kxcub&@m$>!LK?@`fN8>{C*{c zittBo!z-6G-mUI3le@N4_oeET1(ugH7R<<TO+K;P;q6OK{%JurtS?1{9@qR?viS<@ zy}ILREL%!rIvsZYa-O`?$Rl}1_X&AEc7~(_74CYup8He|$Qo>0G&QHJ!TwP|>^H-r zv?HHAC+*^IF5VR-cJsj*$qT;{4Gu<Hvl<_L;C)+Wy3t8xqrD$ZI-g(XoOz^kK40;) z39`GKytZ9fDZQj^tFrhBnPX=sZ(b8TsmP=8-~pyoE6421ZpHpSYk94*S1#0FdsS*# zv+j?athcx4-gaBNp~)*(O*}YY<+&+R;hPiqnr-7B#0dPb6pR1T9VflgY37NXV1Myj zg*7GXBL2S$*mpOJ>&il<{nFwm<d(Udo))pl=VL~T`YPX2`Rt9`yZjaJJ=(a!Zj0!o zE3cEMhH5zcoV)3M3fKO&<LCeV`*ZWpPvifuZpxpZS6lz>&8PZ)f4*PS90KjXEGcgF zcE6o@!Bczc>e?eG<+QD;n12@rTosNnzf|^P1>5ADvo}vm^YlNdn<M!4$Gp|*Ym%8H zz6r3{hjK>n*l>S$`K)H|aN*PW1O5@OY}T*T&exp&blXZ^3+JB0^}qkA9^KAUtHPV1 z^h{3m-$}>V0<&Q88!7L7!f)Krboo^iqbsiXInl9x#xy_i-8L18&NtgPY)*LRaBphD z-AyO7Pc)kPW@xaPPbr+n_T@!Lf$w#WSnXLYr|%zVSk%+CeUrEF0;>wa4K;sO&9m^@ z_ovr*X|4aof63zEQBn0jCwq%svk8(r<a+SGOW4o5OEq>Ex0P?6<Hs3e|FLN5#4l&7 z&&qn2rOr8eee##Q9UnH`ES(c`*-CG<dP(KE9R{Db{GKbm?3UujgF!b7N?tj(Pj>$< z^}(}T>Tu&L@wZnJj<hrEVGG=JIoI*-Uia+pW^ScPdTZ_S9)B^vKE*&v*Vk;<UpXnU z;w9z*c5Ab@JMp^4Oi0q)d-&G_IWB3tUmVM-gYRCk+`nsAMfulff2~{P#YGN#vrkyr za{lGBNh%xu1PLv5bX)kZ>t{^%+gbXT&&)i?XqZ)fK&hgs=A}o|y-y6MJ_aeT4SuFt zlznmTu{9e_&&gc9WSOz2Kj!h>n5VX>!dJSjO`?AuHb_%bp8oLhu7)L-gbO&>tIj<- zBHP3Ez(6+rh^!31&&jQFh41uvly)6dJ2~g}vbzWE7df8h*f>|~MNjb8g$u+D%NH)V zy|FHqtE!OaR|v<R6WrmNmsvMmJ+$NWf`aH-&WoPL#MK^K=hEzcJyNEt+5GVj9))?z zZ3?+7RT@q_?=4|kFtvqqoyE}z?IZL13Qk^rU$Ua%tdpwRzMF57&cAxk$MtF2*V{at z$+6;@`{$IjU7F~1?6&G%b%#^OW|*1m<Tr@4t@gSdR>(a=%1h*5p+}>;uu1;OS8A6M z3#5;7MjTuAqbd8l>A7<?hkhvU-#4u{VEOS3)gW1QS-nG3=Qui8Jr60^>HF|?;j1n0 z_g^_VY2&N59kGoH^BMWGw79lU4qVqYrF0A5)Uwv^2KCHtA=k<sB$>C~6S*GP9@n<% zfcV*!F*kFAv!3{M?AmcR_PMm|F$qq)#bGYljdwy!ZUtyZwnUo#n8z8kPpx3fO}~FP z1l~3?EZY52>t?gkQ~#8$$(frxnk;2(E?hGa6n{Na=jjuBM*c_a!cubSPSUMQY9H+X z`SVTN|8<EA9A@^nlxJ}-(ci|o_$vSPlo{SLo~fqKn(p6~xk=YvVaa1*pHq`$r`^*i z(agT}Q#1aP&QeRQc?XYh8*=p?Fr8EV;#b(Au1H4Hp#C{m^E3tW_c~_ZcmBBQsryQ& znB!f`I#Q3Hd=a(z_Z_KsjZdFX4}Cso{|yGs=Z0}AH(h^3FKu19C-t_mN$$n$)q8gC zJYe}V>#@MDqA9hfLgrZ%2=8Abc-=AUN5;mKtV8bE@0YA#O`F;-CcXO`UzBA@jtHad zn|_m=ka<37PKQ)J?zNett#IR_phVgK0={jNiw)ddY^&<7o@wsri_iJ1^<974m)IZq z{QR>j{PxN5&C;2%+dJjPbH~X`Iq%AuL`q#)UU5}_agIt{c6Ugf^;2cRmDOsG`7WKl z=~I>azw6YpPuaOyGv;t4zfRq8zQ}uj`G)A7sR!?T?41_B`p%{v$NQOKQ!Xr8F)c7G zyyR-H$+FwaObw59l*yl6`!gw;^Uc$PN29V5*<QZp{cM}!dvj`pE~nhR!y94?I`4c* zxhU7~{j;BI-_wu#9~9cl{CWFR`+<$=T=nRbQrCUgnrrlx-YM;0E&B4^<^>`j%cgNG z4Z5zeZFO|$;*S0ECnP9Oy)7lWctZ2miJvyuOWt1Px<BXB<!}bR$jen{W?c(-VV9+O zyLQq>rhDg7a-Me{<I4E%d1%{tyKSP3w>^tCmVOHT#KOPS{p!{Y&m)-D{a>@=DevhL zjS%lAs`>0cmdLL2YTj?9)W~~lU!393S>{tGF0}n4@vPe1=J&MhUXO~L1y<f+DMxQV z<1^CUP*=h4|2??>Z-CU|o-kttCjLu50(HNs<cU0<qqy$mbcWB*PVLLF7n!0^+#0dH z=uNh@&byB<{}-7&ZsCnMyLp3et^MxLzweyRWn8@KGP~b~UcEDGW-E29b=elz?yz6) z&-Tx&wYF<JM8#bRN!Wk)-pwoR9IKt~zTn8u-nSxEH){Ql_xC=Q)ZSKWQ{Y~-$?fW` z&M67EnfovEg)%?edhC$pj}1;7bB?o|cMP>y!Nne$xO<h;;@w;K8~G-#ta<SJg2<^0 z<<IBua-ZcC+5OEiIO4upT$1)IC&_KL1@m$jYhKy2ys+Q2sri8&$2+Bm?;;B9?^TQa z7FwSAVt4WEyUK-8*A~?ZEPs9bn0JoroN0--8!gt(o;qXplb>I|q&iKxU-vitM}_aQ zDZdYjY~53m;a$!byFgtxZgtJi=i3h*KWtMuXJU)0;ar``EI+ik=FD{0PWAKHW3o8e z|ES9R*xdp0%^cTus#-jCFq+#b?s!Fc|Mzx3!)wd)jUGI%c-plmtu;?!)6J7NekL<$ zb~kZ;cS{mj@Ro7%g+1Q_6E~QJsQ=*6a!-l(d%SI($FDz+K9}iv{`%9)8gy=U)XycC zX6~8KI(eqh-W{3TMqhp`e4Kgo<NYQjl?C_Le?Giu!Msh1t<`U?hn=1v>7XUK@TkTu zCL#4zi)U6OzE!?DH{<lV_Zrh#{_yZUc9)T{cW%Gta{ltuCRR!3H8*VUO#OUhisjC( zomR`Nb9lCzzR$WpRpJrz^GyqPpG!J;>#B+Oii30XN`5Bk#EKsKk>qo*=-m1P^6RD> z{kig5<6h1mbBmzK(*tBTd#~s_Kj-lu)sW-ypUT76UKLuhx7Tz-tkO?|eS2G7=4~ig zvFb42&l<;8k57#cKOD9G{P9Qr`TIYP&oAMf!|T`Vz0plccjxIH-2b;~A9pOvI<)KB zSHXD)ZrwdOw{K(T=?CWjGY?M}77OKAtF+|e+qXZnQ;$eISMd#1zSc3PFVFj|Y1Y{` z&T#22?Su8V=5lkD*uL{}u-cdw(tiB2(e2%r|1wwlUD<bN*K!T>KOY~>j{3L7FLTv} zZ|jWiuAR4!af#5^+58MVH!ok?FZtKRq}$F<b^E?YCBGD|JKH5JocoA#MLqA1{|r;_ zvj6yhdcULWcgBDDNs?!un*Wtr$NltLv!1j1rwr>)2hJ|O^RaZH)vj3YUpD*xISHC* z?pM2Ue#+OY59^`@AOBG9J0!||*TXWNd0|*l{UI@zKjC>zRvib@ls>%fxVihPPos!G ze^dM8w;`W0EUX1>W$x>x^j}=y^`=*4;sm3zg_m3=EvQ{&bEwyJV*I=f;?W0%ECY>= zYR>=M^){rTS>)j?t@jyDVpBXmXteL^pMEo`Qb3f~*2b#$<>9T{9P8dKi;;P6_u@iB z)Pd_7kA9Ww_DpAUJGx)ovqt>KnX?H8`My6%a%{TS>!O)?Hm}TxZPUMPhHqH*8%_G9 zyL4K=$M5;8Sb1B6gRkT$=1E1dPP{Gi@m^=&;kX4~Et8h}$Ue$BSDQcaB3s6kIwLWe ze^nb7o$V?+_rg-K{P;`W7VD5JzA1A*guXMm!XN!qFtNAf=R{|52QT&R*fTr*w(f7) zEwd!c>ieYmM_e<Mn%5eCdBC-G!ZsC0_QuJ!c6>sy^^<qc4*qrj!nHO<i#Z2X#gv%Y zcfaW^wtJQ#ck!OzUe1f_--bB+3!IT?_0^z4WQk#!QuyadMI31}*_l=z+41t&vyZp- zl|3n+y5Hl0w(xY_@6KnPt`@kp)%@J~r}+8Dtl4>squf>$&b*KtBjtW8)?`*&!S-|d zYId)U(p<}={El6GAGOk8<5x+SV|VYpd}nd0DbrzkU8Ynv&#pRU?zlvoQn3`phqssa zpLy-8&7^N1TKPbCn#B&4haMX&3xn7`h*tm2JfgMf@{`x1ABDc;tvvK(a>*o?7lnar zf46FV@{CE1V=VNV&a9dHs{BXTp~8%8&bf?%e{_FGvirYq-R}LRpz`#7&jrgasms59 z>G1ThkH2#q^IE$@`?g<NUu521FXw*qOhqiCsp0~sUs4BWGXH4Y8~*r*XMamT|LV;$ zft@<uR&|ejH>d4d?qOv0FmDc5l&c=ok84Ym;w{f~%I`B@v1YCG3jKOBhK18^O<m!z zGo<R$7SUr$Q+gBqWh-tmEZFH$7<6Uwt8JN_Pl_F$TJ3d`m8sv-x-`s?;qm?`=E>aB zjh#pDvW48dw}R^i`=`%F9tu(EZsxf&;valEK7G1)_^&+mj)0}B9CA-Txh?QE{$9+V zt&*3{RDE`E-V**?|9+gw;pl{}%BJP~(Y^~>7d~@*{5b5uTA%5a!7Y{=TQhg2RIlQ) ze`>2WeVI<LL41y^d*S-s=H>U_zi@rUBs1q$PSC=V)vLK)mzx=EDxAAVD@;u1NJ*6W zWs%6~wLMc@N}q0*nyAt@W!1VLK_Q`c|1?ij{2ueyU3X5*vYmf|U(Q<h!)Vf_qoVOY z0!?^2MdY?_D6D(`$$x3Yu1BXe&a2(M^FFGAOXi}kjpR*>+1ZuX9ys;hs{HdKeRsja zU)OkDkIBxms9<Q3I=Jp|P05+Nt-qdZ{5EU8f4+}wwad%5r*HQk-e}IN-*WGZR0emO z+~NEm7rhT!Es~pIZg+jdjF2toH!M9c(dXc#P3Pj0!X{mtG;4QFs{6)BZ=V~|H@$oU z*u6WyuD=t+ba?yBxh?S~?_7O6S!I2VXC%B+t9yLkXZMlAr;YNBl3$x_hzKcKedrF~ zl)DOb1_xz)4A_Ow9Aqg5Guieub3U6mBf(Fe=ivXNX_ErEI5qSSA1Lp&YWo&**=6&+ zwuH?Ow-{eob38QfU}omL$o@-7`&TB<S!tOkdTn;pvYB5q$`W?3e7W}0nUc%543~;u z=Dpoop1(u$!P^5l$wzPYUtD%!O0D6|5R;zwAI(f}iWq!(dH#@Pt?XpqwR1o5^TeH7 z>QG#^b?4S~_c`Q4wl}}p*1qbtX1rbWXMx&DO4Im*<b$rY?P7L}ZrdgwnVo%hU&rlN z+j2c0-J0-4vqbTO|C`i+JF6`06Zh)(f8nltFqc6gW2cdq|Jyl5NtfD=Ce-bDwwP01 zn0bd@!<xKp(y4ZD^*yHK2|PB~$IEr))4aVAdwrOU);bz<1*mRak#zQD>-AV$sV2kY z1<@&s+cx+gS|}r{wBvKi=PuiI-lj}lps7ypsR44uCv6Uds;DNIsB6T1zIb7>;f~u% z>V`G7LX*>ywK%IXimPI7IlW%F>8iWK!lQ~8;^Q9)ubmLZBDAqgZBLzUMzh1z?+Ps+ z{PxBAoS2iJlT`QQLB+|pMSj{QzQ3>jx#Dxa@8tR3py!+0o)}LMaw(X!=33<qH-@+A zv9lYev|pQ*$?)EAjf9RL|IVm4A7@QoxP2REe0s9R%@dn#q-;(ruk#f;z&UU7`Hvpr zYkwMispma!eX?Y8;GWdN<hf?IB44*FT=V%THS@~(OYbh%K0NRsIIU!9jPFy0?iJms z5Bv*0&7WT4tUA-eh(p3=$3kZ%Z<dd*C#b%BZZ!M(?=Qw>o=nEpN5YH5?+UIkdv!*( ztgZQ!>eJ^oOS<=Y#7LK_9X`hqvGZO7$Ey0>47#=nhxFVxoY?h>Iq508lS$TrS($-9 zy_w2pZ7gGc>OJ|XbgDq+<eKvZp&k-j4^CyfsWm0IU+T*?W2;c9dM;h#){8ZsM`f12 zYf{<7y-4h3Qt{zS`@ikF$;htJyleq8+ojJp-8%0rWG`K3seWVAhx?P9U4qrN%Ex4C zyL~%rG2!l=J2fZY9q+pOzDOf-TlTv24Qryd#L7&2m-y1CAZyRvTii3YJ4;)Ke2y_s zUm(%EeTA!j>KmuH)vZ|ulXktkyVTKKW^c>uN#EkC3?H(xF8!`?>)!{d=KQz|_M59! z)?9V`;vIY6d71R}cZ*7nU6NkV^h~O}=yIG<{Nt~8ujDUSdD(yG%*);!<y*sKb>C*L z-LhaA&x4i!j`AIwbSSmGY0X_zF4bMd!E0_j<<0ZbV0aTa<I&XGn3hB3!7p3YpH2#n z`*3_!l*-bUjz{@@(^rR_IBv;yWt(U($3E$mCw65^iw7$>S!!|rG_Z*?)GQ-1uE z_N51DRocuKKWm+yzwKdynML;H=}})Tb+s@3@!)-JTPCG@tL}<L{_7jPyan?`OqWm2 zTDbE4&BszKsth4QlQgc(nNo39-Q6dtVY{nmQcJa8*Xb?kW%n~HpIQBV5_)Iqs{h9} zzj&Q0bfx#lQWs&?Rw<8j>jkP(Z{&JCle@ZDt!=Z$(y0FVI-A&5?X9t!zpiI%v;3Y9 z$8MH-_gQ>Cy5->E8KJFv0|KN&!$jmQ?CUCm3y-WkCi?2Y`kGcD*`BRWG<W&Ff3W52 z1J}L1m+wt#*?nf`Uq_u4`pbJv{N<nAx|zgw@9XRgV^{rTf9KrNUAMkZjHzGuW7Fp^ zd)K($ef~am^Tkr8_#?Mcnc{gLp4+qa^u=|Br`ujE<eRhU^sOyZdrZ|nxZRrYGRgPj zKYPULyu;I?qBvKx&Hv2Az@W><z#zuJz>or2)E-)plb@IZU+~%+5}ke9K&0;bdW#m( z+d6@_Y<tc=aJ;=F;Krm&rw?az2fj&mKQpaIWjXKS|FxT*cyD@_SlPLxc;DyR=V@VA zow77s0}bLT&cwF9@)!C&`Iff+^hHc+3#xbB$PT%leSYutDd{0!x3OOR;&q8@ZlJlA zu4K{O+jrMCr%88iRoIfo5+A(ARJf+&OThG|G;ht;FMIqnZU!8^<bAL>jAiEp(W@Kl zg#xB#g(a?dpz@&2dd}S1tn;exHk9zszg^wxb@9-TpTQfp?dY%GyDQ4y_Q!Gm%+4)c zzLFi6W@ePUsEmsWT58og-E8rRCiTgkfA`;iG*MLMfJR$LNa*26udNST#g}bg(EI(- zqia)`@}`%6FQ_Z_eXvKzH}kev))cOwQ;E$B0+@BDHpnh+s5!pmL8$kKl*;lDqg|ST zzKouZYpg%55j(RZLhtbAJ(23CuRcnv-MeeP)8c?_s#Zq!cXac^pW9DU>+$3KBho9X zP^O`J`hr$j&&roGrunY&&0;TV-@|9h_o^d(<3v^-CgtdD`<M<JH*S^Xi4uxP@SA<9 z!f#vD^@}xe0loSq_QsxXBD#u=y*?iktD9$h*u*mH^obM`XCCc?7d=lJw5ue}d8xuF zGVSM=xtssbpHj!MIp3_rgeOFLB2RC}*+moA87y&-{gHd=<l(d5zy3_h=(YFaaG%(> za`KFssi$wxa({d;vTSjM%KLPi!@kMe(jGZAh_P$_vkUrR#>u|r=7S~C4|m*-E4r^? ze%(>|^bZazCUf6;i+g^pZ*?qRo-o08i$~B_Zi(|BO!pZz_XgikIvcPnI^)qYrNamE zOYD9>YEQ11&bn=`r0S%9rWw%_OLo7WvZuZ5-ocEOJ|>+mic?>jeV9M**+J#GPnU0A ze_sAD|1xFekZH<mR5x3TIJ<Ib&a$%Ll|R4e=FQI!4u87XyK?`t#eY3diOAJ`W%}PG z)$%sv`erjHmKdIee?G*{mOSq|;kVudXYI{%pY3M9dt%qyKdsf5zuR57?WoeZYhulV z5C0et*`%>6EQ*1Ffq@A`FfcF(A+kw)d}dx|NqoFsK_xRD9Y`4~u^>|)hc3`!*<}JZ z&0dHwFeIfgFbE>-0qII9$=55Wd}|Y(f7{~P`=6q2b|RM#n!ilASZid!ze)M{tRItZ z6<Os9a%^(BJ?F)vuArdr*YztaR{TDjYt=pX?j8#j{_}I&pD3=375T+{`j%>;kl<;l zfd3M19}n;~8Ei|IVtez5>2-{?n&H=zNBzD$RK5K%=NL!u+_EVZ>vB{bAFa-s`(Ho% z@#TqZ)uHx_b^fJpu;J3$_WiWOWRuQn#fAOq*ZGoOY5bUY_JmCdC;Q&dIZ|spU2^;D zR4*QFJ^3?f<6C+5{izjpu{=NKC;jgIwfxfGt?9p`uglr+vis*p$h>8_@_K$;?T)Ia z@q3HThF^ZT`satMzs|0{>u+B#6}Pum;?MsF%lqyB8g+1lM<*2SJdwZW@p*B6adGhl zqI%+;Z!CJ^mgoGpVX0eTEmIJ2QaaWByj^7D+sSLbo%}W_<|6OhBkGMN?Q6nZc<$eu z9LA-3MkPs8=zwoo*`uR}51R4VF4dD}NpjwBVR?33;-^o{;kpq&Ov^TvZ9B|r^Y>Zd zhWQJNJDgVU^Wu!H<^I&8<W;7xKIM>YA4fTZ;@N47*FDgGRN}NQUuwdMQ<s;Xu~Lif zx3aALX!T5{BVT;B$knrfJMP-5o)7IjcU&!1Li?Fji$#mhIYa%DXo2Sv7u8=)v@KlQ zGI7NX%j*?Smdrn_aou>~G?#U5@73=q_3YtbUZikj!CA)(3VIG(OvI1g-5}+;nx}Ya zp#Jgt#+QpMvkZ^LytOQuC;LWt-NrR(?#g1`vwD+?m0}gX<+<B-HSZME>XAuYb?aM* zgr3{?gq2yVnh%;?TJ*R0&|x+Cv+J%lX86zdxWKw)bM33Sw-yBDXO#SYcH_WaFOT<A zm2`Sq7xI|vKe`|)cb+$?vTs4Y^zT3+mKvqAAC(rlG~R7K%QyGe7a@C#>4D<R8H$rW zXswU9d|>B{h&GQ%AFU#n4-XGm%`jzc&5O(4sm<vyL-=Cy@gLbmGHDM>obM#vcqe@- zvBmcDyKCP<x_oOEWEIL>%oP$YtE+h>wf%0R`uUSH4UhUs%1>kYx&25_pF#LsKA(km z&E|&hzVnbL_+_a5*Ni@A31Pqgv%>!~olbgFP+7^jf038Y42#3f1=FoQA81>b&$U52 zcK5SKF`qOq?G4e5;o5Naz{cjrjEBjmnQii2>=~-}8~NOg+85t(@4R4d=h43#<ycL+ zHwy4cd@Kupu%l>;@jmy0+nE`gBi)*rw_av2dAowU@wJREQ`Ei{!had$Sr$!lJ06^? z`lFPuOeOo>)~Ty%HZ5LLm!h-fDtqAGrH!(4gI=s@JpBB&Px8k^ljuH|V4vp8*SNPw zcCY-OxN6#rn$C@`SC^S`IbW+@7cV_~XVaHXZ(;l9>1$U_&pG?++_Y}#tCzW(Yp?ll zSrNBL_4Q(Xv*JMQZ{?fP)~@H_eRC$kd1;n!<WdWBpOxz@Cf|x!;#AD<yyK}*L1#ec zjAwUx1*ZJGBOer@DQo8W@RHe@vmd0)BepL6y`{`3IxAr3XD8{`>!#1X=p#Ng@5E!X zgHg3PXO_;;EBuktdnYz~S<6#H#npzrl~LN?CV4&ExzB9t&$&~i%-2NDUNy~BzT{<v zy3!uMo&R_i*To+X-|TYos;R-+Ubm|z8aE?mIb^mkjn=STWO%Pp(k@wgM^kT~!p%@; zm*x*i$uTnz&9HcoaN*j8V;f5Nm#XVDO67z!vHi`t`d)d;zD1smzr<GdJGAMZT9ALh zQ#gltPV^B=rgPg)+|1xw+FT_3QYnJTZu^Pn98Yeq5-4C^YP(D6!%OA)$q$Y?#^p7h zcaLY4luX*dGRN}7O{NVj9Z!`V>Ov<dOl%hFbxh}b_2!#xK*h0bs#{tkCMojnoagki zVX5JX=LS!ATuR-@A`-J?1H*a#DVLjN@2uBSInmIdy1;M3t{x^Wju#5Lj+yEVJDpFQ zd>`;j*gK(J_EsWO%=-ziIe$Fo`}>(q?Vzn+qxpg7azE!Z_S$T@sC(l3iYJqqMJji) zR`q-Mv+J;IyyNsz(A!+$t=!VRjH};V)C!*Pt>Kbi<2}ZgzF@+!nf=NGkrnb2eu;c3 za@gzBc!*I`BEhgr%$Q-4(h|l?K~t_V><zfm&A2Dv$x((ljZaAotgAE*R4li+m%reC z+}Fv5qECOz-uicB+x>&_|3c(AqpDnV?>7CFyI8kf;jr?l0`4zz6Yp`^SUUOdW1Z8_ zrGDc3iZz^@>=(V+{=l~Xh3$5Qi^^Ul+>2j*T(Zo}a%CcC%7=h9$qSz+-1G6P&)UQy zU74|1^2GCnHO7{$t4<29sP?Gk`}9-ezD&x8&?^kSKUQ>F{+QWcXEuGa)T2F&=f0h| zDO2%r;&jW5>+WyQDQ5kUFbz}4ZMk%=F<X9TT*Dj2Q~MaW8l~Ppuw|?|&$NSY!fVzF z|Au>;+k}Dzd0w!3<TFa~1T=FmkW(mSPFbLFxJbuqVYBLnw2o^rO*M+Awzp(RC7HxF zu{mFPAp5{Z>74b1_Z^?^GCmPhRKKt-ICsHM<*a{vCiO07_cLeLxn-|wsA{<qt`OKF zw3flh>4d3+(N+&8UZX1yq*fR&*~fNM^3*=IOi8cZY+O8=YYuAhtlb3R+9zkto5pRl zwS{T5!Io1|dP@WLv0mVwFpn=vX~j}gk0VoD49q0^&YC(Hv2xx!e4*NBft+%w@Ui$c zVuu!VN|+`#sU=-$(Y)UL@{_n%)<>2)+0~U&Dz_H7sAVX*`Odf?w%Y80v74Rmh4h|Z zCXU}EQq3Kk4YMw=WF}83V~$Zj@s&+MxaAJRG?tAy3Y*j=ZoYSHQ=jrs?njN2-TTJ# z>Q6q~W;~KKHDsG>xneWtl(L8_{=f4!-j`o6U4O-NeusxGB6bW<I2G-gTGx9#RKD>o zdy=khXj;s>;MLKIC+?)oj#wcwdq?85b{*Bc-$`0|YtO$;-J#Oqnx|-#`6l%Hhpe;Q zYm<D>e4k_T_H)_>wUh(pb`#!e&fhBY=*Nk+{r^r)TI}&}Z=<vRzSvq}x8L!WI=@4& z#{5*-=K9b}t#;kKe?QM_&wrnM^yBfDuOvDbPn;q2tv-K!(m~Hc$2gB=ozHf;_|G~O zu)D!&m$Q~eD`Vl+oxZ+dd%bh*XLWD=8}e}Bw9P@kR%U&Bt+Vj@Jn1v)|Mms1lQ|n_ zmG}7L`X{Sbe6<PJl_`%(n8cFjeyo69VQG$5SlZ%^y3fPgwt6j^ZhgQ)B~0kzwmC00 z%kC7rZ=4_9>1`k*^w#t1Bq`~T&-WMgE!w}(=vC>J2dT!dCM<Zi$87yl6J6bwY?*g2 zPu2*u$L+BHYGHNyv9()@`~H;FvMr0x$LXz>-?=-c^ZVAmGM#5r*DdaS5+PiFG{#6~ z$Cb|RhN4M1%;HDgi;_zBuJ3fus=D4FUGQ=d)63Sr*q)G{0@sd6z48w}IpH@{LytXI z>51<5&2-RNr!}8#?>Th`b|c=HhZi`R+hrc}`TH~7Vq2t9c%-C!*YcjcmF|x(d&@lX zo^$&7w#jFbEE*55?>qd@xPQTpX%+sn*$mBV`c7G_cDGoVQaXPzgND?v7_OIg1*<1+ zJGjHvPq_KW=OdZUKVmEvy)J+AUFjV2s^^MtyPr->kbizY@$_^BiN9V^v+hnao7i-I z{;Z}(7HL-|l|1%US8HD}U#%8r{5xk!c{A6GU4I&?7kyq)wP@e2Uoy(CZeKk4i1F2) zzTE~&CGrtQo1V@oSCY;<x$^zeC9L0f=4^^OY*Tga;p7iD@07F}7vAN(Qe--<()x${ z(t?Egll3871&p(8K6am6IQ5N6-R8G*rp^6U$Nzb!^W!?B8twfFbNgNw^|ff~&;EC+ z+LFohdJuO))!Ij16O5vs2b%wk<JXDx-s^LxZqK#y6`N|p_R9quSh;=AT6@p>U-8*r z(<4@7-oIob^Z$2S!hXK`=@-N9Y|zxt_|Vtp`ns#)(XUdrdsaE#+vhG#)YiE4G*%_* zfTNayc8->1skycN1lEP;wU~K(w&pQK{aC+$GJDXK4gJnLcId3S@y&7F{)GDqcRla8 zNOYZch~&0@vi<%9fea_^oqO6p1?}OqnqFIV;;FTk_sw4+PV1kpklx07W7ePO(#u>k zJGuO4Y<zK)CEok<)!f%x_rA$XRX!oCdj73|!}8U4xelFZR~O7(aYFo&imam5q<M3@ z9eAg$=4p(J>gEvU)h&-H4w#w~_Ef3r-0|4oSA;L|Hy@iDYwE0Z$U(KM>{;mf{jXkK zbjaKI!@pWYAp9p+y7{6>N6Y4Hu=yjEbtx|WX!9<I#Z2CcVPATMo*!@j@7nf%&xsG; z`#6gaMO<I3Ynkymd6#YZuZ+&!vvmz#&6SkD->S~@a`Vop451xsH(YJ_+AIDgx;dmQ z@ZVGAkbaFTQr!Q#99M0L`QNtY<4oqh*I|3TzdfB0Si1GI)937t;-YgV3k;unwCrgO zDX}}MbL7Y!Bd;0UBC6J3&ptTWxjn3Lt5>vowA-U%*N`jA=9oQS=+tFXxUYRxr1;V+ z*^dpj?L8BE`S!uXj#h8D`aUS>C)TY9_5OGLN!HbLgXEb__Mc1EDQ~{;pT{YtS@5IB zV+M7%)si1(eO`B^`6%Zt^%HB-+J*SFyyh1lD)sj3<w<EToit@es#m_Ui_eohx4FC4 zt~**O!S~=)by#Zs$?%^?__|W3i)BZ=iPEbK3eCLs)8nhgs*}<ycdQM0b~@8wz4P`j zm)OoJ1$nNj%D7T>OFj5>oAt~6rx&YT>3%xrn)%Cp&2ptTzkUy{Wi3B7@28F1D?N{_ zPw$rL>g6v}zc;a3j(OpW0QdOG+eLFrV?Rbs7j=@JuG%TRt|0Z*iO7utORs1btyc66 zQ7QH<6KKlHyS7DOO;ENft5nX115C5^dOL!Px<dYnUT>Ht#&~May!KeX<j}Pta@k_( z2@ek!`LlLu>z`k0)xEsufqtq(!kVfJKm5+H<hlvJsTI$c{IoCT+E<Um6LuZCR{r5h z-^qm9NbA0|W&5HsmKCm#UY2-@-F+7O=R%+P90H-+3*0qXwr9-QIzu~m<Gjpeb#osY zC|f6Ns6VwZVwO$Lft^Wb4j)UcTsle5^_N%0guhR^migHvZ@d=%gQ;6z<?3av+GUT6 zHFvZX-JD}+*Dif0NbE~o>dPw5;}ib4$KGy@KJ~|as`#co4%}-WOw<1#_|%@~XOQNv z=0~p2CmKrWKlPrZd$&uHNAil;{|fD_hw^KTuYEEz|D*hRnN5WEX5Y#^Vb_fER2KXQ zO<(cp;-nv;rq3d-%}D<0!1(dJ(Vxv*Z8AmoSM03S%RZuiZGqA|Bi}oWS^t`g&qd#S z{!_O!+GknNef?~+<lJ7~hYyu^u;gwqd^*?d)l$*?ChmKSrY*I-HhcH(nReI3m#OAA zOXtj$>6a4>uRgnhP0wAS`OFIry=mN+BXT~?`Eb{ccan@bhmz%?YdzYA;p=(=`I^rp z<r?#Fu^6lfTQ(;(_iSnK?rTrh{#<$XS;cb;)rGg#cE*TEXr6Fc%g-{ax^}DCH0~os z`tn<rdu+HG<)^}x6aOx#qxIiDrmYI+Ll5kpT9>b59y+I7uyRpiQ1frU=$Vo;WRI@$ zHPDlqn0;|d>8+j}xBYi!^|F3Da&}*KO4Hgeobk50$1J(moakG>_(z+vsUsJQnaAzo zw3t3~)#*ErML)K5R+?a<VzzmX@!9u1kq4*$QU3aA9Sg$?&kNJO?z<k=cC2=`bmhFr zlYKvgY@d~VE4~%8?#SWr+_08dw?~3&-cD`k%|5r$@Y#i|D<>|#y%Cppfn)Nk_uN(@ z(fjwXu`;akH+kBApzD0a^=m1r_dj+h3VeKdZm!EK&whz%r_W}sS$=2TVU;3}zVlQ6 z<t4A-lBx0gaZ2MjBZC6>g=rr*$gG{7BzJ0;{&pRa&w;n%8yT3co+|QJ?b^O(e`4Z< z+qPHq_}#MYcJ?2<zIE-6o~KLt=be4|NlN0e^KXG&uUPr6uQ}(tL!j;1Yc9)ON6pu9 z7&p!JxPR=Wg89~qJ}<<ZW_=2}k*8a(l$W|M>(%3zOfgOgYzB{Hm>vo-W&i%f6jt?I zgJTj)=`R63(}wNFEb&hsgtMgdr_WCOH1oXrpZa}{{SQA0ExESoywIN8FFuvpmAr23 zILNi@!^g(_=*3(7i+UeD-4(dZOZ_A7)=e2TQ&-%(!+d`4#V4*UCyp-fpSUgT{dL9m zE7CJxO<2erE`30G{TIVpeiw$j3%=_-{LOo7dS!=|@{;0?2VqaU?uzvVOZ<po{rXqs zxao?brM?GL@>1U4(m5omuE5a$Lxrt-<#XO`DGo6kZ)v_@WDCs}TWr=m+j{m%qpn2@ zr!1cw{jB84so3=UcQ&4o>EfJwv~~6N*2OcE{{PuIDeGmm+vRDJYzKcYYk#<9i`x0; zZ$E9nvv+Q3NA3C<iEm2-_uflcvGSAny@cJ`f40A0Iy30m`n1FMFBTSmak?EVSjO{O zE^5Q}Pv3I)b^lU(!2ffHVwKPyNsZc+%-I3wr~Yi*5*4#>n&#PS(btTQ-sGE9XR$$6 z=g?EP+uyg};hT1cukMcAnH_&E1m#O?E-ZLk6VUU^Y{sJgy??GBdXVh->cirn5sMyX z{l6(M%6zVBFZ++a-#?Ao=b1Ur+ry$T`IWB14;e-F$@a1<_jsN-xRmq#J9Fm96E90I z#C>0+&}+Nb;7g74MNWo!cR7z9pLvykQucwaL+RI;Cdtj;BB5*RpV{cy?=O|`DZMtG zf7hXmRkDrGYv!)6yi>}%asSN+m7Lpk=j7JD|C#&NY5kW3?ea-+HJ?JOo|oSH&iC_? zuHw`FpthP?$v2yiGJUgut+VrI*oB$b8-KNyYr0>L{q%0bhf5Pr)ZOBq^tRzCzxkZs zs{TKYZ4{m^%duyb|CS$u+ompFcmK43()+VN-j;tnXZ>^iUz0C4l{bW~f6`sNp}Ds5 z#-5&{%kM+^z2`5eeVC}ane~46)2BJ?o5gC3H=Pl3xe<5Ap=;BfSf4$6t4`+^hrJZH zUw(-@^rZ8x@@XIVHvbh{ct;~O{#@=H`6nw*pSyZleNyJH-G6WM-Hbk+xUP8SGlTy} z6YsoS{bqM4`y^RY#T%8&n{KT9HgVBDv+%Yv>)l$CmuT&`x^^wuSMH^yS#gf}-*Zzl zb<K?bTu9~dR=T+<BI;IzYE1KmO>=cFYE{L)7S1&eo_{#x_O8=Xx!c)4X#J6F)VkVc zRMXolAGJp<ePvaH!3H6ZvL}DGC2W7>S(9*5`GMbyN22@0Zc4x743S*F!o@Ov>HGd^ zFa7ND-fc>`ZLv<?;IDkaX@gGza>qjT52~j8<TP*l{7Lz(&!+b7dPdaY*S8mQ=iXvq zU?^Z@U=T$e7ER4d&QD1#(krM;op3tuhysu6_nOwJp-QeR?)JFdEx)KY%k>t&!od<7 zE{Vp?GxqDNd|nadZPT*8cAcWUCFdMt_N6gN{AFGek+VH+aWTJb^8YmB=#LdsW{FQW z<`F#Hp>}rpb%V`EuUu36RV!n+j{k0VlaTM_oafUoI2ASSy;I1v#)|8{f;!7i!36>L zk1_VOFMqD}*{y3q&J;z3s4WJuW;SnXYLDlLcdygitam9bCWhZ;?)tc_3EFctM8all z)ZO{d@UDJjZ_B1-0k2I{@9o_(_t)fe**cg1|L&L5+I!ht|7z<mw7|$c*LdV0BLl-8 zHU<U>w7{rHPAw?O%+D*<E2vyL#W(M^fk5kbJJyGxyEFJN#0u=#Es}9ZCc&pKfl0+( zwY{(O_ql+u3nHwl+iyuslD}`he+#3R;rR$RFIM@J4;9l-$@7JGD_48T?|;){^ZW0< zzyB;2pETdPQOSIt#PfDWV>L79Wf>7B6|xtNteiRR_ZLgB?zsInhk3uq8BQg+b^8h; z-LKD%TPa}FG`q+D*UdR<%$+TBXRl(mb@`B}Eoi^;RzvZmvY-0zwp$B{N?gskxTng_ z+qL!fr(<RN*cJE9XME&$$#&Jr(mnfw>?)rdtgUXoYQH5Wi%0Q7w*D)14(6vFd3SFz zHvc;I)Z_TK>Z3NYGe5Ph+;{vtr)0=~jckRj$5NJ;Ht-xjdi#Eu^1YZPdk=W8bbHyA z6SSXOFyhyrf{7<vf)DscaA$s7-aUQm(@KV{1lcD)-=-g3)R?-*mGRZh+e@@x+qFGb zdH(2|P{gW(TT670Moiv*Ab;^X(OJ2^nfvB4$gO%I{JK&xPtM!-s&^OLy}9oj`ih@i z`p{A)o$XmRLC-UAW=}}?t*56WFU8edoB7{K%J8+o|BK-f%KLg66AtrTTUNc>+-qx? z-tmQPecwOJ9GjNCl5={aZDw74YzNZ8G@z-0*;C(_uViIlI3SL4Fb!yGAUCm~0GtK( zMnvb|HUrJmJ=n$W*`TiCx|>~DYQob^tPzja8g?=EB^rpm6`HEiyF@tM_5W`^e$7a8 z>!Mj#`6p_~$<;l#7ME*VUa4m4x#?<G_tk_0Z!MN9Ez8<4CDQAN)!F$Svpc>9pL<iT z9qcnF*jHcG_vVB<Mki-VMXdZ0x5<V(^W5Qx^wuwLf5jQvs?@KYS!0#%t+(UZOo>Ia zs#iIjZn>xaVTadCF1hJ87k&6nMjU%qs3v)p$MxK%l(~ma?PhF@&vnw!)fA69$TVfv zln2@yZloP7+FYG^+SGU2OrOXa#Z)!+X2&zrp2#zouG_rR=}q0634K~Kb~0LP89eR^ zynL+T&zJ7a^(_;APEzstp&_d$u$=1zr{%WG&)CB>t~ET>-|Kx!SWI|9X=B=C_H%OX zE(dO`QtVRASs3|-b%nQd+?5WWi3=n<Pl(tHUdUGG6koDIXUiitg?+6Ks*{`4iW%$F z0#kIiByC=$TbAfh*AbW3+S+X0>BD?zYscyrb3DCyc*M@HJy|R#{rkYjjJba$K1t|q zQC@t6X^z}ku0xEKoyFhR2ZTRnymGZBJb4kb+@(w3ew^OBmeY6ArKi6;gW9GFEp$yt z=Llc%T1_~o`{;$RGu^ZPtT=YPe~HP4Z+B1Ci9df+DA=-!^^wWBtXEm<vaDWJT)Fkj z;J=7qfW(g+mwe5$MQSV0J>d)59AheR_EXbY9rIZm<yu>%&ZG!bE;zaCl&9hTe$nmM zvx9<Wg{Lzcny)C>$o<qRUFqA~#0Rq%YZRHy_@4Nlhb?%~wB3pier2q%P+c|oaxmki z_y@-v6V{$RbMxBN1r{5v?eA_`;r0ErpUB_3lRLG|1&{5!lJlr$uECZ)va_aL^LEup zvVWAncva_>BP^XeTY@Fd)mh6<OMYH)@=Fxgb&(r~FTc1IboOy#;QhsY!l^HWj+{Lx z@qOd&l?O}>j?G*8@`8_WvU%s}bw~8m-EW8SMT^$o%G#E8ShhASpv+{c)rYb(W(#dK zLzS!Me+~C44svYUb-~+V%IDKbyKRr;n(Ni;TBx*lE!%6fh2y$^&c~kzOcOXBYa9MQ zGmkH3ruT}P3yFtLt?0H*J*&I?z>T#tQXEdmwEk@pn>{zx)G$+LgMIjo`QnQ2zFpJ_ zty{`jm?^k5I`@7?XG2sCXVuJ(rB%0^+b4JLSKlkvRXXX+!o4TuB4rv^oBjwsd-i(n z5kKC($PK>19roGD9oI#JlRg~%KF!nZ>-qP460YbNe=`$y$~sWXE~Y>0S9{CM4<Qq` zpO_Kj5Xqq^Am}L&^m%)1|DCN`JvaYWJ=MRzWLegfxd+4-f7d?vyMs9`$u5n%qveV3 zg`nrJmTz5Iw3PF_{<(GQ{QuwB>hQ7tY*V@WZkD7OwbAoaJCoL@Oh}Wi?J!ld@XDO_ z=9}7*vfI-&#fvRM9aZ;iZCaw|W!|cB_l-EKfcp~_t*wV&8#YcTjGw#c)9T~N{I5l} ztDoL(&>1Er_kQ!61uK4(+T0Trdipc9J=UxBS<=}oVf}+=5?wF<-Yppax2*K?`R|XH z-8a3nH99S4v(%o`CjODuYtP<vE`74JCOB@2^t${toC|-nx*C4kD>#KoYu+xd1Bq*T z4Wk*BTrxRp9kX}(o|9L<9)0`d%dhjcr{{g$E&BGuUv3@4De@sl{nW+RORfKAZ~bKP z%Z(eizu*#B8fAL$>gm2k0zs`0*%<{|687=m&AhNmWNF{zb9!GLq{Qd1uxUBA`M$rs zO|g(n`SopFZ??a`UvK<@U5o$dzmH#>`F}9H3q8N;<NqqJnVatFg#Fz(^Qv`M{r*Gy z`J)0wZZFTMZ-|z4JvTcreudg|--oLX<o?>!@X2FogZdr*2e+KAcbfgaTX`(MJnrkX zR~Kd$OPK#@x>mP#$~Rlrqj!(aIkKT@?}qCuWPLL}-%9xtdarHI?%mSs?-e{g8XvmO zsqB7diRqbMZP{H#dzZy#`p-F7k7(YQdlyFi5#X`Q;b&lo)nQ<egV*S~hI;0D#(F84 z#U;9#d1?9jKAz65e!;GHqoRv%9}}(nzWzqhvfxa%Wphn3rJr|heA2eoIn!llp4#Mg z)eQ>U**2WeQ|S8p)pq*c#w97`zruW%nR>ptx%v60x$oy3<^H&HzpMV~xkB$tS6VHP zv-$kQeoE=Bl1Hz9zIOWKTef%$`^T@Zuiv-XnPJZJcXs&tZ@>S>Trw+8-o9Sy-l@G+ zjok0ozpsnxKKjaQ&)&#b-S^YYS8uH-FIKl(v!1)KytcZ$`0GR6y4VZB;itd;z5A)1 z{|7JUk1V})A#1H|8;bJ&9m+QTtUil#`($6`C{=621D@=u(dsGTotH{P*9&dkm{hV# zAnfb4kmSyI@i-B?=uGp7y^<fR73Z!f@DA-f>$oQLq|-j8pVxYB&;8*yL&`3r;@p(v z)w>=>=qLM&X#3W0sM;;va<lvtR{*EjtA`3tEZ+27{lDz*o;k(ZZF6N<a&~PM5-W?Y zI&oVu*daGnd7bB%PNC#>c9pkNC#ZUIMm0!2h}1uJfH}@_txP^Io9voQF2%K6@=`&& z4qSe)Jvsc~rb}DazTBhof5DB{iN}j74)3f;*Liudf1A00;mK7OA0Bi!)=zbFFMQ+_ z|0!s5_%?>`kspM#7Fz!+S7cN6;`BTIe2>V#PMri-ZR?$(FKq5y?|phsJFMfc-^Gsy ze{Wf@a&u?uH>t&(OJXuEwA^`Iw#(gf>$-!p_HI(`+V|tz*Z2CF*38cm53@Tye!#ZD z>KDVEl&Rc8j!)c56Iz0rwbd^f+fF`RZ}!+H=0Mb+>2qVB#kK#xpvJ#TDsY-;WlaU+ zE5R*S`9vA_M!%I|wK*!O&bafb%9U#yqB%7=US5@RkID~SyQcN&muz3L|1Hs5mR%|^ z@r)FeS+jeS<VleUEsKnsGfGw$mVa1m{B^_e4@FxPEtWF9Zoi}K7{_BD(DG;f*Rm~N ztamI8l&rav^N)35!Kz(v`2NW5NY2r)&&rPavGLAHzAb#5Oo10IYl7Mu7UfI*-zXNe zq0%G9(00M}!V({k*>TBEl0oO>i@7H<q&KWrXFqq5+wa$b7jFajp69LB(mh)6;&XDn z$+yd#8gCwYUz$<Cp{%>K;oTv_B&H27|7?tkWSn5*arcC;@F)AjOPMZ;FmIS*Hznmr zYeQZFTZP3T>1ZywYbjxtJQ2|+oE)R|A2IPQkW0ON_}m781+s_ch(DU#y)S&jXJwV( z<ZshYa)qCI#lGQDvrvYBxpg1IoyU84|GeC*vduA|Mp@Qs{o;@{1^hjA9dgIC?sVO0 z-MQiZ%cALxj277qQVcUQuQscNCy6v?*39Ez6*DudVG_J|w$iLJG2-czW)H>J-Z##e zOcB}OlV8fdd(N*vBK^#MS0{hbKeF-Xp05V8_P+PnvtBA}YtZpOA$zxoXl968xvgH4 z#W#WduDa13wneOumrP!}i^uOegUhyQs-m4rt0!Juq3*S?bjr%f*Y7J$`7Kp{?eTF- zfnc-S`cfCvV^%B;<QFmf$a%Ej=}eCaDL2fvaMjg&{Z#VqVhp^0;F@nku6Z7VwM_-f zJ;#f#vnE&BiDoDt`Y0SFxX0(|yPH`Pg+*ObZ^=EbU3_4M>5NC2pFX8tjXU#bW?G!s z_1_$)H+Yy%Xt>58A^xJZH%FuIo7nYI7rSHUqT>_9p16gd49Hl1aA}I-@7<4X28nFc zzR+lo=?6`Q!ZgQjCt*d`^>B6jl?*PaUSnU;q{IC-s__>Z&9KFlsndt&xeH+>_C znJ$iLxm%<Q?i7`TJk2~l?Zc(ZC;D3|R+_9lp3w3#(%I%vV9ff{7kl_7ZJ+v0*lE7+ z8;t<Hr(d=yziAI}k)N1&-c70LY7XnSX-em>{(NK7+W(`}rtHLl^Fj0OG<5X8y|^ri z{Zx*~5#azgR}Vg~=f9Vzl)Tz5_-OgTTyN%Y&x(3m%)RZ|7Oj8&XuZekg4^3a{%DNs z{CeW()#I;jrm1;vmYFIV;yF>$L!qVN+>u8e;tZB8!Ayr=UuBra`H=m>^^oe`n8n6- zy+7?~7Jhtu`hlu9V$$lx6V4V?L`JjDHxby)9;`HBen|2C{}0<1-fj||kZgPGBj+Vm zi}%NQ*RX0kE%?^k;?RG;;ap6XZ0+Mt*L&Nan%E~9PJB99_WYFMLt<qY<c-<yda>O7 z&-^~-fYDX{83`APcp8-&oBE^|d0+e-Y5blsmOat>=Yo!>tgS2h%}RT1_`4di80vo3 zGY0m^-Y^tow+Z~VW<rA693I~Tc3itp?aSYA*F@H0?wXz(PeZk(S023gC#TF}gA(V- zwbF%~o8OfBMfu*0jCPoR;i86YR{Xpl;_rlRC0y2w7i9d`FwrH<|8$>t3v*%n>(#m| z&a33FnsYy?e;voxJiTeAzwEy`@lD`Lwz5jS5FO^2r~1!F;koqp?vM>i+qWItIX%U| z#x2wBiT@u-8+}*h?|E04<+cV!>oFy4Tu}3f#eKyOnFE2o2}kGVZ=F2H$nv>BpXi^9 zLcy$tK1Y{Ll+XyyaI0O`;->s`hJIyZXkqCA5!d&v5fk+UwsGy_IVirC`_cygH4<F= zW_DXo^>2H&rBs`r^JZTlM?nC4p7FuO=@D`}Su&M#%$QCD$|x>w{BOQd$^Ukm-a~(d z$ca&kMjl*i!!*AY<x0Ki+_8`SO_lJgH?4b~OzsoNjJ_g%^>H2ZomCGzIHD}S_TE+e zH&-SksMg}0%D&}BQs3^RRDXJ)7MS^F@rL^63;T`=G<|a{mr%cByDO)<WrxHi4dLkT zx{}Tt=e#_Zx@~hPvr2?uMe(&m!Q~86vhsSjE%IhCEjqyCeRbo9i?IqiVO*8L6DM+V zT~u5;+g`d~;oOU2o|QkQ&yZf6KEd%+Xd8!ah@_3$tjWgb_*NEt^z`%odL`qkYE#&k z{rP_`T-|*2?B7pszw%6aU#L)>eCwy}grfA{Pi{_iJTTM8a-+^qZDG+Ue@?q8qF-ld zzPJ*(SxLil&gZlwn-zja9~@tB9G!l{RJi!wq4c+22ic6IRAsjX|D1A9-}5Hd5e~Cj z;VV-dkEgs&S?C$EGrjbO9s6g`2~R6+WgR$U)#n_Xw9{AgL&(03M^{cweNc6C%IWWH z>1#sdQ@I2=UNGE@RJahP|8YY5i`jh7i!T@`ZwwHcb>X*cd16QW^0ae*e4jK%zqEML zET?3;{zSmCS3mA39kKFB`@Avd#HvH}(QnE>b(~qka&>R(J{4iEZTpzrpQJCU<2o)K zx^!1o4s-5Y7as<(cmJEL`we?}WZEPW+BTnbxvceK<_z{5A1(gfFz~+{J;yZgl~%{L zOB?2K9=P~GyO@>h<MR`t$0p8kyJnTRGhL!a>h0W}MoES@V<)aWpAo!d%gU9JHZ~W# zo?PBJ!%KyK`?+P6o{f`luksY_TO*x*(q*Y(pIY+F8!Kf>nS|SGywCRS=X?-ny3xU0 zT;6KMqP{uH<PsMLCI9vo+RQ!4;=YB<<`X$HruJ@}Cljl>tlwIWzi7s*+)pn**I%Ah zIm<OGjq$M3j9p<5zfHWp{!Bynqqn?Qr}sWw#&fyM`>pIW!JxCf0eo{-iNv!cN~P$1 zls4S`fKfBTaGOi?i<cT7`0bomC<phiI-@YJ!CdOds<m5c)|cF={;|8ko>7F2>5+h# zv0SXA)44{?@-pR?w(sIuKJkZ4+j0u?#3XtB_D-oiFmvC34y&IM&)S_Yu=P4GSz>l| z)qS_O`TZLfSbyN0R#K!XQg`{$SCcH}Ft&SvhZy&2CtYrwd~5R0oD<6)n8)*;o5HZ| z%KYb#ysWe4ez>$vOun(cDVEQWbJ42V%;p=eR3>*%O=#HTan^fQljzAryYI0<Uztje zE<9M+J<GoL@#)TD{layu6YQhc94)dHw%56Ky42v^@uz?L&E?-6J%04=-K5g}d*Zrh z@BS0@@7dglHFaY3@$1$#yvx|fSa;;*3UBp`E!v@GYQB;##X*t<uNZvwW_C#_Rda1j zIP?4I-`}s9*6gd=8MAkH^tyjle=mQ1wNJo4_Ws_#f?Hz#Y^d44=l@Kn7k59^mF|6Z zon0*M*xN^ZGT$EledKqiZpZGuk@3Y_pWZ&imM`Y;U(W1m$!iC5<2#~$hgogXee+E( z6<ZbXUTp0T_@jE{?6ajdxg~rSf^y~uwwATLIXA^>+ew~R|K?3yw(+Oy>rCU*8^2Gt ztl?8T>iT}`ofmC-=ch+hvR;^<r(hewR&({j2H}zxKWpi&Ewgnv7AVR~mSo+|NQhs$ zOXpE;xuN9KV<*q2KmOa)$#m|E^j<|L_fxrra)R%54^3m<*ZAN?*`Jy^gDSsM?0l(B zr=@(Qe|IwM4BJ*@J@?_`S0B6_sw@wD<$8Z@^X+sG4TWtrQyW;?(sxxTK5u1fIW|-J zMepOR)8)@1jwY`?7XA3K+w?V-ZatDerSDdzr|p>K&!abQuP}eq!;R918F!m5yY*Ua zzHD97qMToGkERG%9_;A49%R1wX_m_Dsy9MA7b;ae^A*^`df>s?w+E%Q*&CY+J6Qf! z2s}?clDKP)oJs7YYyZCTo?yst`B2m>eqQp!-54FOHJll(4SRNcRuX-sqiOeU!Y=>I zUw>@+aP#%H15T&s8rrZf^?d$h)7-Rm2X1G%Rxky)OPyL5QqwW-_yW1Vd?Mwm-hQ|` z$wVM|vzcRgqFL{JC&B#6)(y>Prmv5BU^7F1-~LOCj>*j*7vD@)Ke9H(MB=8g@SJn* z`CCeS%cO-Yx9=BQsJQOGRHMm3jhEg&>US5ZxcE<Aq{H*aN1|FS*4QrjQ1QOWxvw&2 zdtJS-?gLlCv8yvL?%blQ7^ralVwdJz_w38LGv~`Nt2u}Foz>zG?7qD7<Ff}R-K;J! z>Q2a!I{C-0`&f^eTdYOH`tb0G@bi1w-1qC}<v*PG)c*bg?#w8Lj;asq^`ESN_b`9S zDZ6{B2k-wC*VFiuEpj>2X~9*tO~;(1?OIm4O|<$MwR%|*6Bmn$b@M;Ad`(f8XK$v* zrwjhbFnYN9t|E)@!d35oZSt$q(_82Bz5T~NhiQu)f4tXYEq#4unbiVu0ZxaHi{<uN zpEy-kX5PK?5nsde{*OviW>tkT6flXI@#(Mlk!i2atKoOP=#Ik_#pI{kx--(`y9#$i z-CgnJ6xZDeY`!vja~g|GcDV7(OI$nSUd^xR@d3UZHnQ&@?|ph`Z???&C5r7^p7Q0d zv6Q%!`beMs$M4WTPF2nG+_$gUf9bKE$Er2yv)cS8?ibL~`_TB~+|#GuHI%+6bFjqh z`}4!*LdD&mW>Xdzx`iyUP%8bK=6u=6Qu1c2!!&1(@8|ax{gT`9JFE7uP{=aX_(K=w zKa%@5*H~n7?-jrM1&6$w|1>U_`0?LkKl4Ym&1<L5S|QLhCxiD0kIdTJeF6mzoC|bH zj^}^-nd$lH^}8=IpZ_DR=?3-Fji#tw5)x-%SnA5aAdkDB?&})j=;9dSc-Q83(QS{i z_kX(h)FUTza=uDBy)Df|v`;Vj-Kj~_rd*pDwDXPH1%+zfMH@35M9inI_j=0y?R3$( zmw5~<4w0`*pDOBHzrnKGf4<#!>1TUSR2(q2`!m^NYsg1K>koWZ;Wes#kp}**i>!|7 z|Gt;~euMGpaP4_{eK&9F2mhFPH)qq*uA58eEdQ|Mv)|ey1`oM!>_4-~MZVwd_19aI z7k=ARqwD&n@c!eQ9>)?-l}>wBH*L97|CvN(i{vYk&l!wt)81FkIys|OAc*^Sfks%2 z+wnEge{&Dyy}!ZUa5vR{?Tek;k3Ih%XZ!K_xusuR*D!A6tA3Y0r=VVQ#@(NDYNtgx z9NWwI+qS=0fy?^F?dqRb&wA*2>-rt9(u(a-D&8U|`g?Ul-udP4({pM{kNK@%e@<=t z<kzbuckh_DY4^>a4Zi2|mt9XUU;d-QVf8t+&9`4ZnQmQkiL2m#a=Ox#jb|PR-O7$- zp1*FX$Mlz~{Yu+}Y|<nHw1i)J8OyPs2`@}oupwZnj=LFScd#hK>4zT|unB!<5mIqF zSNvyg;aMgZSC*W8iN+756Mh%?t@?Cy(%w|97JZ>>n)dOX7QdzTY2_-sS)DTZ)KR14 zEZOcUjH?(t(xi`hK6n!U@{iP>ZF6r<O6QpnxkQHH2zOM<%P%ZRNe7k7{M^kZoK99@ zxf^8gPB^4pb^`acYX>wVGV~Q%%`_O5H-)$|9}9lC&!uD~<2|wY&k7lC*KCbixr6Ou zUPAUvU0$2!hU0o6UKOg9vot1Lm?YiGaJBNz)(g8zT+dc*%6C|?)r0-OKam|h9w%@7 zsXkzIw1)3c^Xse&XM`37oC>pHTioo_Q1RkUe3T1&&R!80u?b36^Dj&0PKlmu$e3Zv zIYTh|Ymgd;;S|LHTfvq6?qA~G{`H>U7wTYlc!AXco6C{~oRw@jtkTaFm|yJdX!O{} zaxH&u(822MC;lw^r1zRp=TG>px8Y0K{wchbOPQejW=iPO)odO%hjN#=u{?~^UTLZ+ zadLg2Rnqft*9x|X9|>FzXTwW5{elF$OjrxPWP8l{)#Sb|M4^#o&X!$z8b;q1&+%YC z)^JoSd18#`5w0hWs|}(T-^j9(m?6b*eGacegK0t9!vi;$2Izg7a*Z)s`D4q>-ShrS zx~!=*mCHY4oRBRyF|KW8)WQCLla3dx-j&pJ<)~D7f%=9oDx2b+kIht6Zj{XtUck26 zjW6J~%OWRjr)!gv8HL!&TaHJ!WNzN&Fp>T7R+B@<W+|#nCnL9c&Qm(iKD91WVy&so z66uM5T~6wS3fOGho94{OyYlVVa2tl^?+okaomWnuul22@;T|LF-REH;m51{zU-LX^ z@@=g&o6_n#>BfQ0Jhi%kmlETduQqpgy6^L15N2S|<GFI0;ehO86~Ts+${M9huKm4x z#Y%W(4TGKyM_bF~ySrQ--h8`d)0LHuCR>WcXBYQ62~5u9_@HyeYJyjC@<)#(^H&e5 zH2<b{Uu0UA{^0Y0q$Q6WCwVNm#=yCDo)M!=;L6`@3)bui*}9WWWbeKU3XMlh`Px@^ zOcC66y0z!wmSty5{(9ft*B1RO^T4YoTd%n0ZnRmRye8boa6--v&WRtUsPMgXyB^&c z;v#)v`wwoxGQObpPh!p;cgmfV4<;;A{C<-2T4+x94_=jtRZgwDmp&7Toz~kKrMhfg zcI(TGgNqe*gjR@0i~LZ$pc^--kHu`#YUhx)X<MYPz1?+Z!J-<;Dsxs1m(ubjpDk~g zWM7Hd<95l*T&ZO3sf&$I=1V0;#Cn~0YyVPob)#IBxD)f&484XMiW6SEK6wB0BE@UE z?{2I;X!0@OVOYZE4u^-qtmjf1?#%k!@uYC>qkl7+w%TlqNm>z`dqz-Iabn+0y{Qv_ zEMfQGb*s&H?L5wUFB!>YsT?Xz0&)w&Vu}TwUiF?kvg+aMz&8rtPO$EBnV-bG`%(vQ zRh95vQN!%1md#?u+f;2u*D1s*9{*768^}L*k5YBs;jjEDjkEQ_ZLE}XFCRE*8WX5~ z>3rzAgAopVzgT?>qui!`y%3tQv*ToWqldD8C*xY7UboHFtThkUWO46#ciq=b_rB(d zM<#!7E=-#GAY*^HY03?u33Iq7cypX&t(4p0^L5X%P1zr(%RDh~GO1zxWB8CuO-j@> z-@J!i?ziaS5SQm$6sC8F+|)5Y*mAY;+LA4<YggZMaR@n})sm8N>Vcn#Z15bGgXRH@ zO3z(V91iY^XwK|w+Il2HC+y<{6%Xdr53dCl9Vuz#+<5DQ#%-R%AqUJk8$UIFy2$vp zCoRX8L9pPa$s3lregXbcVmn^;O{(EDXn3`N!}Eya!Y=g!ap9nhswC#MS#kHKwTbR) zo;00}O*fI}=8m#sa$yqHhc8C{v457uzpY!vnYBH{uvk%5VU2In?exxtj;*gJ*fCyE ztrrkcy)L-Ks+-HXXZpdJog8=Ce(Fb9O-*ZC*c!X3v$J>I$v;=~dsK|}ltz3|>D;hq zL6U&fBeq*%-K*paIcp5FqxE>Ns3nBziImx~y<TYQuNv8Ez`FW{QJ~`MeS5PSs&<{P zSdx@zYd0ga<4V_?u5H)NujprK$(ZeG$eyWCDIHmTMJn=H&CcU$il=;)+pi{g2BveV zr4=OxJmT)NpDehIb#C0t4(XjftG37qC4Q{hcgpad$$iHpi|!v$&yAdgT#^#!NCsSq zT_!1fb<Ou+wiz|EcXn)3ovvoHKjqo6*y|tjT_@T%7%RTs=5pQHE4*gItQSK2gWA`6 zmj^EYn3usd;dW`{<6Epd82`Lz+3|qM;piXx40Bg~TQkwCT}#|G*8W(wWl!mAj<Tp- zH`ZVEvlCPm);9dp=3H!WNTpxm<H7r@1SjT9_xI7*eE1UIsVP%Au8UlqD&Q97B<jeQ z{YWM~xWD|Ur0qR(k&}*-#4F@o?muZ(P!sZKblW;B$z)UA9}|v4C+}Z1-Xp*LP=}S? zXD+>E2@%VTX0RvEJuV^~EE4GPKBcE9V-<6$;Sv5>Pn@O-m`y7ab8$(0VB0$}{-B1a zq{g2EPxYq;@u%iDWX|Q#<q++d!es8ytG~Fp@#;FpSzjFzWUMkc_kB3LIq0u0uMg*H z*8Q>T80}M2a`rSdyPja{65{%>tfE$B|3-$)Yb95nwVf4smZ`*EYqGDk=BA6h>x$~q zT5C(&_f3TrXFB3D_}<){!L@Zx{MBz=C$lczU{minud5LIvay-xLqit#(t_?Vvjv7v zZ+y>SOz$<0G%9x7b?bp;O$Oujb2G#2CVXI8<5AH2vM}2GOrGvq4we}WM>aaoww~iX zZ;D9H)S$mAe)eH=uTHzL?dHt4P8yRFGsO){BBlsBe3qHIjkCT`SK2##)jG53*$b0) zI4f&jX!5ylAkMJ-pn(2<%?ionzZOjwIG79$2KV39^DXNwD>Jv&Dspn1rnyq&XvT@3 zrxvlgmAris8LQU4>*lLm(Y%T5jQ^~U?%Aq!Q}@E1sXDCl7bh|wR^{c%-mU%gWP}(u zlOX%gQ%gCcg`V@wIr&-kclphzq!#Tu#+gx5r><H&;rA>H&9mhvH!9vK{@t`zMR&7< zm-vdCsZ2|w7`L^ya-6xhy-HO_)ccIswoN_L&a8^8%FBEyRWMa<9ar=QX_KqQOOy_# zxpPIXl@izTE)Z;;mQ~ytuz2+z(O!{Afo}mCOC2k7bia#Ars)P(Pnx)1BXjFq)8N$_ zi}T)Y+%2()!}p9>e?x=*Mj0pd5UEMMRX3N(?G5i*HPz_Vxl5VG%FaBmSe=EV&ab{Z zJ>PR@?hmhwaF+88Mk}2I=9?MJ*Pi<D*`jW*e?{wjHua_@JHE8u<?Iyt{K2^`94(n= z7VX-);gVd=BE8@b>{;R~-!c`I1+D45>Tqhy(ZwI4V?-=_ni5t<e7N$Z`nBcbKDk?h zGYZ64WSTsmYNH;I^3iy*P^i_G6B@S#%oF4G+MWoHxUQ?@u;y6T7sl#@Z`u#CN{{H2 zc|FVvn!aO`&&00%PcD@e8!otbz?&!2Lq&lh$U@5H24lDa-{(e#X{EhO1g!;o|21EZ zJD&ggZd6R9wQGF!8=ow%-ohEmDe?;U*nj16rE0G;xIe>*Ei}!bHE)*cBsMR%(^_vA zr0m%0x@(UU|N92lWwA@UUg_x^&*$`%f4%0xp<Rz9XP?>iX8Ok*qt(Wb4?p>K_v>BV z-v;yij)!lb{8@7Mys+c->-2B@cxC>r{p3~2mexx?EjCG4<IVFmPQGKEYUZ$V;}!M? z=lb$)+?p^+=uXM@Y=%Ym{qpqBvmaQy`r(sTNme_5ef{(I=he3jd+q1X+sC}-_<kQf z_3is7YQ*{Etv{EZmXjINTxvXz>F|5K<H2Rc=6iR}n>#z>aLIq=H)js+6>@M2y546s zf0@(;y|M!zLsVBDG3n$GYTEKBXwvgb!6CmGmqo2JJ<{jVwrlsqSvFI`_UW8bKW2IJ zC)X>h5O$qeuDxZEb&n6e?_=e767*?jPsWe5CP9wo0>g70_RPX^t|3R*?}YBk)O@=0 zoDoM-n6Bl~Btg%PxY~>IBEd$@YsK6aU-}VR`)VcwS9QX~Il&1&C-gSVyZYk4rHIj- zl1nDBm)F%FyOqDwQRmmyNLf#(BVm&~On!9fZ>x^uINB>U)!E%j&|>ywqp3_?+?*|$ zM-vaES4rG3*nVJc`oSoJJIuGuSI*pcP-B_k>IYvu_FixdInO<N`fPQhZD-cs_`i)S z`2ES7lI^OKl!M$D#k^RvCAVJPwco*Dk&w)DnSh=tk6WGe7TcJ{O><9_n|@H<@~67m z<qg$sUV%%eJGx{D*i1?HnedABk<^++H;**4dph$klvQTt-Rx3yION-mGT!Rf8#ngv z<6ZgGhBe7Vk9lg>rP_!juC2LhWv0L9=d|yBaW7sgb=9wsjrp?Y7S3ZjvVWn%Z?<JK z44!S&Kcgxfd~N%+O6MY-FvGrmrrcZGcqi@_4*q;1%vp1t^g_uaJcqZKJe;?p-%Nj6 zsdv0e!}}{z#^J$A8XR6<*2@Iko2~ZYQ5!3RcK8#kZFfD+a{ZRzt;>AJS>MHS`d!Lp z;i;l0yDV<XaXi~)Wb%)Nw|Aql%kB-1yB%64gw2{ep_4^-t;)Q0CzN)jEL%`?x#vk{ zRN3a-<195D9)Z5O#R(VQOg>|7_982;q*+8OGhQY5byrCEq4!MN%Z^&?w>oUGD0k0} z(!W2Rv2FAD_gKQUah2x-PO~zbRaQ>D`vq6Mp1U{p#~nN20|)x@bHnGpdfCgg)^{?; z-u{!f*i)CPPf_ABVLs08cEVz#rJo|lg@$*3kN=v%*0Ma};-<K|$1PL$G@X5?Jyo>- z>$#9Wi)PqoZ4`aCq5hTes%HT+ot%HL3bCyWZ=8Pip4LO}(>ZLfR^4l;uhL<YU-2SY zfay0YgHmsA^5$FLm|w+pev{bAl6j2h;F60X=hXEi3YA5R1N*LAba9b2?q%53U}9Q! zVS33$@jQR48;Z6r(kwA%&nk3U@7{3@{HEQVV)J#n#l=f{Ax|e9_{(M|f7A9Z_q)K^ z+kV{Gb(bqX;AHFeqeTI-f6{GZ0?wTHUcaWPs8Ur*@A0u*=~GK1jkZ1IF#6cK#LUSx zEUfd&oK-t&R&RMD(w4sa%A4%<GBHl;N=>ch4^547v{7GtOZ4zf$$MHmyfk-Me(XHE z>s8bGRImRDvz`bo)-5{Ua>MDQretfk!t8>l6%(5qoIP0I8LaaUyS}O@wQlL`?_aIV zR~{0(_aU#UGp$tBN8;Pr{Hr+!t#7Yut(U&AIM7M||CI#)f*Ib^9mI{gf86n&7Q?2g zF4!z!Bzvja-Nt?1r$hsJrI6mw%V!5ld|0R(_2OcI%j3kV-&1DJefckLdC5Novj@RU zZ|~(u%{k~Nvnus+lJ|3wT%~Oy!4YhR{!4_6b{j89S$FfJVfD$jH{ugNu3frai}9m{ z+nTp;s!EM*%-8!nX6@a|tGCDFXI5)d$;%Y(u-oP99>llb`}gnKwAU=3b?z7}R<w#K z;q_wr)S7(CLOmk(oy*KH--2nDp%!~t@2_ptHYn3~^zGgCdf~xGGyc{%Ma-G{FR>!) zl-c3izDj*3SN3lBCeqMZx;~Lt|G+awrenvZ1e|v`*?)2w$K03m{rUDB{`+fv=buB; z=gk<!)c^b{PVnB8slyifWLNPvMtz09$<|C!b@98l->{l1U$*DPwVix#rDf_=e80}A zQ&?S)|E=at?d+tzU-;Z7@D<8LD+s=s5|o`5qWR)@Ld1gm#+&cU9(Z?8aGj0SO_fPk z6b)Y)7kPi^sCM6`er>nvV!PJ~3I+X7>a%SB*u1KC*d_1q&Sc4H3&~qAYySO_oXpkn z$ol`8o~H?iMGcG>MoRj;daK>OVbkS>SsEuEh>KKJC%@g%AoM-|S%>|zOaGZ}UtV+h zXJ|^<oL-M~DZ4qT%RE-<-oKe1@|OF8&c~lKJ{a97$=G@D;B2N&Ki>4SPeiommsm}E zu0FNhHekJr<CNk{rAtmea6f-&b<w`t>>Hh8EH7*CGFMuC@#CWJ|BU;1QoMaUgSK9q ztI*PXrt_Xt%KR5r^9%gXbDmI_oKtc%?!&VO56-@Rczf^m{C55Car@==arWQi<Ny12 z`@(vQ@89G1z1sHGu)DvpXG7fk_WVEB_50hJ<Yjo{<@Vl^KgWN#d7*xs++NE&+}|sI ze9DYiVW(dG;MLRkqbC#hI}0Z0b9{XFqw>!a?G4+HR`FDcoJ~o{^*j_m@A*b{xu=KD zB&~>GGda<fzm#Eu?XhqDd&1e>f3KI^EuiB3bI#Yid+*;nTKwJqKe8vR{&zleo9r9s zm}58Y{rh<D-o1U6AMgI=XGr`1o~d{T_nCwDS)XOFOE8qwd&H#o=lo~r5PG^gqTWQS zkn5)WxdbuOa_yO-mB;cX6e;ajy;HU}lrg03!GFI8>=Lh+Nfgg7ab8;H;m6d+S^L4W z{9JH=kkB8M4_&V(?wSARIk&d8ejoQN{u|v+4G%tcTd~KznRZoNBX`H~PcM!#%={An z?T5k_lNT~#Y;x7#kDiqOJxyhvzmK8U&%0kP24tn(i<EWv@cZP9t&?w?h<}M~E{^-S z_W0Tf0*eJQ%bQlYC$%VX_;sD>$#>0qdF0fArG~x}0~J12zHZxa^U3)WQzmnJXt@42 zj(FtBGt=yemfiI$w-;Qu_2}D?8JumM>^9{H`y;`cjWbP^70qvI7%<-n-tuzC5-Ioe zE4Qxvt?l^fyJc^pcFjk<g_Tmb_Nl&UNY(yrV)4yCjd{b(nx(%cRR6emi9_b}nIAG8 zZF&#>y;ykjy~38uH$Sj>?=~^JCb{YRmprDE<^~PFP3E1f`ri2I>vlE<cjb8}F7mg1 zaAvXH((wE5qZ54EkC^}R&!3*%U~y#2Q^&5-!Y$SdigF4yrp{J~{w1r>q~CpW(xdNt zeqQ@1JV~uOd&;u+MUy68T-fT#9%<ZtHzk<y?G#pyif^^&j!M)Bikr)*87(+`-gmWR zAB*XMo(I2W*jMVtO}@9=VEd6Di+Lt_?EK0xbG>`oR5e|Tt?y4eY1kZ#boTh-d%QU< zeuh`q$>yC7vhoXgmI^H|@cHO;gx@ICFx85G!s82$+ivpKx8!bfxnj=und5fIl}pE8 zCSLnl%csS=^W)T0M`Bj$&pNhyqVuwIoZnhn_<0Vd^Pl^b!#?+bwOd!Pyi3|Kvyx@c zH{bSuJp1JG&#O1jetq(4?#rD#d%xK}%(q@wbpGy}nkv(}`aGG4pMTP9X4meRH&1eT zsNMXz^Y8g4n$CKbm;UEpzxkIRcfY=|JTCS+f8Fv8|E^wq-F)h>l-|=vxiMYO>u34o zzdttpTS0NgbqTBVFy@uMH{Eo_zNM->XSk4cI9V+5oY%D5(G_n#KY8`&m-OTG-$&+M z-B_PoP|f*YBy)X#*l(fpuXoCS++ipAZCeD(yy?@bxq9M1vaJ2wBcyW5zQ-UvVVCvX z`lENOzTEh0!M9<_xn%-c9a};+`MjFdw$L)*<BJb(FW!^RpSgC?KmQ3+|K$9?u591? zf%|~%Y=$eZ{?C0PX`tv<QCqM<_{D!F)MalMvRmH9FfcGgGcYj7;2us7_i%OfVLfQb zb=ZK1^+N3O3pe<T_*&U&8ZWJFxo}Re=2FANCLR8rwfBGjX;90rxbMsDuX&l7Ykgwe z4&`HlX=^{H?pr?R(^Rp|6Vj(&FWB-o+M=f6+AdMMbF)`yE_vnog&oyZiP21ToD2*M z><kPHD!5%$l3x&?lUkOVqgPT<;_a#BrF-Hz6WV-%!nJAUbD0<z8dw+@WN{l6<m&7n z<g)hC$#shY1lS(@trgoK$tt!tflV-l?XEye^8zMz%SRu+<X&3%xOeC7d*S;+{(hbQ zo4et!{zlmaHF*y0VjmiNOZ_&UzQ1w5&D78bS3_LG_Xt+*t!NII_*Tg?wSH%}v}@q8 z>Q%GUdxSjxt^U(}li5lB#y81cr^g#7-ky`pn<H#&@TU9tw5|Kj-3`e*{7EyS$tHxy zZ6b?pvYmvz;oS*cd&BOz7QOB)%;aH;=a^HlQNjInY-5|QlUH7t$>9W*jVc<6&y*_O zeg4F}X3ez;Th4jTb~a62IsK*dpNxke9bY@2Q@(QMTzdnzB(H$P$xlztq()vg)i`}m zqb)duU#`-btH_4?tl7bvQ+d|Oeel<PeWPINo0468>!Ml&H%~tNY=4yMtNRjuLM>l? zQ}R8O^`b6&yO!Sxs=Tx|NcqTO_f(;S1?6gw6O-3hHr6k92>+tGV^5*9=-d2%S8SGX z`%btJpmtQct^FkLr{d#ti`X@;Z^}}eV`f<OQ+BsF!=h#HkD2pxzWRBvZ0n~3<?VmH zl*(0Sss-0Pi|IX99LKWUH^nz_#{PXL1J79BcqUL6eQw))6(er<=+fT|2d%@W_2fBx z6*Ink`CZT2JE^};KHVL3bQ+8O^0vv`d5-$0(p)MohyGo^Rdco9f^#{KBub}l+&8Cr z^;Da-GmBbRwl=wae7)P$%ZK6jH?cP>zOGhKIa_4EbDLCGmqeGbP1W^x5&nyw@rGaT zy|h%Hc{!KwHoF~LQ#R}D?wp*lbXE56Qk(zlPs$f0?MX|Ux>V)t{UAY=6)#HeJek5! zHoKwg{YBPY()P9!K3uuJOODk>ZG!#8740`AeID#_C^xzMN@#}e!YzmE^ku3ib?vaV zcx;jqHK(xgv7I}ozSMEAZA#ygx%O%0*RUSm2RaRjkx7JE1m|7Y(4&zUmNbG`&_l#f zZpIGqMl}Kbo?VbW5MI*wj2V6m8Op7@$R>a`M4(?R3epY2OB&7D;U=J5Gm31&VJwHA zfpmlLlE$lga1+puLPItK+sRNM{UE%g@sA<g45SmE@aYGg69v)>!b=+UjNtk~n>=us z0Sbv_Xs1Sj^n>t{#uQXDAZJLSI{|%n6-X-xFKMiHM{xpTuNArx=zEet+Cg|pV}}Q- z5y(4~kWB&k1AU7N$OI5x(pc|>VhVi23$h8I8Cvv})F9m;yreNI0A>QNb=Bx*q0jb$ z%mLvgjZ6tR&4SJSq8o-@*MSTI;U$fM<v0xk*L>(Eq1R6!Q$To0<8$05q10CBCZbnU jAk#p2OQTT*PPaiStpIOUHjq+&27U$!76t~cY7h?q#D_TI diff --git a/dbrepo-search-service/lib/dbrepo-1.7.3.tar.gz b/dbrepo-search-service/lib/dbrepo-1.7.3.tar.gz deleted file mode 100644 index 7c13793a4936d21d621548c512ca88cfbf914716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49697 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 diff --git a/dbrepo-search-service/lib/dbrepo-1.8.0-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.8.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..86bf040fdef558afb682d4aa0d41e2cbf4958787 GIT binary patch literal 88162 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≀rW;DlsxaORk-=Roq6-IYrZGs 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 MU}*JWWME(b0It$gO#lD@ literal 0 HcmV?d00001 diff --git a/dbrepo-search-service/lib/dbrepo-1.8.0.tar.gz b/dbrepo-search-service/lib/dbrepo-1.8.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b0c21d94d641cdddaede16449367638abc78d5e8 GIT binary patch literal 97755 zcmb2|=HQ5#_A;I6e@aqOYC*oPp`L}FfnG^s5yP9kud8mmZPJ)^zluxe>`AqqVy<^p z-K#CCFAB*PFX~plcrwN2Uq%OmYL8<Bqr=Ib>GNOJJZJqjdG4xL+Ur;}yCx+U8HsV0 zl!u0ghl8-Wne^=ce~<n7a?4ED`p3IKyXZHQzn5ocm;2Wqe||gK`nL6b$@%-D52eev zr7=9%|J%&oTE8dp3D4VS-yYt3_wL}ggXg-B-Fx_t-#$lvUG4T?e_q;OD^2MC)BE;V z_pxiw%KOd#^MC*T@%^`l|EB#5Klk(P-ouCI-p&0Xf1>H_+`Vh}zVG>)dhY+jy>DB} z>UL(n-+#&fvE_;XbDOvPxgUG-|I!oxWqtqUA3k&2E+c2H%Kz<}|NX6xzx}-WTk@Iz z&3pIC{M=u>VefALPx4FbMGpVmzk56LxBJ(Op8q%3`hUGAbN;mxZ|>hZw(|1!y%+Sf z{&&l^^u3p~?p?d<WBFz2*$0o@xOwZ=>9r-&u8S9+J^TCj?>5f_sk(yAFO32oK9dT2 zvrYf}x}Ix4I}2+H>n^=4(>u4mCtQ5`vD>T5?(WFhzjKd8Wpz*g>yTGVim&c{v!|xp ze?{Zlw!$QSne&|tJ2z}RwlVU#ZIt<;=*y+O3v;X7SZsUWBuGdtOP8#@zd1rT`2qVe zi!HC&e5N1Reyp}8=DBZT<Y~^u2X@LmE<Vh|%k6k;TA{7sx;J*&Dblz2|9m{V_G9xy z{s-;MPyhU@$fyn!(zo|ey!PFF@`0T@dwKrf+sw=y(A4E;VtA&o<Td*_d6xd|lS7qv znJP0k++$G-`I5InV0m*}Lv8Xdx7oA&6b-*^Xl~h?JEJzsHGwguVbdN-d9DH$S?iPq zjSB)F>@Gdblk@Sg>XO$tq-(6c9pGy$KfLh$$7vOgkMDKnMOyPD9IklE-f}!crl;nC zglnkfgQT8omD;bbOuewe$~5fi{_V|HJn;;RTRbe}e#e<B-G4FL;6+5=_Cs-ktW3!n zRnK~Ro7)Qx7yh579A^G5KlhbgkKIAjmAP|`zVj6cZwV@85SE(v;hJQkH*-3}6`7lk z^0U{y%dd@BF0h->E*NKG(&tdcxX*yiz^75ROKjoE?Ay#rUt}dtMZA`pmvy54^YPbi zqOTrpPuRPx-|A1h$<E?6hTB9Xtm;3oz432YE3Bl{@cja(b5g}4V>8Z-h@drPtQUS6 zuqIaVPM%}N^`=plC1CD7zK%!of=4cFmw7SEbF&xEhR0v;8ct+VTlnzj#D`YS><bTD zwEa`q<^GL}Q-P<8^@@0Lztp3%8<<KB|FfSvYq8+FfzG<Mo&DXf>zTEe1e)*VtY$lG zSe9AG!&J|q|9kr~_K0pyrkIDV5tl@GT>WGI6(`JKQ|31f?=PRQec}r>pV<?eg-@wJ zsW8uP5MIFl!QxtCY?Y(``x#&OHp-fnw{Lqo!_7qU<=uZ*`R$gq9I~}h>G9-KT)tBC zLB%5JA|``NAM<z<A12NyU-o#`^>s7;&x%>K*u<6X&Fnc-eKf^eN|=ot5;gBhEM2g{ zImL7_M=5upN5bjZE1cNh_&+OPnXpi)qb#8~OwfCqo3gY*ebdP&zrLHgwhCJpyldzx z-`2>&d3~}>gTbcE1J&oFlS~9U;%6)J&2taF=p=FC?*Ut%Fhvb1y*b?9xBLAM6J|4r z5PZQfV`gLR^9un=;>?*pYz%W2Y>@AWzrZ4&R%`b0SitF<iUnMO_gND5c~53qWoh2W z9&jmn-n8RRe!NMS_vfjcJifC1&Y9zVvz|vOZ)jhp{Cv5s5%VLFCETUS8SLAv8!I2w zsvL@C-mWme;@O3DosQ)W0<6rN{k;~gd+FhMMI^{W_O|?rKzp~qbEP%UI@F&x%-JMm z<LO}cutjfbMMCmMLq)l5J5-gTK1t@T5ZiO!dEYwUE{>)9_!q<~Zae(Z^aP)tP0L-! zJFYW?t7^0a6ec~^-0ak2v~sso?m}rTjj5bApMG!UJtD)P`Kfn$(XD$C(`%!i=Ni`P zA2kZu6g#7#k^j(+zQqN(yN<YjXT0|L#1Dz;IltJ>G0lCkO-baECfC&z#b51TokCSo zr}HuY3$|!<DT!J0rpc3YZKjs@ET@MmJ#P|MbQfIMnJgXZF~3Ab|6rTEsr=@!C2N-o z?_Jk9Q9?Z9ircQn-rMr+OP+E*n(#!`T)AGgb9u<*zn%h$_reeMUzl3(<je7Y7A+^O zO`7{PelexWa!x+YH&?np#eRcQpP-=GWZ}Swwey+x`Z~{F-TU>6h~JItn{Fqu`I%Oh zFfFQ)QEQOe-f(6s?;jSm#lDkdCR}^C!c*eb{{F`L7?#`L8}IqVE<U*0*IuooOzK#F zMwsG_<eRmLk&@xb%VI3or|G3_$z0~0D!paNLctRbf=m{ZMcvC7CE71|Z}{L=#xh0l z4f~?=Ti?lUF}1mWd%;Bhg~xvsGq0KVfKA-*-;t8VCyyy?csQN8?e5(B?vC>=J*)ZK z&Tuq~JL`aqw4(fSmAOLC7k@Op!m7ozxGzRnBG!&^&dgQ3FFDP1zLd_+d*&VKbF7Ff zsm)6L<{`F>aOnl+YFu~i555RlILo%Hpy}WwWg#^o1&K|pfoCN)?#o)t{>;jxEc@Qg zl&7368M1Hr*)pCt3T=oL*#9Pef<~Rd#>R<74brFXXsH+~SGB1mB&#f#wRmFpY2W+J zj_O*A-#l9JHTE)N)#go6&l|d~boj+;n%mCUo0!4IclMkk!zK4M89DAR>}nr{AC}T- zu08)uO7Mt$gvzB=%d<{$EppCjJ-t<T!TFv&7DX~gZ24L*l=3b%KJamR_Cf&_(N9}s zrkvQBs4>G_ZJ(Oraq)MdOE)aZmHm;p!;$51-j~0IxBTCj_w32s@vPROOzF+4?E40) z3?jlOv}Y?QigvTeyku#sI5GX!s=525=5)T8Ceg1Lx#|Ls@zF<fG<?)HN<1}o)iJpu z^H|G2BGkwFfymK|!h4e14kc`UurR^SGd6?wdZ(B$Yc=oVOV@0jd6{fY)V(&TE)_W8 z=zhb@ureg!>BR{PZgLzrrtqYr|H7ii{rj$*_?T)O{LpgJnsw8hTm+6rIp0oOZ1W*D zLfG)HUdr{0vtq)pM))5;kZInbzv%ciX@fO<C4#Nf@_wDVs#q5!YwBsQ5-#+A_LUV4 zm1_^C^hu|BJ+|Vy{{GBLVFm7kpALSU;D6(l;gti6J0|P&=03Xgx2+>_bJ?Q_zoniW z=u2q2+In}5?!(Md1_@Q`<&4u9M4hh`wrReNcz!3=ePhPW4D+j|$xRU^L6>{K_wH0M z`rz4hWyjNFOO|IePuN^zl;L<f!F=MJoMWsLgJKRf`InjanXGPe^6s;b|M4(j{rvb6 z>*H@rXVlDBT4e5L&ByGU$J=MO+eC1JVQ|otr5`WN67u#JK6YVCM(@fQ=gz5UbEyjd z-4kUTvtnXOg6u-QE2l4nW~<FUG_yoCt=TN*Hcz4D((0F$qNdRY4VV_VGx-KTSdp<- zL*((Q4Fc`|*K&WBnEdjy)w>3xIgOKyR~Y3_Ve{Gkp8c!IRNutcnQ?mi%uX!0q+l3) zqM<=lL0TunV1wC)$-<Uqa=)G@9PDXp%{`>FrTTPOqQ?G9Dc6q8?qT0HWtyK|g!77{ z+EE&XB|q*cb((hme75wKfiCxc_8s>wS_WmiE;y$dlBRY=@~g81$6o&}^PIl7rQV!p zD#x|i^q8U3h7DimOPpKcqs+vu&Ne}@*l6N*u4_JL_&APv{!4B-d3*Z_m5EWI6K;B) zt4d=~k%_+*kf6Lr-s;qgNyQhkdLwsAitQ<So0=oJF>T9UrTPhtzOlZu8Fj_fExiTr zTB|P?+S<OrG=H9x!q#Zf%ZDz#a*H>bdFh0^;r5=Gl`3IO8yRmdKgxHXGa)-Pm9>rc z@mlsMlO>Lu?HL#BYd#&H6?j`=;=f+cOI=syM9z}dzFxXir?zEA$rFR%_fg;N&Tle# zoF=w#r6Est)68|#Zq%lHJ^z<O`{Z5eOZwOCqNhCEvUlNA*;Rs0x-!jH9J!~{q#Z4I zw<tbrm{EFAW{HFAPL*Aarm}|rTFwhZO}sh(%|5k9o*%rLSibd2Zm3=Q<W}>0R+$D3 z5jKyGq`=LKb?2+3AMwe{b?4wbZ+>OQPo-^!XB2;(UE<mtr*FN(dA{9$PK!dhv{u&3 zTs^N(y*@I1W#ix9Hy-YGUva@%LOA55$&v*>{wn7AE1Nl_Zm|A!!O>2n=wjo%TT|-8 z&ZrsY#Ym^DU~pS`xUKL}%a)QuzPB4cYTuaeFuijQi_q2AoY4m^osym&;l*=7<I*G7 z%7d@64*a;oFS;u9i0E9lld7xYr0!1NcyR5)cy5<}Rj*IIh*>MGA00kd+wo4k_1){@ z`MZy;UwiuWwaV?6_ZjKwea-#Z9q#t}kNM-}=YDd|u;#nX_^;*O#elCz6n7?N<^`EH zpYYG(vNUaU)tlHQ=HeK2gvoIC+;^F~`9kdPznHUs*PA*2Z`fteFMoY3^7p47rU^Hz zZd$%AsaF=Oy83e7_Vp1z9J;rETvp1-{O#M8(#$=T)jyv-T6K1d?rq(Y!gR(D@{9rP zWwIIRZELw6zhP1q|FQUh<L5b6HVp3$DIKZzdX)7q=vgk0^M=k1yPaaJ6+ORQcyC=a z^Gu7?{dCp*HTy2kiaTR;uli!c{iY=mFRvJ`mz{2Q-g-qPuR;Bujt>dB2b8DJncJYe zW{YWf_l=WGY+WVO8`JOa;ERZ_-5oZ4_ua2Ew8N|FmVK(8D#`WYa{1hBqZb@IrN6kJ zsO4rfI>ga3q3rnP=j@Z`8Gdc_lQc|O=iIQ<y`k-z%q;UldAn<3ii}zo3Nkl$Y+v`* z?r;m!;c2<53m6aA?AoDtTv}8}sy45|eAjB`ZRvecF|V@jnEL6Jbk0iFOg{Fe^YO=n zSDvhTXShP_T_^XN4Y${wm-u$<``YT`S8Lnl9W{S1p4b`Zw1x9n$BzRgcM1<|nfQ|L z*gT^=56(1~rU!ZqM(h3f*>3PP7Ea*5=-_Yls6zVE%)F>_zT8QC6+hU{F!-?u-Z?Nk z-S|O!+r?Ll{T#G7PIga-_6p3N{OEeL$=%17O?O5{?6|A8=EA?V?~U~}Dy@=dzkO27 zx;r;vvJGRPyTq)x`)P9}49zvB*9kweu6~i2(OJ}CxM>$t`QiO#JH@-+O!F17&iJ`$ zt=J3xbK?8<6&<=!#;;=#_xt+}p(JllPlH9vuWfiG@4BU8-8N~Z+`N6dPJS`}Bv@Ap zEpE||w8|29^(=X+dFe*O@0P-|Pk3h39OFFy%=%)QLT2(!=7@D0q!J{fCD#=jOH5J` zI<|GmqFLu2D+KILy;IC%BpLQ}M?|XMm8x6$HMS3rwY|E)qPZYLtM_Mhue9mrz(<E9 zcGT82Rheq@^xfNjZ%?Dr+<KXZ0+Y5gsJv=v*MG6F`bS^D&gs>j5^>?1oaVL%9@)!z zXwA38Yb+ah`dh*muM7Lce7tP!1qN2e$#XgXX5U%5rP28M{k`$w-6CIn3UbW_&$t9l zUH@y#)RMz1=KY9sJ;t3;9AffM-n2RF^%fuAgL@eK7=+^=9Smomb?e%<w8C{Q!V{j) zf8wU0`%02YL4Cm@=|^m$+GqbRaq0?=JZ63%HDlwZRPmWJl^6CLz4mJBTBop#_K*aj zq@$${eKOZIny&|jA1Sx1{J_14v*-DVzZHI#8{cc)H9mDRk?n8vosDT{7MKa&_kHmB zUWI!F^SsX3Yu`iW7<VpRJM+<-;Oopzy;@=u45x4X-|O4)m4l0E*}fgWV`hBpJ3f7( zij=Cmr?7kU*WcHl=o%;MSsy%+rgEb;>VzhL<2{BcE4?JSZO?yuV3?l0Yr2t}exqEQ zK?dt5oe%7@?jQP~wkh^z84v5hCn?t$&O2P+GuzNWW(Lawu{|j%^53UvRNMM|U%ioQ zef-@2k#qmY%>5rzyRYxFeSY09!MPgZ-nRcY@7=q5|8$H0J9qEjy5H*m=AQF2WoJ&4 zoGE=L%$g}VH~*~+&wl0RkH==!IQwiWGnHHP{L2Z8%1X}lz2=i&TszKSwPAPj$y?d= z8TkvAR=F$-JCUoKE?~Ck<KE<I-p%(77W?wtH7K0CT)y|9!_AZfW{k(4MRhN7>F+V# z5Oi?SFHz0&@_7k58>&;*yng@6?fcq~+FSPK{VDZ0FKrU_f35SM+fwG<X1C6$EV474 zJoU_8^Tz&<{L=aQ{)M`xTV|e5eiwJ-mUU--&AIC@4nFJXn47V?dE)$qSznHI#(dso zxXV;l+u-Cr*%^Kt93SWOUA$mozUDP=j_HvFA5T6zU}V1Ixb2-gH<m<PGT?jKCEpVv zGG*)hH=H^;YXb^`{<35xvFs_-T)js2F%#Eg^9EVJH`cemx^FSt&E(bR{P@L*8^&fm z(+?coxG1)s#q5n>(pmnx7gHZvCWo_ItqgDGyU+5hpyS%Rl?Dw9O`aG2*mnEIy}r<$ z5(_5_X~zT}(G}apa9Xw}(Z;&r;Nj^x9|iI@r1kaeH(fbXc&pSMi?rDs(sxgCr19xR znioDl+{8Nl$?fnBMoedJa=C7;V)AZRj#_vlQRLs+otJOi_1h<FDS!6L=FZl2U+X?u zUMMy36lH6^&vV^RZG&3LFL#>>(SP@eUXHVUl)Z{K=EB;we^uS%*2MDs&|JFj^@h2j zRgT(|%GaFx{i^13>iUhlBUdN)Fg#yldbCI9-yE6T7c({$>Yh0lzlO2wJ&UF2i;F2w z1g7`jSaU<fRp5xV<C&&Ui%z7Sjc`ssU@bFc(Wehp!sqAwd8&WFZ^5#d9<KQ4-ya?_ zTYafn@aliEL1RJ=Phy9=$oF=>e7&6upWKpqd!}*9?~XlZs%5$Y9qj(-vpssg@$&zU zQv%mc+20c6pR0Olqi@~ijvH)ICw3nE(O~>d)JNj?VZnz-H$*Oe#M6FEb;64oy*l0R zOs-7cYHIh)_idtR+SwE3dsgh!^AJ9Gnl0a7{^wVz4Wf^-q#jQA)qA4tM8ylnALebz zuG?Rz@%;H+a8`;zfo)@9vb*goKmOMttj%9!R`1NqkJK+Ki<8Owv*GJue(CDy_I7D~ zHg@}*H{Z6`OMEF`|ND0J@7G@!P2R93HRp9f^@m0EJIXgC&bDTku4eyzTl)I$=DEH5 z_LhH0D$m}K%lED8_94%!cUDO+{M>%`&f2vT%~xdcZg~IW=atvL72HxQOJ@8Kx!(3$ zm+w!eiPW*VFZ*)Eu0N~pb9H=Qv58yircuw^=41cP9sIU1anGjC_G8!GzMj4LE$pnp zzxV&kH(UPM|6f1**o~Wc4wcE-zd3x(**<=~x&FeLZ$4+=JTu*F9Bj;PdDg-CeOcy} zUjJj?_yms1^6&j%J6q^@WAD6E9`D$T&t3T;smxPz@RQ-QXQ@9$4xCKT?SJ_Cg*x{I z{p&IEKkE3N_c+)t%*tICKbz4<DCy6{s}t@j*X7r(E4a5(#&g#7-mVmdiWtv62i5uE z+9z@&+WP~S_BDTLZQjn-EAULl>a~67ea{o`v*)Pv+VOJDp29u5zb7dCjZNv@f<tn` z*=O?%w!JLpcy|9nkL|e}PD3e$x3et1cJxkQb@ZG#<7M%*U7|ThZ!Nu0WUci3f%BU7 zfSEr}6b8&%?_<6tTi!va+~)DE{=D9Ol9&G3$lg`5Gm3l>bmDP-=cFG8{;^2SI{Hv( zva!Dj58Dd$@=a<oFC?zLxW9St+kGz!{qG-<c%*n$@TgVLSBcHc(`FtPZ`$>KBbULM zH|lS1cC^2@>~+`}V>mZC+F-8lr3=UYGj;3snB99|rqOzDU2en1{^yfB_9rr&v1^?p zeYJereg5aB418v1CvN^J?)HN>r>faJX0_*p?6xiZhu9BGw_kX~w#(<e%<s4+F$R+j zLK?Zetqvj%Ec|(&-tKYzX2Z76`OcB*-aA_aJbK*CD`vBFbVv5YB<=3c&I)Flr^}`n z^~ikQn}^3vY~-kz-D=M0F@r7Rg+AMyzn!~0)3-(FU;G!~Cgl6BK$zYBPRdfJS**wZ z=vdA;q}%hHFQ?m;J>bsbhy5ugx3~5d*9cc?6c~J(lv{J--dy1ya=Hoc5?(qrR6G#< zlm5AZWqQ&qwq$W<GmRP^e-DZ5dildswlVkEY+hgcKiR`QxS-|6Je3o|Np=D(@=^@1 znfa4g-@f>zc2vMZa58W9^tY??)_+}gIeY&6Jv(2_DWCc*>C3IW8-I5^3M#!9w^jdq zbb9Wx16MwquU)-5USH3D#-*V1>u(*;*I#JT_3Z1`Yd6p5zxepNd$mzQ>Q8g==>c{B z9~8J(&p6;J+V@y#{{Krm-|WksTl9eEg_UrL)0!y16WiMU%$BYT2-IMha_hs5f<jHN zNxKU#8`v#4p6mB}rv1YW*M7vC<oQ2bEgO=pvDIHNE_9DefvM1&$ZZ@p;gfy~vDIbt z1z5#jWa_*o-!oHL;BI#I|4#2`j)yC*f6}@0%}noL$OdN9lS=A7XADHx_if+#`|!bQ z-N$lGO0w%)Lr>n{!Tx;x>>tdxY+pL8-Zgo-%j^VYnRjoVnC<%XZQZB+YroZp{k$JG zf6m|er^{YHS#wt+>hzueH?8j6yyf|<-rB+<;_ZK($D4~zue-BJd;6PHy1Vf(PZyqE zS7WgH$N$hj|2KF2x3~E7u>GyLw*H6h&;CCRyPACF|IK&xw`_0N$K3tD<<|e`lmD;& zyZ>r)&d>W&|Ll@p_Z`dl^y7E^@88wzoqzW?-(7q4ufO-t4@+0cd$C*16M1<5aA(b* z_W?g|9NlHMO~K6FuX*mR<%b{a(U804RL^zV@d6){eZ=I~53`L+ew|?qPOTK3HTC`K zv>Wb?A>6(1SC=#&KK6~TZuwKo>Vk&-?K7tSWIGl5D(B_BE7LFCy!XhU>FS3KoPV=g zCO++7d`s%rKSTHCq+iObcI`VS6r8}u`L$2IMB+!|ysLK8wol4kz9|1t#@?3!K@4u( zU))T2z8EDoZBu+UA<0keS!B{rm4B`d?`4c{ZwyI4$El;YO<f{`;dWiIqOJX@`Dgxy zZu1B|HYZ~SvybAzhEsYeySGHJwJNVli(&ugZvEo!uL`pc50zit{ZhwRzt6sSHTv0& z)}Ytx?wiNf?7ep)gUfSD2A6!QS?jw+Rc_J^W@>ilox1mHIrQ)DP1?~JJJ%)o(Z*{N z;=JE{R@r@6UOk)Bulu4%+sO>6=StJFdp!6m+b3}R+FkKn_-m-UkiN*eTivGfT#vu_ z`XR12ZoSm4cM8c~sS9Ez9*#M=e!?5~x|3_-LT?15Zk>Pid{0v3-gT1F^^5i0H`#pK zweYK;*RRB8fBur^q1uMW)jgEfmgsJl6=G$5yTCbQYxB}j>vIbG=e=WId*#B{p2*Ng ze?1>965h_SyyEsI%iFxC&F6hI@sl?!aqZwZUf`O$Lv4kQ+qMZu?)1j2^mbdJId8e{ z@ek8B?h*Vkg=x+Ai}M6FU-9fQ*JUq0(712$o(G=C&LpTBp45D-(A;48uCTeuY>T1$ zE_LaUO*3qtM@TfVR;Nl`H#l$i>CJ1o-A#_qN+wOxXtU)~Uc1n3lY!D<uZhdN_Jz$o zsw5Pw#$J3RW7G2)_jS##9a#4K&$5;uA3ll~e&h1-shyD+9K!y3z0a;6JRK+3{}ND7 zx)~W7>iFzaWcZrJFAu3jI`k%cUN!#|D>`%AOcAcqOTlNK$gKC@A8GvWV!E4gzS7w{ ztF|q?x}-0YUn)Q5^2ffb%~?4GX>F#r)y?jinu>MJKN_*;$(nV?maJm)S<S)o@}?e} z@Jh{t@?pV8XMDXWygBwmad1ti@84zLWK%Zh`_9S`FkkbrKqM%{C5>HbN+wUj`akyC z|IeTLzxh{<?7#V&?=Q~i{5OB^+UCPk{->vl{{L(8Z@#9TykuJCYxA}P>b!Dm8@3xC zIB!4Q-@~_Mi@(QS?YF{KzjxmLJFUiP(|-Q%oF|tR)jHkQk9%|NbFKNN#+fzdTyK(U z%{$%{e?P6!WVg1R^>~7yoY+mjiS4Pg)Sb*eDfqWIr5eubu%EvFVRnJU2?^UvjW!<o zKckZFO5gqNV52_mdZ%c?CZpxWrf>5-c1ra$uMH`^{@vZy%6!T(Z-cO$(C7^ddbhsl zpZB$?>}%xO|KYFyU;S18b!PS7^^eX?-|+AL-J3V<Z}_eMzdh{rf7NyWg-`$9Vcjt8 zOJB_9eREvOZtRQ@c0JOV9o8p*;K}<Z7v26%n!i<Sz2WW5(?;$a9{E)B>1_4+cU~y3 z)w^tWPwks%vzryAHX)af1y?BkKYMM<`ach5@qPHPJbhXBv-!E5Q4M)(Zk<oIo)L5K zSHzav|3nt@KHt={e&aFYoU>L=GP48|F7IMqEIj>O>ElU(z0-FjMHW8Zf2EGSc#=w{ z!4Ydu=8N?<{-!To>-uH$SFK(=@y7)DRomEi6dd{OG=KSV*Uoucj=NeH1z&sIw0vs8 zU%RVECzY%#n0`7$-22susZo4tTpg^+CZb=BV+?tc8lBU`!h0Mh>8@uHeeyUbo@c-0 z(_=kvs*9C`OxHjE9g?!!_-9DUTATS?>qT$<Eo7KbxAb$7nd~On2bD3qo<@4f&YZ!t zUU%^f_5~|;*oEso`SCTOWOcyzFIk^oy$aFIf71{@xp}#u;}(+}lD1`)@_O6MKIkZ~ z5&b&Jw6{e5gTS5k9qt~y2b-M=XIM7|KDzb&?#x(6PaCb88Qgar`3pX!h<HEfKXR&= z_2kW|WwVwnlk$)W+_Q&S-BkX0(Ss#^?#E;-SRYz-KAs%RTq^Oh%U}YpX=2XAEmJc; zT5j_F<|-!8bbHhK<K|Z*_Bys+X?tl^f1`p?Yu=jlNi*g*KAkCKcbx5G_cXDGn}4wJ z-(-2)y0BYRpj}_|?Axom`8_rk?icUaAASFk-ul7^pYl~y4k<s56|KK^kNaD*xUh}n z?Uem_nX%kYFZfS8zi5HiuQL9lttpqoeXczyyj@ZHC|0pf>d+gDOYO0y?&_thZ`$e9 zOnrG|mF~%I)+;S`yjq=!zj@B@4=MVQ6d=g_X=d%uMXoKX-IoeBK1;gX#2aV#Uj4RU z^WT}ZnoOE4XVZJH3tzDGpTe#`^M&#MZ%Ylh{I=XzS$FYHeq?U-J{^89Jx{fyr!_9F zjmv&qlW6+-`rC!x<p)*Wu84RoOgEjZz4>7Ak^5^m@3x#{-*Nd`p&sA0_*-cV*Iqu4 zh>pL;-FZ=b`Nx}U&+be9YQ8?w`bN9N)y-B47v?M#o@1dpceCmSwdPw1n_N!rkN6xv zWmiU6ex_m2Wh?O;7cD+a>3JBxD(8^tO?ja<-yijJ6HGtKD@M<j`s~mD*y()!Wa9}_ zX88UK_qe6@`!H+L<bPLNzWrUB&nK&-bkf~~<KOZOf2PZ-ox5{peq8ZZ&48)pOhQPq zle65^`<f?anoL=lxnZ8fq^~~|J{xvSjr2Ave5YM3Z}7YS>lKM(y{10-t)fn@D}p03 z_EmGAk7Mhzt(fnt>$QyaneNrIDk5fw^X4owOcsBc^l#F^8@-_pu|mtlPrJLZuljK! zYRd$ryL{K$wk>0dXm~W&;PPY(u2d&ZOM%`lH*U7x9KHq1uY8!Z@Oq=(>q+yIl>$O? zTS^{!ujl7jymIsAt)lXwJg1t!rB<fA%6c{-%db7F>DN}alJgr4WCc$D3^<y$)lt=V zj*{F7hNbO^t+^W$ErMj-w>Z|Oe0|pa;L52homMLxw)eg|>TkMNcaM%*nuFl<#=X-X z8C8UJo!+qS<Hf_T!xuVRd~>ezopPox_)N=<1I7tXJ~dyj8Z4BVbJS3g@9<=!M2)o- ze{L1eko1@7oV>1qcO{c_*)~<*{j#eAymfk?x)c|NCv|S~xf|fMUA#OZsM^U@YFhqg z#YIPwR8v1ZOZWSsf4)>nLB3#h=!V*+``i!S<-SeRo%-nTB;C3F9n;kACFe#@opj;b zrUggY*K*uCAYW~@X6BWX!M;yEcDMwdi&0CLDHpl=bm_rA&kt}O(s=6L6eQ_ye9@FW zA>GO(@{#X>U$;Dui+Q@v(~Y<n<bSB>kgKK5%GFLs95f4en*3d|r0!Kwp_`7j=<7qB zS3<Am6iu(1B3OF&=;^JA=hjB2eGvSAskztgo;Lpxq5Lb&A`GsToX+<i_^h*2ELQQk zy*TY{N%XA^fyrz9=Y&Mo-II`u3}xS7R-k_Q)iJl|_3QRtFuE$b<;YFv{Kt<z?I@lU z{M%7WbziMY>b8hk_h(mBTcq)&ZEwG<di%`Qe>PuFI)|t#e@lL~>|(@a-_o-e!zL(S zIZ-gvWTt^bXW-J4H<r{-<;d>RpCyrfD*yA`UZKg0HTPX9y_T1Ce`ibfrTtqcSyen& zw3_kc8MDa8uxVL6=X+<wC9gST8Xfi5rt8!7gsf_D?+wgJb5%clp2fUzn%qH!8-}aa zK7RadcHZxlUA6tMPL%A~V*fZ|kH+RZA!|kSv_dy7kB{_<**EKHYLbiCwqqfSKTYBG z?PT2^@bvwSNx_#EWZczU{pwrdxn0F_*Uki<<a(3*;_1$c>d%|~j-~Hzn6mg6!&B4M zHtl??1ZUUhPS1Gu@>##nmbnuiKXQ9#loYcq&>}Qt<#O>yOjFmpwH<d)PE?BFJGuG6 z0lBA*;WaNh0yaE}kPBA&^>WVfQ!m#{f3jzN!^Z;ScMInnzsXg;E=6|VNq0ll*YnLf zzP;YMes1Ru(FJ$I7WOb0c6Q}39M#-u)?jr=MX_VDPf4Xi<MOB}KZS2_Ez+Jn-_*+{ z+S`%m@20zFo6JrZTOL<D_qHtTtj*au&&)TgEZbTln||ZxtyrUt6^Co;eLt<6Su!JO z<B<p3Gha9z{`l#d;H$)GCV_RqTpADZ(zZUHr6Kpe##~Ke&KB+{Wu9qQ*O^>oF!iw8 zkZ_xWLm_^{hg;dR@7q7~<EhhiP1D&ZCm`*v==eIv=ZC6o(q&8Gl`b=XeyHBi@{eoo z{-;~rAKh{0?0Lb%bjEqbq&&UfA%~}gZOsX=5ox^7Im6rSug1|S$Npw7Y1zSi<l~Kx z?6*=scpa>2oA&4gzxWfy^hv%R_ExNyQv9-GKbd@${}med>Gq$>BSGIAROP39?a8-a zc+y~X@|^g{WhL(?&3UZ3!`mP%$Y5&0DWe#!#QzgmtrZV-HS$kdZ&KJMq$tJ^%D49K zlVv>4+R-A@j-KQDXfj<`ZE12$)Ku4k?F<JiJDyei?3l9ACRjl3;I}(wtBy~9d+mxZ zUtWXS-P5yJwSw0)ypWz{zRk$Ry|I|RcGt$Wac?Yq-}t^^@oijiMR@ZDj*g9!PnkLM zPgXr$u}}Z4^d3&Vj+tvq4lcQVJY;@Fs&uUTG_&N5=XrPS?P+y#sdzurMCaEbi)p4I z^6QUJd{~{ZqV<{V{-BGe`%GQd?O0~3-+e`6O7ipHQk<*JdtUI&$c<K9e^_9H%7qtZ zAC8-E|I?*^`h9&%*1;RevX)(Eq>~T-3P_oiE!5RCO_(+Gn{ueY{8X_pnaLaOeXN|u zJO5<x$6c#9ZfAr%y!tcuDF2J6+g1JFEWI_UbJmtq6&hcqRCjE+Bb2!yXrr0m`i`oK z*4rmc)f;%yMa23aGd|`!Q@3s5`FGb_Q;)LeJaZO16LaTz<M)F}_g7ry=a_MJ!k(#Z zv&8Rz3sNq8HY>_w?LyCO0@^e5&SY<RxMJ&ukD+h=>)kS#ZWO!yjAo_5X(5#s@8FtB z2fO<`J1?K9*e1d8DaGfQ@w}YMbu6cEeGF5}ob_k@mD#@kzF(X!+I?g5oZ{GpZ_V|} z6DQu#k3DzFiFwzHrLImXQ`_f>C47!N(Z9Pm=9<g1hX*hHU%#i)a<_q|c&_bn_UJ=D zwUnw#?K2O}UomsyEM>Fw`OD6%J2&ahs`H1+fB9N@Jk9Vojtb*Dd$Xx-b2+!UD8Id{ z%!irzmdz*iy|Pj(4aA>!-uc;OGtuUniSq_M>m+mG)~83`K5LqPuxrLy;T_Y$PCngG zB^P(7Na9n_XA7R|&laBb2@A3j*>&R4$M;jy4RYTs;j=rJcu}AwRl?Zy_*|Rc^AtC2 z;tC5p_&A#NNLIHohtRKoP0!XOn_3=Uf91PZZT;<6)r=bdJ-=9Petr7LglQJpGQqM_ zS|%3>-?d!e`}EguLzC)zGsEg+%9gGcU$Ht<VEUq!-HNuY^Td4ic%Ip7&}y6CQN2%T z-b!N&d+nLN_B-r1e_Od^?!?4wn~M|UEPu~Xs5MG<Zm4H+c4q%;)5Ftv@$(n{B^#sL zbQKqz%W&Ut;A@Y8;-rS1eGIw`E1s}*Ogr@3BQ@y!$K0s08~k$utwOoHe#!05R+qea z&$T7pG-=wio)diS&joGIO#5}LEZJzq$(_s#>l0Rfw_ox6rIgiVfxlOqbC{mDzs{&x zYIT(9_3O+otGN5J(OT2k_Ii49EPec0d79Jz#%ZfRi%PG%`Ozq+)-ZX^nNw_OI`Y!X zBiBA?`FQ*L-H#WzU)xN#|DwLA<bbQWQOMKVw=T1aPISA#-1Y1>?`&f;_sMR)Z>wW3 zY@X?Qec89aADPN;T*=DP+I(ZfGYt*Jozp7+TkhWN{DEo8>a3irSN2U`rjgC1W&G00 z+4p3<?^1^bm9i_vHmCoEtWC8t<2<w2O-HaL)m^)A!RhXhOALCdW}SzVYka$uM7zJt zcrIn}<K=0=*jx6mCbo&V{VJ~f^Vl(6%A!NP=h~s*Pc5zyPwp?t5%#*|>-k6UrT7J# zBlem_EiQk~&CUFFx7hg9yk}efp6T1Z+&5{_#;aR+)VQa<o{`;dcr9qjE<Qh_3(lWd zI*-lM+wHco+WCg8SJwp(@ufE}Ow-o9&-ivy!NuPJ?oCd<dUE@X1dkNdo%@vjdGmr# zn|=Q~{@L;7j{ND(%99^FJNN5jMVJ?-BXe`If9cX?slNYQmDR62_&muhes%S#Kb7mI z26q;IIy~3wGiR7tuiU=<yCzR{dQ%woo9C(O`fraNrYkJH%pjjzZy^8X^9`0Whdb@- zGvpd8KKswqn)!N5k!RNO%uO2<+;iVq);M<m=uEb0%>U?i^XR5PgNICkPQLg57=OJ` zo526q`u3{h{x@Hn{+U>q-L_qR#=X5;r+Ro!=WAP&6Q%3#-SE{n^NxF1AomHbKVM%h zc{+clFLT_yyeNmH$0gqWb63ri3{((Nwx2O2I^s(2g`bDTc7|-*zRkmKfA!g08U<ae zM6KK1D-{^FD%^T9<zr&f1QibX%&ikOj#W8r6nXs6wEO;rf)lrz+xh-$x@1`1KlwS% z+ooxH+T_pA{ySdFs5@4_zsA%r#gJY8iQ~LbNe}%sGp>1GW|N#S{pF!P=ee1Cjc#`- zFh82Il<TZO=Av`k15PyjD)B4hv6;8e{5$uQS({A7FG)5R%uMHwd1s@3p#IjIYn?Yf zr0Z#lF1PUrJNL9l&8}jB@vQA1w+I_uk2^Ab<IT<|dbd6;Dz;Buw!}*HOG5h=mr1QF zmd)xpn^^NdXWQO=T!9;Y&J_M}bC&;!DW~s!cbcV>f7{!!dcuOrN7`ZD-Lq~6X?Ti$ zDCJo8r{mungW^>l&*XVd%QXIGUHj?8pEG6QpFV3oO}}~h-y0V0a}BSYj3?`xR{uQb z%<|uvpYdEJSAOOvd)D`i+q3Lu@oBtW^+f$7muX|!gdU+O@*8!YtAA2)jIv!bb^p&L zJ*Os=&ofx~*7jqd!4aj<*2&AX^Opvw>$?0sQ?)uf$V>k4rI-JG=O4?e?=oOqS8d9v zTrH8G($Uo&?el1k;B$``n|M=gZ_Br@wsHC#DOuFBW2wMyHofOMy_a|&{*Y4lnas;E z?^KfiDlOZ#oT-;IPK)zqMw>>o<!4Mg{rFaL)nu{S2i-o(Z}*6QU2t;6h6A@_=KWKf z?s~(iSS}$c?P$??eciMFybjKO`sI>e+IyoTnRXs}@v{AFAuImw?D+e@*_UT=dTF4y zkm{bC<iPMPHnVodd@~W|Uo-2hYqZ*dRa;_r`<TC-Z{N0ZjjZaUX<=noj1EtHUUsc! zZ)3do)jNhWPIG^cTK253(I+GCU*EDXlMXGMKY8Cd$4tdvR@c4-yFZ%9urP%E={763 z3PW-JL$|$-Jvmv@Get_XzS((cWR2Y_+sbyaubaKS?-jgp`*GmojJO2H>X~-4);2}# zFLC~%r+#aFfp_z+@9AGYZaAlVLXWZSnNu>`;S@zNXCszZGv9p(&{PfXh&MDmxBL4p z57~=v%X3^VL@l4$F=w@X4|n*rAm-zTHm|zMWfqvYNqOQnl}Mr6YYjFAtv<W6G5+~l zvzzmG6=u(#CfjoM{8X_s(*i>*jkE±N%zn*Czgikg|`$Cvti@^D&j$nhspf5Y#( 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 A+W-In literal 0 HcmV?d00001 diff --git a/dbrepo-search-service/os-yml/update_database.yml b/dbrepo-search-service/os-yml/save_database.yml similarity index 75% rename from dbrepo-search-service/os-yml/update_database.yml rename to dbrepo-search-service/os-yml/save_database.yml index e9cd0d56f9..988cf421c6 100644 --- a/dbrepo-search-service/os-yml/update_database.yml +++ b/dbrepo-search-service/os-yml/save_database.yml @@ -1,8 +1,8 @@ tags: - database-endpoint -summary: Updates a database -operationId: update_database -description: Updates a database +summary: Saves a database +operationId: save_database +description: Save a database consumes: - application/json produces: @@ -18,18 +18,7 @@ security: - basicAuth: [ ] responses: 202: - description: Updated database successfully - content: - application/json: - schema: - required: - - id - type: object - properties: - id: - type: integer - example: 1 - implementation: int64 + description: Saved database successfully 400: description: "Invalid schema" content: diff --git a/dbrepo-search-service/tests/.testpickle b/dbrepo-search-service/tests/.testpickle deleted file mode 100644 index b9f0895c08ef7cdeb31e17c5174fcef1da26a5fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700 zcmZo*nX1kJ0ku;!dRPkbi%O>Suo@egn^{chVadoZE}7E9nUkNKm;+{)>fzC0NvaNW h1Cn(ZlB~msR2^jaoDN|{hO0=94>IhagU@lL5&-|a;9LLz diff --git a/dbrepo-search-service/tests/__init__.py b/dbrepo-search-service/tests/__init__.py index c68ce82814..e69de29bb2 100644 --- a/dbrepo-search-service/tests/__init__.py +++ b/dbrepo-search-service/tests/__init__.py @@ -1,3 +0,0 @@ -""" -This (empty) __init__.py file is necessary for importing this module in other python files -""" \ No newline at end of file diff --git a/dbrepo-search-service/tests/test_app.py b/dbrepo-search-service/tests/test_app.py index d2c8f2bd60..2cc9b3ba00 100644 --- a/dbrepo-search-service/tests/test_app.py +++ b/dbrepo-search-service/tests/test_app.py @@ -16,6 +16,7 @@ req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", exchange_name="dbrepo", is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief(id="7efe8b27-6cdc-4387-80e3-92ee28f4a7c5", name="MariaDB", internal_name="mariadb", @@ -58,17 +59,19 @@ class JwtTest(unittest.TestCase): def token(self, roles: [str], iat: int = int(time.time())): claims = { 'iat': iat, + 'uid': 'c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502', + 'preferred_username': 'foo', 'realm_access': { 'roles': roles } } - with open('tests/rsa/rs256.key', 'rb') as fh: + with open('./tests/rsa/rs256.key', 'rb') as fh: return jwt.JWT().encode(claims, jwt.jwk_from_pem(fh.read()), alg='RS256') def test_update_database_media_type_fails(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1', + response = test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}'}) self.assertEqual(415, response.status_code) @@ -81,13 +84,13 @@ class JwtTest(unittest.TestCase): def test_update_database_no_auth_fails(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1') + response = test_client.put(f'/api/search/database/{req.id}') self.assertEqual(401, response.status_code) def test_update_database_no_body_fails(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1', + response = test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}) self.assertEqual(400, response.status_code) @@ -95,7 +98,7 @@ class JwtTest(unittest.TestCase): def test_update_database_empty_body_fails(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1', + response = test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data={}) @@ -104,7 +107,7 @@ class JwtTest(unittest.TestCase): def test_update_database_malformed_body_fails(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1', + response = test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=dict({"id": 1})) @@ -113,7 +116,7 @@ class JwtTest(unittest.TestCase): def test_update_database_succeeds(self): with app.test_client() as test_client: # test - response = test_client.put('/api/search/database/1', + response = test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) @@ -140,27 +143,27 @@ class JwtTest(unittest.TestCase): def test_delete_database_no_role_fails(self): with app.test_client() as test_client: # test - response = test_client.delete('/api/search/database/1', + response = test_client.delete(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token([])}'}) self.assertEqual(403, response.status_code) def test_delete_database_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test - response = test_client.delete('/api/search/database/1', - headers={'Authorization': f'Bearer {self.token(["admin"])}'}) + response = test_client.delete(f'/api/search/database/{req.id}', + headers={'Authorization': f'Bearer {self.token(["system"])}'}) self.assertEqual(202, response.status_code) def test_delete_database_not_found_fails(self): with app.test_client() as test_client: # test - response = test_client.delete('/api/search/database/1', - headers={'Authorization': f'Bearer {self.token(["admin"])}'}) + response = test_client.delete(f'/api/search/database/{req.id}', + headers={'Authorization': f'Bearer {self.token(["system"])}'}) self.assertEqual(404, response.status_code) def test_get_fuzzy_search_succeeds(self): @@ -202,83 +205,83 @@ class JwtTest(unittest.TestCase): def test_post_general_search_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/database', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_table_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/table', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_column_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/column', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_identifier_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/identifier', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_concept_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/concept', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_unit_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/unit', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) def test_post_general_search_view_succeeds(self): with app.test_client() as test_client: # mock - test_client.put('/api/search/database/1', + test_client.put(f'/api/search/database/{req.id}', headers={'Authorization': f'Bearer {self.token(["update-search-index"])}', 'Content-Type': 'application/json'}, data=req.model_dump_json()) # test response = test_client.post('/api/search/view', headers={'Content-Type': 'application/json'}, - data=json.dumps({'id': 1})) + data=json.dumps({'id': '7b4942c3-6312-4f1d-bff9-cd24ea53ea05'})) self.assertEqual(200, response.status_code) diff --git a/dbrepo-search-service/tests/test_jwt.py b/dbrepo-search-service/tests/test_jwt.py deleted file mode 100644 index 6c2b169893..0000000000 --- a/dbrepo-search-service/tests/test_jwt.py +++ /dev/null @@ -1,98 +0,0 @@ -import time -import unittest - -import jwt -import requests_mock - -from app import verify_token, app, verify_password, get_user_roles -from clients.keycloak_client import User - - -class JwtTest(unittest.TestCase): - - def response(self, roles: [str]) -> dict: - return dict({ - 'client_id': 'username', - 'realm_access': { - 'roles': roles - } - }) - - def token(self, roles: [str], iat: int = int(time.time())) -> str: - claims = { - 'iat': iat, - 'realm_access': { - 'roles': roles - } - } - with open('tests/rsa/rs256.key', 'rb') as fh: - return jwt.JWT().encode(claims, jwt.jwk_from_pem(fh.read()), alg='RS256') - - def test_verify_token_no_token_fails(self): - with app.app_context(): - # test - user = verify_token(None) - self.assertFalse(user) - - def test_verify_token_empty_token_fails(self): - with app.app_context(): - # test - user = verify_token('') - self.assertFalse(user) - - def test_verify_token_malformed_token_fails(self): - with app.app_context(): - # test - user = verify_token('eyEYEY12345') - self.assertFalse(user) - - def test_verify_token_succeeds(self): - with app.app_context(): - with requests_mock.Mocker() as mock: - # mock - mock.post('http://auth-service:8080/api/auth/realms/dbrepo/protocol/openid-connect/token', - json=self.response([])) - # test - user = verify_token(self.token([])) - self.assertEqual([], user.roles) - - def test_verify_password_no_username_fails(self): - with app.app_context(): - # test - user = verify_password(None, 'pass') - self.assertFalse(user) - - def test_verify_password_empty_username_fails(self): - with app.app_context(): - # test - user = verify_password('', 'pass') - self.assertFalse(user) - - def test_verify_password_no_password_fails(self): - with app.app_context(): - # test - user = verify_password('username', None) - self.assertFalse(user) - - def test_verify_password_empty_password_fails(self): - with app.app_context(): - # test - user = verify_password('username', '') - self.assertFalse(user) - - def test_verify_password_succeeds(self): - with app.app_context(): - with requests_mock.Mocker() as mock: - # mock - mock.post('http://auth-service:8080/realms/dbrepo/protocol/openid-connect/token', - json=self.response([])) - # test - user = verify_password('username', 'password') - self.assertIsNotNone(user) - - def test_get_user_roles_succeeds(self): - with app.app_context(): - # test - roles: [str] = get_user_roles( - User(id='b98415d8-28bc-4472-84ff-3d09cc79aff6', username='username', roles=[])) - self.assertEqual([], roles) diff --git a/dbrepo-ui/components/database/DatabaseToolbar.vue b/dbrepo-ui/components/database/DatabaseToolbar.vue index 3e661cd754..0e69b9a91b 100644 --- a/dbrepo-ui/components/database/DatabaseToolbar.vue +++ b/dbrepo-ui/components/database/DatabaseToolbar.vue @@ -63,14 +63,15 @@ :text="$t('toolbars.database.info.tab')" :to="`/database/${$route.params.database_id}/info`" /> <v-tab - :text="$t('toolbars.database.tables.tab')" - :to="`/database/${$route.params.database_id}/table`" /> + :text="$t('toolbars.database.views.tab')" + :to="`/database/${$route.params.database_id}/view`" /> <v-tab + v-if="database && database.is_public" :text="$t('toolbars.database.subsets.tab')" :to="`/database/${$route.params.database_id}/subset`" /> <v-tab - :text="$t('toolbars.database.views.tab')" - :to="`/database/${$route.params.database_id}/view`" /> + :text="$t('toolbars.database.tables.tab')" + :to="`/database/${$route.params.database_id}/table`" /> <v-tab v-if="isOwner" :text="$t('toolbars.database.settings.tab')" diff --git a/dbrepo-ui/components/identifier/Citation.vue b/dbrepo-ui/components/identifier/Citation.vue index a52cd87159..570ab26790 100644 --- a/dbrepo-ui/components/identifier/Citation.vue +++ b/dbrepo-ui/components/identifier/Citation.vue @@ -15,7 +15,6 @@ :items="styles" item-title="title" item-value="value" - dense variant="outlined" single-line /> </v-col> diff --git a/dbrepo-ui/composables/axios-instance.ts b/dbrepo-ui/composables/axios-instance.ts index cd3737f2bf..31746818e9 100644 --- a/dbrepo-ui/composables/axios-instance.ts +++ b/dbrepo-ui/composables/axios-instance.ts @@ -2,6 +2,24 @@ import axios, {type AxiosInstance} from 'axios' let instance: AxiosInstance | null = null; +function tokenToExpiryDate(token: string): number { + if (!token) { + return -1 + } + const exp: number = jwtDecode<Token>(token).exp + if (exp) { + return exp * 1000 + } + return -1 +} + +function isExpiredToken(token: string): boolean { + if (!token) { + return false + } + return tokenToExpiryDate(token) < Date.now() +} + export const useAxiosInstance = () => { const config = useRuntimeConfig() if (!instance) { @@ -15,11 +33,14 @@ export const useAxiosInstance = () => { }, baseURL: config.public.api.client }); - instance.interceptors.request.use((config) => { - const { loggedIn, user } = useOidcAuth() + instance.interceptors.request.use(async (config) => { + const { loggedIn, user, canRefresh, refresh } = useOidcAuth() if (!loggedIn) { return config } + if (canRefresh) { + await refresh() + } const { accessToken } = user.value if (!accessToken) { return config diff --git a/dbrepo-ui/composables/database-service.ts b/dbrepo-ui/composables/database-service.ts index 0609373923..204f99dd35 100644 --- a/dbrepo-ui/composables/database-service.ts +++ b/dbrepo-ui/composables/database-service.ts @@ -66,7 +66,7 @@ export const useDatabaseService = (): any => { }); } - async function findOne(id: string, rawError: boolean = false): Promise<DatabaseDto | null> { + async function findOne(id: string, rawError: boolean = false): Promise<DatabaseDto> { const axios = useAxiosInstance(); console.debug('find database with id', id); return new Promise((resolve, reject) => { @@ -101,7 +101,7 @@ export const useDatabaseService = (): any => { }); } - async function updateVisibility(id: string, payload: DatabaseModifyVisibilityDto): Promise<DatabaseDto | null> { + async function updateVisibility(id: string, payload: DatabaseModifyVisibilityDto): Promise<DatabaseDto> { const axios = useAxiosInstance() console.debug('update database visibility for database with id', id); return new Promise((resolve, reject) => { @@ -117,7 +117,7 @@ export const useDatabaseService = (): any => { }); } - async function updateImage(id: string, payload: DatabaseModifyImageDto): Promise<DatabaseDto | null> { + async function updateImage(id: string, payload: DatabaseModifyImageDto): Promise<DatabaseDto> { const axios = useAxiosInstance() console.debug('update database image for database with id', id); return new Promise((resolve, reject) => { @@ -133,7 +133,7 @@ export const useDatabaseService = (): any => { }); } - async function updateOwner(id: string, payload: DatabaseTransferDto): Promise<DatabaseDto | null> { + async function updateOwner(id: string, payload: DatabaseTransferDto): Promise<DatabaseDto> { const axios = useAxiosInstance() console.debug('update database owner for database with id', id); return new Promise((resolve, reject) => { diff --git a/dbrepo-ui/dto/index.ts b/dbrepo-ui/dto/index.ts index 43c3ca2d19..3c21ce5abe 100644 --- a/dbrepo-ui/dto/index.ts +++ b/dbrepo-ui/dto/index.ts @@ -5,6 +5,7 @@ interface DatabaseDto { owner: UserDto; contact: UserDto; created: Date; + dashboard_uid: string; exchange_name: string; internal_name: string; is_public: boolean; diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 55a9692c2d..ddbef88b97 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -38,7 +38,9 @@ "help": "Help", "visibility": "Visibility", "update": "Update", - "you": "You" + "you": "You", + "enabled": "Enabled", + "disabled": "Disabled" }, "pages": { "identifier": { @@ -330,7 +332,7 @@ "title": "Owner" }, "creation": { - "title": "Creation" + "title": "Created" }, "import": { "title": "Import dataset into" @@ -595,6 +597,18 @@ "title": "Preview Image", "alt": "Database preview image representing the dataset" }, + "dashboard": { + "title": "Dashboard", + "text": "View", + "visibility": { + "label": "Managed Dashboard", + "hint": "Required, enables/disables the managed dashboard", + "warn": "Note that disabling the dashboard management also disables automatic visibility permission management of the dashboard!" + } + }, + "creation": { + "title": "Created" + }, "name": { "title": "Name" }, @@ -919,7 +933,7 @@ "title": "Owner" }, "creation": { - "title": "Creation" + "title": "Created" }, "visibility": { "title": "Visibility" @@ -1136,10 +1150,14 @@ "missing": "Failed to find access in metadata database" }, "axios": { - "connection": "Failed to contact backend", + "connection": "Failed to establish connection to backend", "malformed": "Malformed request", "timeout": "Connection timed out" }, + "dashboard": { + "connection": "Failed to establish connection with dashboard service", + "invalid": "Failed to perform action at dashboard service" + }, "concept": { "missing": "Failed to find concept in metadata database" }, diff --git a/dbrepo-ui/nuxt.config.ts b/dbrepo-ui/nuxt.config.ts index b3694d5b8b..f63592bf75 100644 --- a/dbrepo-ui/nuxt.config.ts +++ b/dbrepo-ui/nuxt.config.ts @@ -81,6 +81,9 @@ export default defineNuxtConfig({ contrast: 'flat', } }, + dashboard: { + url: 'http://localhost:3000' + }, api: { client: 'http://localhost', server: 'http://gateway-service', diff --git a/dbrepo-ui/pages/database/[database_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/info.vue index 9f2d426553..89583c5f4f 100644 --- a/dbrepo-ui/pages/database/[database_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/info.vue @@ -45,6 +45,16 @@ :max-width="maxWidth" :max-height="maxHeight" /> </v-list-item> + <v-list-item + v-if="canViewDashboard" + :title="$t('pages.database.dashboard.title')" + density="compact"> + <NuxtLink + target="_blank" + :href="`${config.public.dashboard.url}/d/${database.dashboard_uid}`"> + {{ $t('pages.database.dashboard.text') }} + </NuxtLink> + </v-list-item> <v-list-item :title="$t('pages.database.name.title')" density="compact"> @@ -108,6 +118,11 @@ :other-user="cacheUser" /> </div> </v-list-item> + <v-list-item + v-if="database.created" + :title="$t('pages.database.creation.title')"> + {{ formatUTC(database.created) }} + </v-list-item> </v-list> </v-card-text> </v-card> @@ -187,7 +202,7 @@ import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import Summary from '@/components/identifier/Summary.vue' import Select from '@/components/identifier/Select.vue' import UserBadge from '@/components/user/UserBadge.vue' -import { sizeToHumanLabel } from '@/utils' +import { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils' import { useCacheStore } from '@/stores/cache.js' export default { @@ -222,6 +237,10 @@ export default { tab () { return 0 }, + buttonVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal + }, description () { if (!this.identifier) { return '' @@ -341,6 +360,20 @@ export default { const userService = useUserService() return userService.hasReadAccess(this.access) }, + canViewDashboard () { + if (!this.database || !this.database.views) { + return false + } + if (!this.database.is_public && !this.database.is_schema_public) { + return false + } + return this.database.dashboard_uid + } + }, + methods: { + formatUTC (timestamp) { + return formatTimestampUTCLabel(timestamp) + } } } </script> diff --git a/dbrepo-ui/pages/database/[database_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/settings.vue index f20ce2be68..cefd76e639 100644 --- a/dbrepo-ui/pages/database/[database_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/settings.vue @@ -165,6 +165,34 @@ :hint="$t('pages.database.resource.schema.hint', { resource: 'database', schema: 'tables, views, subsets' })" /> </v-col> </v-row> + <v-row + v-if="isDashboardDisabled"> + <v-col + lg="8"> + <v-alert + border="start" + color="warning"> + {{ $t('pages.database.dashboard.visibility.warn') }} + </v-alert> + </v-col> + </v-row> + <v-row + dense> + <v-col + lg="4"> + <v-select + v-model="modifyVisibility.is_dashboard_enabled" + :items="dashboardOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.dashboard.visibility.label')" + :hint="$t('pages.database.dashboard.visibility.hint')" /> + </v-col> + </v-row> <v-row> <v-col> <v-btn @@ -275,7 +303,8 @@ export default { editVisibilityDialog: false, modifyVisibility: { is_public: null, - is_schema_public: null + is_schema_public: null, + is_dashboard_enabled: null, }, modifyOwner: { id: null @@ -291,6 +320,10 @@ export default { { title: this.$t('pages.database.resource.schema.enabled'), value: true }, { title: this.$t('pages.database.resource.schema.disabled'), value: false }, ], + dashboardOptions: [ + { title: this.$t('navigation.enabled'), value: true }, + { title: this.$t('navigation.disabled'), value: false }, + ], headers: [ { title: this.$t('pages.user.qualified-name.label'), @@ -356,7 +389,7 @@ export default { if (!this.modifyVisibility || !this.database) { return false } - return this.modifyVisibility.is_public === this.database.is_public && this.modifyVisibility.is_schema_public === this.database.is_schema_public + return this.modifyVisibility.is_public === this.database.is_public && this.modifyVisibility.is_schema_public === this.database.is_schema_public && this.modifyVisibility.is_dashboard_enabled === this.database.is_dashboard_enabled }, canModifyVisibility () { if (!this.roles) { @@ -416,6 +449,12 @@ export default { maxHeight () { return this.$config.public.database.image.height }, + isDashboardDisabled () { + if (!this.database) { + return false + } + return this.database.is_dashboard_enabled && !this.modifyVisibility.is_dashboard_enabled + }, uploadErrorMessages () { if (!this.file || this.file.size < 1_000_000) { return [] @@ -449,6 +488,7 @@ export default { } this.modifyVisibility.is_public = this.database.is_public this.modifyVisibility.is_schema_public = this.database.is_schema_public + this.modifyVisibility.is_dashboard_enabled = this.database.is_dashboard_enabled this.modifyOwner.id = this.database.owner.id }, methods: { @@ -463,7 +503,7 @@ export default { this.loading = true const databaseService = useDatabaseService() databaseService.updateVisibility(this.$route.params.database_id, this.modifyVisibility) - .then((database) => { + .then(() => { const toast = useToastInstance() toast.success(this.$t('success.database.visibility')) this.cacheStore.reloadDatabase() diff --git a/dbrepo-ui/pages/database/[database_id]/subset/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/index.vue index d7127d90af..dee6e18c64 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/index.vue @@ -46,7 +46,7 @@ export default { if (!this.database) { return false } - if (this.database.is_public || this.database.is_schema_public) { + if (this.database.is_public) { return true } if (!this.access) { diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue index 18662f55dd..808e725bc2 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue @@ -66,6 +66,11 @@ :user="table.owner" :other-user="cacheUser" /> </v-list-item> + <v-list-item + v-if="table.created" + :title="$t('pages.table.creation.title')"> + {{ formatUTC(table.created) }} + </v-list-item> </v-list> </v-card-text> </v-card> @@ -142,6 +147,7 @@ import Select from '@/components/identifier/Select.vue' import Summary from '@/components/identifier/Summary.vue' import UserBadge from '@/components/user/UserBadge.vue' import { useCacheStore } from '@/stores/cache.js' +import { formatTimestampUTCLabel } from '@/utils' export default { components: { @@ -276,6 +282,11 @@ export default { return this.$t('pages.table.connection.permissions.read') } } + }, + methods: { + formatUTC (timestamp) { + return formatTimestampUTCLabel(timestamp) + } } } </script> 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 b5266b79f2..aece8572cf 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 @@ -166,7 +166,7 @@ export default { if (!this.view) { return false } - if (this.view.is_public) { + if (this.database.is_public || this.database.is_schema_public) { return true } if (!this.access) { diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue index 41285c4d3b..6bd0864445 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue @@ -286,6 +286,7 @@ export default { const toast = useToastInstance() toast.success(this.$t('success.view.modified')) this.cacheStore.reloadView() + this.cacheStore.reloadDatabase() }) .catch(({code, message}) => { this.loading = false diff --git a/docker-compose.yml b/docker-compose.yml index e3c665faeb..34b09a02ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ volumes: search-db-data: identity-service-data: metric-db-data: - dashboard-service-data: + dashboard-ui-data: services: dbrepo-metadata-db: @@ -39,12 +39,13 @@ services: image: docker.io/bitnami/mariadb-galera:11.3.2-debian-12-r9 volumes: - data-db-data:/bitnami/mariadb - - "${SHARED_VOLUME:-/tmp}:/tmp" ports: - "3307:3306" environment: - MARIADB_ROOT_PASSWORD: "${DATA_DB_PASSWORD:-dbrepo}" MARIADB_GALERA_MARIABACKUP_PASSWORD: "${DATA_DB_BACKUP_PASSWORD:-dbrepobackup}" + MARIADB_PASSWORD: "${READONLY_PASSWORD:-user}" + MARIADB_ROOT_PASSWORD: "${DATA_DB_PASSWORD:-dbrepo}" + MARIADB_USER: "${READONLY_USERNAME:-user}" healthcheck: test: mysqladmin ping --user=root --password="${DATA_DB_PASSWORD:-dbrepo}" --silent interval: 10s @@ -129,10 +130,13 @@ services: METADATA_DB: "${METADATA_DB:-dbrepo}" METADATA_DB_PASSWORD: "${METADATA_DB_PASSWORD:-dbrepo}" METADATA_USERNAME: "root" + READONLY_USERNAME: "${READONLY_USERNAME:-user}" SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" depends_on: dbrepo-auth-service: condition: service_healthy + dbrepo-gateway-service: + condition: service_healthy dbrepo-metadata-db: condition: service_healthy logging: @@ -148,8 +152,6 @@ services: network: host ports: - "9099:8080" - volumes: - - "${SHARED_VOLUME:-/tmp}:/tmp" environment: ADMIN_EMAIL: "${ADMIN_EMAIL:-noreply@localhost}" ANALYSE_SERVICE_ENDPOINT: "${ANALYSE_SERVICE_ENDPOINT:-http://analyse-service:8080}" @@ -162,12 +164,13 @@ services: BROKER_EXCHANGE_NAME: ${BROKER_EXCHANGE_NAME:-dbrepo} BROKER_QUEUE_NAME: ${BROKER_QUEUE_NAME:-dbrepo} BROKER_HOST: "${BROKER_ENDPOINT:-broker-service}" - BROKER_PASSWORD: ${BROKER_PASSWORD:-admin} + BROKER_PASSWORD: ${SYSTEM_PASSWORD:-admin} BROKER_PORT: ${BROKER_PORT:-5672} BROKER_SERVICE_ENDPOINT: ${BROKER_SERVICE_ENDPOINT:-http://broker-service:15672} - BROKER_USERNAME: ${BROKER_USERNAME:-admin} + BROKER_USERNAME: ${SYSTEM_USERNAME:-admin} BROKER_VIRTUALHOST: "${BROKER_VIRTUALHOST:-dbrepo}" CROSSREF_ENDPOINT: "${CROSSREF_ENDPOINT:-http://data.crossref.org}" + DASHBOARD_SERVICE_ENDPOINT: "${DASHBOARD_SERVICE_ENDPOINT:-http://dashboard-service:8080}" DATA_SERVICE_ENDPOINT: ${DATA_SERVICE_ENDPOINT:-http://data-service:8080} DELETED_RECORD: "${DELETED_RECORD:-persistent}" GRANULARITY: "${GRANULARITY:-YYYY-MM-DDThh:mm:ssZ}" @@ -201,6 +204,10 @@ services: condition: service_healthy dbrepo-data-service: condition: service_healthy + dbrepo-dashboard-service: + condition: service_healthy + dbrepo-search-service: + condition: service_healthy dbrepo-metadata-db: condition: service_healthy logging: @@ -215,7 +222,7 @@ services: context: ./dbrepo-analyse-service network: host ports: - - "5000:8080" + - "4050:8080" environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -229,8 +236,6 @@ services: METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" - volumes: - - "${SHARED_FILESYSTEM:-/tmp}:/tmp" healthcheck: test: curl -sSL localhost:8080/health | grep 'UP' || exit 1 interval: 10s @@ -303,7 +308,7 @@ services: context: ./dbrepo-search-service network: host ports: - - "4000:8080" + - "4060:8080" environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -313,8 +318,8 @@ services: METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} OPENSEARCH_HOST: ${OPENSEARCH_HOST:-search-db} OPENSEARCH_PORT: ${OPENSEARCH_PORT:-9200} - OPENSEARCH_USERNAME: ${SEARCH_DB_USERNAME:-admin} - OPENSEARCH_PASSWORD: ${SEARCH_DB_PASSWORD:-admin} + OPENSEARCH_USERNAME: ${SYSTEM_USERNAME:-admin} + OPENSEARCH_PASSWORD: ${SYSTEM_PASSWORD:-admin} SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: @@ -322,6 +327,8 @@ services: interval: 10s timeout: 5s retries: 12 + logging: + driver: json-file dbrepo-ui: restart: "no" @@ -336,7 +343,7 @@ services: network: host environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" - NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://localhost}" + NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://gateway-service}" NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL: "${BASE_URL:-http://localhost}/realms/dbrepo" NUXT_OIDC_PROVIDERS_KEYCLOAK_AUTHORIZATION_URL: "${BASE_URL:-http://localhost}/realms/dbrepo/protocol/openid-connect/auth" NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID: "${AUTH_SERVICE_CLIENT:-dbrepo-client}" @@ -350,7 +357,7 @@ services: dbrepo-search-service: condition: service_healthy healthcheck: - test: curl -fsSL http://127.0.0.1:3000 && curl -fsSL http://127.0.0.1:3000/health + test: curl -fsSL 127.0.0.1:3000 && curl -fsSL 127.0.0.1:3000/health interval: 10s timeout: 5s retries: 12 @@ -368,6 +375,11 @@ services: - "80:8080" volumes: - ./dbrepo-gateway-service/dbrepo.conf:/etc/nginx/conf.d/default.conf + healthcheck: + test: lsof -i TCP:80 || exit 1 + interval: 10s + timeout: 5s + retries: 12 depends_on: dbrepo-analyse-service: condition: service_healthy @@ -395,8 +407,8 @@ services: environment: LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" - LDAP_USERS: "${SYSTEM_USERNAME:-admin}" - LDAP_PASSWORDS: "${SYSTEM_PASSWORD:-admin}" + LDAP_USERS: "${SYSTEM_USERNAME:-admin},${READONLY_USERNAME:-user}" + LDAP_PASSWORDS: "${SYSTEM_PASSWORD:-admin},${READONLY_PASSWORD:-user}" LDAP_GROUP: "${ADMIN_GROUP:-system}" LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" LDAP_ADMIN_DN: "${IDENTITY_SERVICE_ADMIN_DN:-cn=admin,dc=dbrepo,dc=at}" @@ -422,8 +434,8 @@ services: METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} OPENSEARCH_HOST: ${OPENSEARCH_HOST:-search-db} OPENSEARCH_PORT: ${OPENSEARCH_PORT:-9200} - OPENSEARCH_USERNAME: ${SEARCH_DB_USERNAME:-admin} - OPENSEARCH_PASSWORD: ${SEARCH_DB_PASSWORD:-admin} + OPENSEARCH_USERNAME: ${SYSTEM_USERNAME:-admin} + OPENSEARCH_PASSWORD: ${SYSTEM_PASSWORD:-admin} SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" depends_on: @@ -434,6 +446,29 @@ services: logging: driver: json-file + dbrepo-dashboard-service-init: + restart: "no" + init: true + container_name: dbrepo-dashboard-service-init + hostname: search-dashboard-init + image: dbrepo-dashboard-service-init:latest + build: + context: ./dbrepo-dashboard-service/init + network: host + environment: + LOG_LEVEL: ${LOG_LEVEL:-info} + DASHBOARD_UI_ENDPOINT: "${DASHBOARD_UI_ENDPOINT:-http://dashboard-ui:3000}" + METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" + depends_on: + dbrepo-dashboard-ui: + condition: service_healthy + dbrepo-metadata-service: + condition: service_healthy + logging: + driver: json-file + dbrepo-storage-service: restart: "no" container_name: dbrepo-storage-service @@ -461,8 +496,6 @@ services: volumes: - ./dbrepo-metric-db/prometheus.yml:/etc/prometheus/prometheus.yml - metric-db-data:/opt/bitnami/prometheus/data - ports: - - 9090:9090 healthcheck: test: promtool check healthy interval: 10s @@ -471,35 +504,6 @@ services: logging: driver: json-file - dbrepo-dashboard-service: - restart: "no" - container_name: dbrepo-dashboard-service - hostname: dashboard-service - image: dbrepo-dashboard-service:latest - build: - context: ./dbrepo-dashboard-service - network: host - ports: - - "3000:3000" - volumes: - - dashboard-service-data:/opt/bitnami/grafana/data - environment: - GF_SERVER_DOMAIN: "dashboard-service" - GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: "true" - LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" - LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" - LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" - healthcheck: - test: curl -fsSL --head http://127.0.0.1:3000 - interval: 10s - timeout: 5s - retries: 12 - depends_on: - dbrepo-metric-db: - condition: service_started - logging: - driver: json-file - dbrepo-storage-service-init: restart: "no" init: true @@ -530,8 +534,6 @@ services: network: host ports: - "9093:8080" - volumes: - - "${SHARED_VOLUME:-/tmp}:/tmp" environment: AUTH_SERVICE_ADMIN: "${AUTH_SERVICE_ADMIN:-admin}" AUTH_SERVICE_ADMIN_PASSWORD: "${AUTH_SERVICE_ADMIN_PASSWORD:-admin}" @@ -555,16 +557,12 @@ services: GRANT_DEFAULT_WRITE: "${GRANT_DEFAULT_WRITE:-SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" LOG_LEVEL: ${LOG_LEVEL:-info} - MIN_CONCURRENT_CONSUMERS: ${MIN_CONCURRENT_CONSUMERS:-1} - MAX_CONCURRENT_CONSUMERS: ${MAX_CONCURRENT_CONSUMERS:-5} QUEUE_NAME: ${QUEUE_NAME:-dbrepo} REQUEUE_REJECTED: ${REQUEUE_REJECTED:-false} ROUTING_KEY: "${ROUTING_KEY:-dbrepo.#}" S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}" S3_BUCKET: "${S3_BUCKET:-dbrepo}" S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}" - S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}" - S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" SPARK_USER: "${COMPUTE_SERVICE_USERNAME:-spark}" SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" @@ -579,3 +577,65 @@ services: condition: service_healthy logging: driver: json-file + + dbrepo-dashboard-ui: + restart: "no" + container_name: dbrepo-dashboard-ui + hostname: dashboard-ui + image: dbrepo-dashboard-ui:latest + build: + context: ./dbrepo-dashboard-ui + network: host + ports: + - "3000:3000" + volumes: + - dashboard-ui-data:/opt/bitnami/grafana/data + environment: + BASE_URL: "${BASE_URL:-http://localhost}" + GF_INSTALL_PLUGINS: "yesoreyeram-infinity-datasource" + GF_SERVER_DOMAIN: "dashboard-service" + GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: "true" + LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" + LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" + LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" + healthcheck: + test: curl -fsSL --head 127.0.0.1:3000 + interval: 10s + timeout: 5s + retries: 12 + depends_on: + dbrepo-metric-db: + condition: service_started + extra_hosts: + - "localhost:host-gateway" + logging: + driver: json-file + + dbrepo-dashboard-service: + restart: "no" + container_name: dbrepo-dashboard-service + hostname: dashboard-service + image: dbrepo-dashboard-service:latest + build: + context: ./dbrepo-dashboard-service + network: host + ports: + - "4070:8080" + environment: + AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} + AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} + AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} + BASE_URL: "${BASE_URL:-http://localhost}" + DASHBOARD_UI_ENDPOINT: "${DASHBOARD_UI_ENDPOINT:-http://dashboard-ui:3000}" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" + healthcheck: + test: curl -fsSL --head 127.0.0.1:8080/health + interval: 10s + timeout: 5s + retries: 12 + depends_on: + dbrepo-metric-db: + condition: service_started + logging: + driver: json-file diff --git a/grafana/grafana.ini b/grafana/grafana.ini new file mode 100644 index 0000000000..df8b9eb1b4 --- /dev/null +++ b/grafana/grafana.ini @@ -0,0 +1,5 @@ +[server] +domain = grafana +root_url = http://grafana/grafana +serve_from_sub_path = true + diff --git a/helm/dbrepo/Chart.yaml b/helm/dbrepo/Chart.yaml index 1c5fa27f8c..44a31bde0d 100644 --- a/helm/dbrepo/Chart.yaml +++ b/helm/dbrepo/Chart.yaml @@ -7,8 +7,8 @@ description: Helm Chart for installing DBRepo sources: - https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services type: application -version: "1.7.3" -appVersion: "1.7.3" +version: "1.8.0" +appVersion: "1.8.0" keywords: - dbrepo maintainers: diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index ba2f383668..8b251feba2 100644 --- a/helm/dbrepo/README.md +++ b/helm/dbrepo/README.md @@ -11,7 +11,7 @@ sample [ for your deployment and update the variables, especially `hostname`. ```bash -helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" --values ./values.yaml --version "1.7.3" +helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" --values ./values.yaml --version "1.8.0" ``` ## Prerequisites @@ -34,7 +34,7 @@ variable when you increase the available Pod memory for performance. To install the chart with the release name `my-release`: ```bash -helm install my-release "oci://oci://registry.datalab.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.7.3" +helm install my-release "oci://oci://registry.datalab.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.8.0" ``` The command deploys DBRepo on the Kubernetes cluster in the default configuration. The Parameters section lists the diff --git a/helm/dbrepo/files/01-setup-schema.sql b/helm/dbrepo/files/01-setup-schema.sql index 7e7978cad8..4ba9d70b17 100644 --- a/helm/dbrepo/files/01-setup-schema.sql +++ b/helm/dbrepo/files/01-setup-schema.sql @@ -52,6 +52,8 @@ CREATE TABLE IF NOT EXISTS `mdb_containers` privileged_username VARCHAR(255) NOT NULL, privileged_password VARCHAR(255) NOT NULL, quota INT, + readonly_username VARCHAR(255) NOT NULL, + readonly_password VARCHAR(255) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`image_id`) REFERENCES mdb_images (`id`) ) WITH SYSTEM VERSIONING; @@ -67,20 +69,22 @@ CREATE TABLE IF NOT EXISTS `mdb_licenses` CREATE TABLE IF NOT EXISTS `mdb_databases` ( - id VARCHAR(36) NOT NULL DEFAULT UUID(), - cid VARCHAR(36) NOT NULL, - name VARCHAR(255) NOT NULL, - internal_name VARCHAR(255) NOT NULL, - exchange_name VARCHAR(255) NOT NULL, - description TEXT, - engine VARCHAR(20), - is_public BOOLEAN NOT NULL DEFAULT TRUE, - is_schema_public BOOLEAN NOT NULL DEFAULT TRUE, - image LONGBLOB, - owned_by VARCHAR(36) NOT NULL, - contact_person VARCHAR(36) NOT NULL, - created TIMESTAMP NOT NULL DEFAULT NOW(), - last_modified TIMESTAMP, + id VARCHAR(36) NOT NULL DEFAULT UUID(), + cid VARCHAR(36) NOT NULL, + grafana_dashboard_uid character varying(255), + name VARCHAR(255) NOT NULL, + internal_name VARCHAR(255) NOT NULL, + exchange_name VARCHAR(255) NOT NULL, + description TEXT, + engine VARCHAR(20), + is_public BOOLEAN NOT NULL DEFAULT TRUE, + is_schema_public BOOLEAN NOT NULL DEFAULT TRUE, + is_dashboard_enabled BOOLEAN NOT NULL DEFAULT TRUE, + image LONGBLOB, + owned_by VARCHAR(36) NOT NULL, + contact_person VARCHAR(36) NOT NULL, + created TIMESTAMP NOT NULL DEFAULT NOW(), + last_modified TIMESTAMP, PRIMARY KEY (`id`), FOREIGN KEY (`cid`) REFERENCES mdb_containers (`id`), FOREIGN KEY (`owned_by`) REFERENCES mdb_users (`id`), @@ -291,7 +295,7 @@ CREATE TABLE IF NOT EXISTS `mdb_messages` type ENUM ('ERROR', 'WARNING', 'INFO') NOT NULL DEFAULT 'INFO', message TEXT NOT NULL, link TEXT NULL, - link_TEXT VARCHAR(255) NULL, + link_text VARCHAR(255) NULL, display_start TIMESTAMP NULL, display_end TIMESTAMP NULL, PRIMARY KEY (`id`) diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index 9fb1271c4361841c3d4061e536d23bc16b590d0e..5632a876e9fcc5546b307f7a795c6fbf2087d302 100644 GIT binary patch delta 647 zcmbR1Ki6L<z?+#xgn@yBgW+9LebkW-7T$?MO7*Ax4jTyUaX)4MgFQ#x#Me7dgfHOZ zgj0|AZ8X1<^(f?<+S2;|*-iqYOnlp}-}`v3;#zrvZ|l4t+*bKf(HlZk3QJxJaG1uw z;VxshjVgP1<<^%MH(XNKk1R6Y`pkRp!~W=yhqrY4_$IFGVd9$lWAZ{N?q%NXx2HL~ zXTQ7n)$O5XebEy;X|MTeYx80cPV2r_9ro@fm+5Y{uEn#{qLZ7a{d;EJSf?y<S^m@i zCpB?*#d3VNd~Kbw`>x-NQ{1o0*w!+rHZ0jVmDzt?@D<B1pEUfB1sYiKpBAc;__=O_ zNy72N=lfW)<!$Us79?DFVI%$R`-PV0_oQy`<^3%<zx#r-o#)Sb_HTive>QCu6XmU3 zKkL!e3kFMgKJU_Q&63`EaPO+<8$FF2o-5n-AK1u0>+s>qT$_ci<vM!~-IK{&ZngGV zr=I%r;<>2>)6OsVoTuuwG}3hSvk9RueN-3pf1elo_vxK{DHThXn=JenYcnNVSRCb} znkE*0;R8hk7Xt$a1H-!{#`?*d7*&|xCe=^A$*2paIho|Zv=);p^Sh+_$w5q7V7i{k z1Wa#Z@&d~<GoJ<1mzldk^yWmCIZPnNCU$O45WSgCphgg^qgQbjnATF7%mIu0$w!r} zz=BN5CLq<5EtPG-bfvN$m|mr93YLGQ3{fYq;sWNUsYHS0532-&X-U;wFx{yd3#MPH UI)Z6kwOwHKuhcTYbf~%q0G@my1poj5 delta 647 zcmbR1Ki6L<z?+#xgn@yBgCVG(AgXd{`Ll^aO7*w%9xDjcZhun$fSqA^>D?pwzTXqg zU%7hezki&#$8lpJOLF?>@2Y;US6y7SoBzN8nP)QR3i!`m6N%V2iGN%1(itmteDiD> zCr>=>tobfcK|RkV?~OxT%&I>f5#P2M7Nu_cl<6+9K6d#@!%bUVA4GWCMdz&$S@vnm zYn3m1CN};_sGoRlqVV^l5x;C+`aJjE7*(d&@k-%Z$`StuCO@yflgc{zasSVA3*tGh zUXB0s|K!h2`?Qa?Rf>D9{r-FJrqX~r?{zI%S2S!b-P(R&pZhyo*4jzSFRMt!9!X_o z_NlR7vFX9G!~K0O+49XcWeY?u%u<s7&VS+9^Lvrk|4V)s-WRa3z5Y{?+Wn3GH%{F? zXXzyOneq0g?N19cWS{%SYrcuvyOh~XHfOoR(Iv+|>U&5ndiJB>=8XeSPR!?8pSeLj z>I8R0%H}&y0z$$w#6I_Ih;oprG;@zhvAi~Q=KObie>}Uq^Sw#NH<w+#a+CgFG2-fM zy0_Iu`SKH9P(*MsFmNz11QjqAOy0z(!W>voF!?5<E|}(Il4A}kD449pqza~kn6$uj zJ(CHT-p1qwR>#bI7EE7e?goi(PGp(G1QOW9&dmuH;1j431TiM}D$WAaT1t~SU~xbB zsFD>}kV)ADq-(OJvMrddRMrEFuTnMz(~p!P>f}{i!2C3oD6qQ2D#2h{QZ*MW-l-Z3 X=D$>R1oL&(c7f?vY8hZURNVsr#}yvA diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index b82eb12cec..00336e82bb 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -122,7 +122,7 @@ authservice: setupJob: image: ## @skip authservice.setupJob.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.8.0 ## @param authservice.setupJob.resourcesPreset The container resource preset resourcesPreset: "nano" ## @param authservice.setupJob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) @@ -415,7 +415,7 @@ analyseservice: enabled: true image: ## @skip analyseservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.8.0 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param analyseservice.podSecurityContext.enabled Enable pods' Security Context @@ -476,7 +476,7 @@ metadataservice: enabled: true image: ## @skip metadataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.8.0 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param metadataservice.podSecurityContext.enabled Enable pods' Security Context @@ -573,7 +573,7 @@ dataservice: endpoint: http://data-service image: ## @skip dataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.8.0 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param dataservice.podSecurityContext.enabled Enable pods' Security Context @@ -659,7 +659,7 @@ searchservice: endpoint: http://search-service image: ## @skip searchservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.8.0 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param searchservice.podSecurityContext.enabled Enable pods' Security Context @@ -706,7 +706,7 @@ searchservice: init: image: ## @skip searchservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.8.0 ## @param searchservice.init.resourcesPreset The container resource preset resourcesPreset: "nano" ## @param searchservice.init.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) @@ -767,7 +767,7 @@ storageservice: init: image: ## @skip storageservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.8.0 s3: ## @param storageservice.init.s3.endpoint The S3-capable endpoint the microservice connects to. endpoint: http://storage-service-s3:8333 @@ -876,7 +876,7 @@ ui: enabled: true image: ## @skip ui.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.7.3 + name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.8.0 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param ui.podSecurityContext.enabled Enable pods' Security Context diff --git a/install.sh b/install.sh index b453e92ad6..8f6069b644 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash # preset -VERSION="1.7.3" +VERSION="1.8.0" MIN_CPU=8 MIN_RAM=4 MIN_MAP_COUNT=262144 diff --git a/lib/java/dbrepo-core/.gitignore b/lib/java/dbrepo-core/.gitignore new file mode 100644 index 0000000000..b425f09ad0 --- /dev/null +++ b/lib/java/dbrepo-core/.gitignore @@ -0,0 +1,35 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/lib/java/dbrepo-core/Dockerfile b/lib/java/dbrepo-core/Dockerfile new file mode 100644 index 0000000000..8a6348bbce --- /dev/null +++ b/lib/java/dbrepo-core/Dockerfile @@ -0,0 +1,12 @@ +###### FIRST STAGE ###### +FROM maven:3-amazoncorretto-17 AS build +LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" + +COPY ./pom.xml ./ + +RUN mvn dependency:go-offline + +COPY ./src/ ./src/ + +# Make sure it compiles +RUN mvn clean install -DskipTests \ No newline at end of file diff --git a/lib/java/dbrepo-core/pom.xml b/lib/java/dbrepo-core/pom.xml new file mode 100644 index 0000000000..87dd20ddc7 --- /dev/null +++ b/lib/java/dbrepo-core/pom.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>3.3.5</version> + </parent> + + <organization> + <name>TU Wien</name> + <url>https://www.tuwien.ac.at</url> + </organization> + + <groupId>at.ac.tuwien.ifs.dbrepo</groupId> + <artifactId>dbrepo-core</artifactId> + <name>dbrepo-core</name> + <version>1.8.0</version> + + <description>Core library for DBRepo</description> + + <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/</url> + <developers> + <developer> + <name>Martin Weise</name> + <email>martin.weise@tuwien.ac.at</email> + <organization>TU Wien</organization> + </developer> + </developers> + + <properties> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <lombok.version>1.18.36</lombok.version> + <keycloak.version>26.0.4</keycloak.version> + <mapstruct.version>1.6.3</mapstruct.version> + <spring-cloud.version>4.1.4</spring-cloud.version> + <jackson-datatype.version>2.15.0</jackson-datatype.version> + <springdoc-openapi.version>2.8.5</springdoc-openapi.version> + </properties> + + <dependencies><dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-bootstrap</artifactId> + <version>${spring-cloud.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-thymeleaf</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <!-- Mapping --> + <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>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>${mapstruct.version}</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + <version>${mapstruct.version}</version> + </dependency> + <!-- Api --> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + <scope>compile</scope> + </dependency> + <!-- Entities --> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>${jackson-datatype.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-hibernate6</artifactId> + <version>${jackson-datatype.version}</version> + </dependency> + <!-- Open API --> + <dependency> + <groupId>org.springdoc</groupId> + <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> + <version>${springdoc-openapi.version}</version> + </dependency> + <!-- Tests --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>${java.version}</source> + <target>${java.version}</target> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </path> + <!-- keep this order https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together#answer-65021876 --> + <path> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>${mapstruct.version}</version> + </path> + </annotationProcessorPaths> + </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> \ No newline at end of file diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/Serialize.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/Serialize.java new file mode 100644 index 0000000000..073a7c6699 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/Serialize.java @@ -0,0 +1,32 @@ +package at.ac.tuwien.ifs.dbrepo.core; + +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.hibernate6.Hibernate6Module; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import java.io.IOException; +import java.util.TimeZone; + +public class Serialize extends BaseTest { + + public static ObjectMapper objectMapper() { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new Jdk8Module()); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new Hibernate6Module()); /* lazy load mapping on REST endpoints */ + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + return objectMapper; + } + + public static void main(String[] args) throws IOException { +// objectMapper().writeValue(new File("./src/main/resources/database-1.json"), IDENTIFIER_1); + } + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/CacheableDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/CacheableDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/CacheableDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/CacheableDto.java index e947ece632..25d248dc4f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/CacheableDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/CacheableDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api; +package at.ac.tuwien.ifs.dbrepo.core.api; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ExportResourceDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ExportResourceDto.java index 5c5bf22005..fb7e87ec86 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ExportResourceDto.java @@ -1,4 +1,4 @@ -package at.tuwien; +package at.ac.tuwien.ifs.dbrepo.core.api; import lombok.*; import org.springframework.core.io.InputStreamResource; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ChannelDetailsDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ChannelDetailsDto.java index 03aeb19ab4..861602a156 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ChannelDetailsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ConsumerDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ConsumerDto.java index ad82492d7d..6d40bbe0ef 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ConsumerDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateExchangeDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateExchangeDto.java index dffe2c1e0e..57fccbcc2f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateExchangeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateUserDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateUserDto.java index 372ce8219b..4f5171daae 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateUserDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateVirtualHostDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateVirtualHostDto.java index b27ea597c2..841d4ee836 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/CreateVirtualHostDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ExchangeDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ExchangeDto.java index 403a04f00b..b42bef7e89 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/ExchangeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantExchangePermissionsDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantExchangePermissionsDto.java index 054548dbf0..64bc4c1990 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantExchangePermissionsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantVirtualHostPermissionsDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantVirtualHostPermissionsDto.java index 7e84edb80e..a49b3b5cb2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/GrantVirtualHostPermissionsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueBriefDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueBriefDto.java index 8a266043a1..7e9ee27d4b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueDto.java index acc2091d41..4ddd5e270d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/QueueDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/TopicPermissionDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/TopicPermissionDto.java index bdd806f71e..50fc100b13 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/TopicPermissionDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/UserDetailsDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/UserDetailsDto.java index a786456efd..07a9a1ef61 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/UserDetailsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/VirtualHostPermissionDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/VirtualHostPermissionDto.java index 0602c418da..0d1f1fe969 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/amqp/VirtualHostPermissionDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.amqp; +package at.ac.tuwien.ifs.dbrepo.core.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/CreateUserDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/CreateUserDto.java index 9742986ae0..eb0f1ed91a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/CreateUserDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.auth; +package at.ac.tuwien.ifs.dbrepo.core.api.auth; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/RealmAccessDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/RealmAccessDto.java index b759aff168..eb308018c4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/auth/RealmAccessDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.auth; +package at.ac.tuwien.ifs.dbrepo.core.api.auth; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerActionTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerActionTypeDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerActionTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerActionTypeDto.java index 9d641d510d..42c40ab7af 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerActionTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerActionTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container; +package at.ac.tuwien.ifs.dbrepo.core.api.container; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -12,7 +12,7 @@ public enum ContainerActionTypeDto { @JsonProperty("stop") STOP("stop"); - private String name; + private final String name; ContainerActionTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerBriefDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerBriefDto.java index 91253b12ba..ec879665e9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerBriefDto.java @@ -1,7 +1,6 @@ -package at.tuwien.api.container; +package at.ac.tuwien.ifs.dbrepo.core.api.container; -import at.tuwien.api.container.image.ImageBriefDto; -import com.fasterxml.jackson.annotation.JsonFormat; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageBriefDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -9,7 +8,6 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.UUID; @Getter diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerDto.java index 39eb011652..12589bc721 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/ContainerDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.container; +package at.ac.tuwien.ifs.dbrepo.core.api.container; -import at.tuwien.api.CacheableDto; -import at.tuwien.api.container.image.ImageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageDto; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/CreateContainerDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/CreateContainerDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/CreateContainerDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/CreateContainerDto.java index f2ac7df46a..77e7b026c7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/CreateContainerDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/CreateContainerDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container; +package at.ac.tuwien.ifs.dbrepo.core.api.container; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/DataTypeDto.java similarity index 97% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/DataTypeDto.java index 908f54a1b4..3455de43a9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/DataTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageBriefDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageBriefDto.java index ecbd050966..7239fdcfb7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageChangeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageChangeDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageChangeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageChangeDto.java index 520449d1de..0a73939c23 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageChangeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageChangeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageCreateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageCreateDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageCreateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageCreateDto.java index 4e9fea5b7c..cce376f5b7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageCreateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageCreateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.Parameter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageDto.java index ec4b0ad489..9d4049a173 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/ImageDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/OperatorDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/OperatorDto.java index 7eaee04810..38f39f5d82 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/container/image/OperatorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.container.image; +package at.ac.tuwien.ifs.dbrepo.core.api.container.image; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/CrossrefDto.java similarity index 74% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/CrossrefDto.java index 4a689a69ce..cd4afbb463 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/CrossrefDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.crossref; +package at.ac.tuwien.ifs.dbrepo.core.api.crossref; -import at.tuwien.api.crossref.label.CrossrefPrefLabelDto; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.label.CrossrefPrefLabelDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/form/CrossrefLiteralFormDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/form/CrossrefLiteralFormDto.java index b493cf89ff..060cb73885 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/form/CrossrefLiteralFormDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.crossref.form; +package at.ac.tuwien.ifs.dbrepo.core.api.crossref.form; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefLabelDto.java similarity index 75% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefLabelDto.java index 7bdaf0f931..5ee179f328 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefLabelDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.crossref.label; +package at.ac.tuwien.ifs.dbrepo.core.api.crossref.label; -import at.tuwien.api.crossref.form.CrossrefLiteralFormDto; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.form.CrossrefLiteralFormDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefPrefLabelDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefPrefLabelDto.java index a70c161d83..b64b9785f3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/crossref/label/CrossrefPrefLabelDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.crossref.label; +package at.ac.tuwien.ifs.dbrepo.core.api.crossref.label; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/AccessTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/AccessTypeDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/AccessTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/AccessTypeDto.java index fa0f6fea49..fb3f34957e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/AccessTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/AccessTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -17,7 +17,7 @@ public enum AccessTypeDto { @JsonProperty("write_all") WRITE_ALL("write_all"); - private String name; + private final String name; AccessTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateAccessDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateAccessDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateAccessDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateAccessDto.java index 965e10afd5..1ba876cc5e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateAccessDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateAccessDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateDatabaseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateDatabaseDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateDatabaseDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateDatabaseDto.java index e7fd08e771..9c9e708262 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateDatabaseDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateDatabaseDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateViewDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateViewDto.java index 9a9558470f..9ab87017a6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateViewDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; -import at.tuwien.api.database.query.SubsetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.SubsetDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseAccessDto.java similarity index 84% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseAccessDto.java index 7e393561f8..22a423f7d8 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseAccessDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseBriefDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseBriefDto.java index 4bb262b781..f84649ff63 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseBriefDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseDto.java similarity index 70% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseDto.java index 0c8c85a41c..0a8ca41eb5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseDto.java @@ -1,11 +1,11 @@ -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; -import at.tuwien.api.user.UserBriefDto; +package at.ac.tuwien.ifs.dbrepo.core.api.database; + +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -35,6 +35,10 @@ public class DatabaseDto extends CacheableDto { @Schema(example = "Air Quality") private String name; + @JsonProperty("dashboard_uid") + @Schema(example = "abcdef") + private String dashboardUid; + @NotBlank @JsonProperty("exchange_name") @Schema(example = "dbrepo") @@ -68,6 +72,11 @@ public class DatabaseDto extends CacheableDto { @Schema(example = "true") private Boolean isSchemaPublic; + @NotNull + @JsonProperty("is_dashboard_enabled") + @Schema(example = "true") + private Boolean isDashboardEnabled; + private ContainerDto container; @NotNull @@ -88,6 +97,11 @@ public class DatabaseDto extends CacheableDto { @JsonProperty("preview_image") private String previewImage; + @NotNull + @Schema(example = "2022-01-01 08:00:00.000") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC") + private Instant created; + /* lombok limitations prevent from convenient builder functions */ @JsonProperty("last_retrieved") diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyDashboardDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyDashboardDto.java new file mode 100644 index 0000000000..f4375d2ea3 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyDashboardDto.java @@ -0,0 +1,20 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.database; + +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class DatabaseModifyDashboardDto { + + @NotNull + private String uid; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyImageDto.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyImageDto.java index 5160ae76bf..f8907baa3a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyImageDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyVisibilityDto.java similarity index 76% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyVisibilityDto.java index e641deade2..818f546108 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseModifyVisibilityDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -26,4 +26,9 @@ public class DatabaseModifyVisibilityDto { @Schema(example = "true") private Boolean isSchemaPublic; + @NotNull + @JsonProperty("is_dashboard_enabled") + @Schema(example = "true") + private Boolean isDashboardEnabled; + } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseTransferDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseTransferDto.java index 5a8e6beb10..f0ba38ebaf 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/DatabaseTransferDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LanguageTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LanguageTypeDto.java similarity index 98% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LanguageTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LanguageTypeDto.java index fe57dd2444..c585a5f1ba 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LanguageTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LanguageTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -558,7 +558,7 @@ public enum LanguageTypeDto { @JsonProperty("zu") ZU("zu"); - private String value; + private final String value; LanguageTypeDto(String value) { this.value = value; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LicenseDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LicenseDto.java index a6384b3487..eada3be8ea 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LicenseDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LoadFileDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LoadFileDto.java index 65f5120d9b..d5c4242574 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/LoadFileDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewBriefDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewBriefDto.java index 47107ac54f..046aa97d10 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewColumnDto.java similarity index 76% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewColumnDto.java index 766fbfd321..c8744f4238 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewColumnDto.java @@ -1,6 +1,8 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; -import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.EnumDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.SetDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -9,6 +11,7 @@ import jakarta.validation.constraints.Size; import lombok.*; import lombok.extern.jackson.Jacksonized; +import java.util.List; import java.util.UUID; @Getter @@ -74,4 +77,10 @@ public class ViewColumnDto { @Schema(example = "false") private Boolean isNullAllowed; + @Schema(description = "enum values, only considered when type = ENUM") + private List<EnumDto> enums; + + @Schema(description = "enum values, only considered when type = ENUM") + private List<SetDto> sets; + } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewDto.java index 1e54da2978..76cf990c06 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewDto.java @@ -1,8 +1,9 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; -import at.tuwien.api.CacheableDto; -import at.tuwien.api.identifier.IdentifierDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -72,6 +73,11 @@ public class ViewDto extends CacheableDto { @NotNull private List<ViewColumnDto> columns; + @NotNull + @Schema(example = "2022-01-01 08:00:00.000") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC") + private Instant created; + /* lombok limitations prevent from convenient builder functions */ @JsonProperty("last_retrieved") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewUpdateDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewUpdateDto.java index 434ce0d9b6..01badab273 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ViewUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database; +package at.ac.tuwien.ifs.dbrepo.core.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/CreateDatabaseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/internal/CreateDatabaseDto.java similarity index 79% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/CreateDatabaseDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/internal/CreateDatabaseDto.java index 76ee117931..476adbbd9a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/CreateDatabaseDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/internal/CreateDatabaseDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.internal; +package at.ac.tuwien.ifs.dbrepo.core.api.database.internal; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -38,6 +38,16 @@ public class CreateDatabaseDto { @Schema(example = "mariadb") private String privilegedPassword; + @NotBlank + @JsonProperty("readonly_username") + @Schema(example = "user") + private String readonlyUsername; + + @NotBlank + @JsonProperty("readonly_password") + @Schema(example = "mariadb") + private String readonlyPassword; + @NotNull @JsonProperty("user_id") @Schema(example = "0e695ea5-9249-4a75-a77a-eeac3ec1c2c0") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExecuteStatementDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExecuteStatementDto.java index fbc8bfebe0..6973486230 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExecuteStatementDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExportDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExportDto.java index 36a13b3487..35f4fff473 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ExportDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterDto.java index 3fe8744661..2e6b1a03d7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterTypeDto.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterTypeDto.java index eb9c12f7b2..aab604117c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/FilterTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -15,7 +15,7 @@ public enum FilterTypeDto { @JsonProperty("and") AND("and"); - private String name; + private final String name; FilterTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ImportDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ImportDto.java index 20817e0176..4a0a04abd6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/ImportDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderDto.java index bb58ad4831..1412edf16a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderTypeDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderTypeDto.java index ee05a75e47..a7afcbcd5e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/OrderTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,7 +12,7 @@ public enum OrderTypeDto { @JsonProperty("desc") DESC("desc"); - private String name; + private final String name; OrderTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryBriefDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryBriefDto.java index c55a108cfc..24e3f60130 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryBriefDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryDto.java index 24915a3dd5..58568fa4c3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryDto.java @@ -1,8 +1,7 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryPersistDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryPersistDto.java index 5bc3ac2054..90012d7a03 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryPersistDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryTypeDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryTypeDto.java index 4df28733cd..e19dccf096 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/QueryTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,7 +12,7 @@ public enum QueryTypeDto { @JsonProperty("view") VIEW("view"); - private String name; + private final String name; QueryTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SaveStatementDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SaveStatementDto.java index 876dd5dfdd..aaefacf797 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SaveStatementDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SubsetDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SubsetDto.java index 6e8c238417..0b5975e05d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/query/SubsetDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.query; +package at.ac.tuwien.ifs.dbrepo.core.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/CreateTableDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/CreateTableDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/CreateTableDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/CreateTableDto.java index 15a798ee2d..af2c3a80cc 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/CreateTableDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/CreateTableDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/HistoryEventTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/HistoryEventTypeDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/HistoryEventTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/HistoryEventTypeDto.java index 83d8441752..90a216c124 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/HistoryEventTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/HistoryEventTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -14,7 +14,7 @@ public enum HistoryEventTypeDto { @JsonProperty("delete") DELETE("delete"); - private String name; + private final String name; HistoryEventTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/SortType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortType.java similarity index 76% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/SortType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortType.java index e101dfc9eb..841587f4b0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/SortType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortType.java @@ -1,4 +1,4 @@ -package at.tuwien; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonProperty; @@ -10,7 +10,7 @@ public enum SortType { @JsonProperty("desc") DESC("desc"); - private String type; + private final String type; SortType(String type) { this.type = type; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/SortTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortTypeDto.java similarity index 73% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/SortTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortTypeDto.java index 2964bb1496..0a7cbeeb4c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/SortTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/SortTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonProperty; @@ -10,7 +10,7 @@ public enum SortTypeDto { @JsonProperty("desc") DESC("desc"); - private String type; + private final String type; SortTypeDto(String type) { this.type = type; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableBriefDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableBriefDto.java index 3ba910b979..92540c2051 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableCreateRawQuery.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableCreateRawQuery.java index ec221ae5f0..8ba7b7ab62 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableCreateRawQuery.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableDto.java index 3dde709183..9cb2848e5b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableDto.java @@ -1,14 +1,11 @@ -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; -import at.tuwien.api.identifier.IdentifierDto; -import at.tuwien.api.user.UserBriefDto; -import com.fasterxml.jackson.annotation.JsonIgnore; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; + +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.ConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -112,6 +109,11 @@ public class TableDto extends CacheableDto { @NotNull private ConstraintsDto constraints; + @NotNull + @Schema(example = "2022-01-01 08:00:00.000") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC") + private Instant created; + /* lombok limitations prevent from convenient builder functions */ @JsonProperty("last_retrieved") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableHistoryDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableHistoryDto.java index e6ed667235..3b6d8df35f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableHistoryDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableInsertRawQuery.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableInsertRawQuery.java index de6ff7feb7..caab639414 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableInsertRawQuery.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableStatisticDto.java similarity index 67% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableStatisticDto.java index 6b5529a0a1..1b728df71c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableStatisticDto.java @@ -1,13 +1,13 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; -import at.tuwien.api.database.table.columns.ColumnStatisticDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnStatisticDto; 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.Map; +import java.util.List; @Getter @Setter @@ -19,9 +19,14 @@ import java.util.Map; @ToString public class TableStatisticDto { - @JsonProperty("rows") + @JsonProperty("total_rows") @Schema(example = "5") - private Long rows; + private Long totalRows; + + @NotNull + @JsonProperty("total_columns") + @Schema(example = "2") + private Long totalColumns; @JsonProperty("data_length") @Schema(example = "16384", description = "in bytes") @@ -36,5 +41,5 @@ public class TableStatisticDto { private Long avgRowLength; @NotNull - private Map<String, ColumnStatisticDto> columns; + private List<ColumnStatisticDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableUpdateDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableUpdateDto.java index d8db270053..f4fd37a374 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TableUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDeleteDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDeleteDto.java index f74ffb3d89..78d04b5361 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDeleteDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDto.java index 13dc2b9723..db1d917709 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleUpdateDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleUpdateDto.java index ab3f1ae875..eac3886de2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/TupleUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnBriefDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnBriefDto.java index 08ee40caa4..8ebc4f9e38 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnDto.java index 0df8efbf23..d5c7343694 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnDto.java @@ -1,9 +1,8 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; -import at.tuwien.api.database.table.columns.concepts.ConceptBriefDto; -import at.tuwien.api.database.table.columns.concepts.UnitBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.ConceptBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.UnitBriefDto; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -120,10 +119,10 @@ public class ColumnDto { @Schema(example = "false") private Boolean isNullAllowed; - @Parameter(description = "enum values, only considered when type = ENUM") + @Schema(description = "enum values, only considered when type = ENUM") private List<EnumDto> enums; - @Parameter(description = "enum values, only considered when type = ENUM") + @Schema(description = "enum values, only considered when type = ENUM") private List<SetDto> sets; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnStatisticDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnStatisticDto.java index a7d76a47b2..01f3e2b652 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnStatisticDto.java @@ -1,6 +1,7 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -17,6 +18,9 @@ import java.math.BigDecimal; @ToString public class ColumnStatisticDto { + @NotBlank + private String name; + @NotNull private BigDecimal mean; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnTypeDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnTypeDto.java index a963370829..fbe35b9c64 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/ColumnTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -99,7 +99,7 @@ public enum ColumnTypeDto { @JsonProperty("year") YEAR("year"); - private String type; + private final String type; ColumnTypeDto(String type) { this.type = type; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/CreateTableColumnDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/CreateTableColumnDto.java index 9733f64a16..b26ca9582a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/CreateTableColumnDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/EnumDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/EnumDto.java index 9038648513..3a5889324f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/EnumDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SetDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SetDto.java index 6986212592..cd0aa8c921 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SetDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SiUnitDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SiUnitDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SiUnitDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SiUnitDto.java index 70da894411..2de0da75ae 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SiUnitDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/SiUnitDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -27,7 +27,7 @@ public enum SiUnitDto { @JsonProperty("candela") CANDELA("candela"); - private String name; + private final String name; SiUnitDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java index 9c74981f14..26d921cf88 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptBriefDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptBriefDto.java index 160807e7aa..0540dfbba4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptDto.java index 1359556943..29d906e90f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptSaveDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptSaveDto.java index b61d911ef9..bdfebd73ff 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/ConceptSaveDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; import jakarta.validation.constraints.NotBlank; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitBriefDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitBriefDto.java index 789f3de150..47658b49cc 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitDto.java index ca3899f7cc..6af216e067 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitSaveDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitSaveDto.java index 530c7c8fbb..7a13c01521 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/columns/concepts/UnitSaveDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.columns.concepts; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts; import jakarta.validation.constraints.NotBlank; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/ConstraintsDto.java similarity index 64% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/ConstraintsDto.java index b9288b659b..35648bd768 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/ConstraintsDto.java @@ -1,8 +1,8 @@ -package at.tuwien.api.database.table.constraints; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary.PrimaryKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/CreateTableConstraintsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/CreateTableConstraintsDto.java similarity index 79% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/CreateTableConstraintsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/CreateTableConstraintsDto.java index 7b223372d2..b2bf3ed732 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/CreateTableConstraintsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/CreateTableConstraintsDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.database.table.constraints; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints; -import at.tuwien.api.database.table.constraints.foreign.CreateForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.CreateForeignKeyDto; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/CreateForeignKeyDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/CreateForeignKeyDto.java index 5e1d0a9f86..cfbba36281 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/CreateForeignKeyDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.constraints.foreign; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyBriefDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyBriefDto.java index 4acc205efd..307d57af01 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.constraints.foreign; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyDto.java index 94063c77dc..625156027a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyDto.java @@ -1,8 +1,6 @@ -package at.tuwien.api.database.table.constraints.foreign; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java similarity index 81% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java index 2423b92a62..4beab3e1ee 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.database.table.constraints.foreign; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ReferenceTypeDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ReferenceTypeDto.java index 239b95e7e9..a246740718 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/foreign/ReferenceTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.constraints.foreign; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/primary/PrimaryKeyDto.java similarity index 68% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/primary/PrimaryKeyDto.java index 59117a5795..74d55ead18 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/primary/PrimaryKeyDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database.table.constraints.primary; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/unique/UniqueDto.java similarity index 72% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/unique/UniqueDto.java index 64db6dfde0..6f1c613779 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/constraints/unique/UniqueDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database.table.constraints.unique; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/TableCreateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/internal/TableCreateDto.java similarity index 80% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/TableCreateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/internal/TableCreateDto.java index f8db928e8e..200bfef48f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/TableCreateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/table/internal/TableCreateDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.database.table.internal; +package at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteBody.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteBody.java similarity index 84% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteBody.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteBody.java index 8ef874acba..272484e84a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteBody.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteBody.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteData.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteData.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteData.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteData.java index 62b8ad411c..1209e36fd3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteData.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteData.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteError.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteError.java similarity index 84% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteError.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteError.java index dcbc312d31..872de43921 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/DataCiteError.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/DataCiteError.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteCreateDoi.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteCreateDoi.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteCreateDoi.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteCreateDoi.java index 24da7bc82a..27749b4b33 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteCreateDoi.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteCreateDoi.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoi.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoi.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoi.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoi.java index 5d3e0b2c1e..837f38143d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoi.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoi.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreator.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreator.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreator.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreator.java index 3d093adf74..a95a9dd121 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreator.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreator.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorAffiliation.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorAffiliation.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorAffiliation.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorAffiliation.java index a361452b96..b07a86eea3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorAffiliation.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorAffiliation.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java index 449c814171..a75f6fc333 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiCreatorNameIdentifier.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiEvent.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiEvent.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiEvent.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiEvent.java index 35b6c670da..5c753dd6b6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiEvent.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiEvent.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReference.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReference.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReference.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReference.java index 595c808a24..546094183c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReference.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReference.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java index 1bdc94605f..00fedaa15b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiFundingReferenceIdentifier.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRelatedIdentifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRelatedIdentifier.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRelatedIdentifier.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRelatedIdentifier.java index d446029eae..3e246944d9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRelatedIdentifier.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRelatedIdentifier.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRights.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRights.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRights.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRights.java index 4a53c7f7c5..0bef60756f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiRights.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiRights.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTitle.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTitle.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTitle.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTitle.java index a0358da69a..38114a19cd 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTitle.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTitle.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTypes.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTypes.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTypes.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTypes.java index 778853ce78..c69ece3ac0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteDoiTypes.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteDoiTypes.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteNameType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteNameType.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteNameType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteNameType.java index b9940ab5f4..c6e551e533 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/datacite/doi/DataCiteNameType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/datacite/doi/DataCiteNameType.java @@ -1,4 +1,4 @@ -package at.tuwien.api.datacite.doi; +package at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -12,7 +12,7 @@ public enum DataCiteNameType { @JsonProperty("Organizational") ORGANIZATIONAL("Organizational"); - private String name; + private final String name; DataCiteNameType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/error/ApiErrorDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/error/ApiErrorDto.java index bb271f5ed6..49ea5af60f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/error/ApiErrorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.error; +package at.ac.tuwien.ifs.dbrepo.core.api.error; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/file/UploadResponseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/file/UploadResponseDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/file/UploadResponseDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/file/UploadResponseDto.java index 3b1cdab223..6a8b9b818b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/file/UploadResponseDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/file/UploadResponseDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.file; +package at.ac.tuwien.ifs.dbrepo.core.api.file; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/AccessTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/AccessTypeDto.java new file mode 100644 index 0000000000..39447d8e73 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/AccessTypeDto.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema +public enum AccessTypeDto { + + @JsonProperty("proxy") + PROXY("proxy"); + + private final String name; + + AccessTypeDto(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardDto.java new file mode 100644 index 0000000000..6b7a879b5b --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardDto.java @@ -0,0 +1,39 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class CreateDashboardDto { + + @NotNull + @JsonProperty("database_name") + @Schema(example = "Some Database") + private String databaseName; + + @NotNull + @JsonProperty("is_public") + @Schema(example = "true") + private Boolean isPublic; + + @NotNull + @JsonProperty("is_schema_public") + @Schema(example = "true") + private Boolean isSchemaPublic; + + @NotBlank + @JsonProperty("owner_username") + @Schema(example = "foobar") + private String ownerUsername; +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardResponseDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardResponseDto.java new file mode 100644 index 0000000000..cc4bcfa40b --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/CreateDashboardResponseDto.java @@ -0,0 +1,25 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class CreateDashboardResponseDto { + + @NotNull + @Schema(example = "3") + private Long id; + + @NotNull + @Schema(example = "eeckcuwfsfbi8b") + private String uid; +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceDto.java new file mode 100644 index 0000000000..e670c99ff6 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceDto.java @@ -0,0 +1,80 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +@Jacksonized +@ToString +public class DatasourceDto { + + @NotNull + @Schema(example = "1") + private Long id; + + @NotNull + @Schema(example = "kLtEtcRGk") + private String uid; + + @NotNull + @Schema(example = "1") + private Long orgId; + + @NotNull + @Schema(example = "some_datasource") + private String name; + + @NotNull + @Schema(example = "plugins/logo.svg") + private String typeLogoUrl; + + @NotNull + @Schema(example = "PROXY") + private AccessTypeDto access; + + @Schema(example = "http://example.com") + private String url; + + @Schema(example = "s3cr3t") + private String password; + + @Schema(example = "user") + private String user; + + @Schema(example = "true") + private Boolean basicAuth; + + @Schema(example = "user") + private String basicAuthUser; + + @Schema(example = "s3cr3t") + private String basicAuthPassword; + + @Schema(example = "false") + private Boolean withCredentials; + + @Schema(example = "false") + private Boolean isDefault; + + @NotNull + @Schema(example = "true") + private Boolean readOnly; + + @NotNull + @Schema(example = "INFINITY") + private DatasourceTypeDto type; + + @NotNull + @Schema(example = "0") + private Integer version; + +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceTypeDto.java new file mode 100644 index 0000000000..e708ccf6a8 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/DatasourceTypeDto.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema +public enum DatasourceTypeDto { + + @JsonProperty("yesoreyeram-infinity-datasource") + INFINITY("yesoreyeram-infinity-datasource"); + + private final String name; + + DatasourceTypeDto(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/PermissionTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/PermissionTypeDto.java new file mode 100644 index 0000000000..f9561da037 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/PermissionTypeDto.java @@ -0,0 +1,33 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema +public enum PermissionTypeDto { + + @JsonProperty("View") + VIEW("View"), + + @JsonProperty("Editor") + EDITOR("Editor"), + + @JsonProperty("Admin") + ADMIN("Admin"), + + @JsonProperty("") + NONE(""); + + private final String name; + + PermissionTypeDto(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/UpdateDashboardAccessDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/UpdateDashboardAccessDto.java new file mode 100644 index 0000000000..08d755e111 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/grafana/UpdateDashboardAccessDto.java @@ -0,0 +1,21 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.grafana; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class UpdateDashboardAccessDto { + + @NotNull + @Schema(example = "View") + private PermissionTypeDto permission; +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/AffiliationIdentifierSchemeTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/AffiliationIdentifierSchemeTypeDto.java similarity index 67% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/AffiliationIdentifierSchemeTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/AffiliationIdentifierSchemeTypeDto.java index 3c089e6454..ba881921ac 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/AffiliationIdentifierSchemeTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/AffiliationIdentifierSchemeTypeDto.java @@ -1,5 +1,5 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import lombok.Getter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/BibliographyTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/BibliographyTypeDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/BibliographyTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/BibliographyTypeDto.java index 9da9afbc0b..d89935553c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/BibliographyTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/BibliographyTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -15,7 +15,7 @@ public enum BibliographyTypeDto { @JsonProperty("bibtex") BIBTEX("bibtex"); - private String name; + private final String name; BibliographyTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreateIdentifierDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreateIdentifierDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreateIdentifierDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreateIdentifierDto.java index 5f2e73fc07..286d04dc3b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreateIdentifierDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreateIdentifierDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; -import at.tuwien.api.database.LicenseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LicenseDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorBriefDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorBriefDto.java index 95b0d588f7..f5a1d94897 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorDto.java index 1382baec51..b98985c1c4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/CreatorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -7,7 +7,6 @@ import lombok.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.extern.jackson.Jacksonized; -import org.springframework.data.annotation.Id; import java.util.UUID; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/DescriptionTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/DescriptionTypeDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/DescriptionTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/DescriptionTypeDto.java index c98c0a1f33..7ddab32784 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/DescriptionTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/DescriptionTypeDto.java @@ -1,5 +1,5 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -25,7 +25,7 @@ public enum DescriptionTypeDto { @JsonProperty("Other") OTHER("Other"); - private String name; + private final String name; DescriptionTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierBriefDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierBriefDto.java index 0434d1b21f..74f60ab153 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDescriptionDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDescriptionDto.java index 32ff2455cc..e491fd6744 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDescriptionDto.java @@ -1,12 +1,11 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; 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 org.springframework.data.annotation.Id; import java.util.UUID; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDto.java index 0bc16d61cd..35293a6d9e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierDto.java @@ -1,8 +1,8 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; -import at.tuwien.api.database.LicenseDto; -import at.tuwien.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LicenseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderDto.java index 4184f2cf2a..741e1ac1ac 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -6,7 +6,6 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import org.springframework.data.annotation.Id; import java.util.UUID; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderTypeDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderTypeDto.java index 70a6d36f26..6682bac43a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierFunderTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -21,7 +21,7 @@ public enum IdentifierFunderTypeDto { @JsonProperty("Other") OTHER("Other"); - private String name; + private final String name; IdentifierFunderTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierSaveDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierSaveDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierSaveDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierSaveDto.java index f63c3ae79c..2054e84012 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierSaveDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierSaveDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; -import at.tuwien.api.database.LicenseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LicenseDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierStatusTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierStatusTypeDto.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierStatusTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierStatusTypeDto.java index 2c7f4527b1..655c670a35 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierStatusTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierStatusTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -12,7 +12,7 @@ public enum IdentifierStatusTypeDto { @JsonProperty("published") PUBLISHED("published"); - private String name; + private final String name; IdentifierStatusTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTitleDto.java similarity index 84% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTitleDto.java index d995527d88..829454134d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTitleDto.java @@ -1,12 +1,11 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; 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 org.springframework.data.annotation.Id; import java.util.UUID; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTypeDto.java similarity index 84% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTypeDto.java index 19660e324d..bca87f3cd8 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/IdentifierTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -18,7 +18,7 @@ public enum IdentifierTypeDto { @JsonProperty("view") VIEW("view"); - private String name; + private final String name; IdentifierTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/LinksDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/LinksDto.java similarity index 77% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/LinksDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/LinksDto.java index fcef2a6597..9b3461ea47 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/LinksDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/LinksDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -29,4 +29,8 @@ public class LinksDto { @Schema(example = "http://example.com") private String data; + @JsonProperty("dashboard_html") + @Schema(example = "http://example.com/d/defi2baxqawaod") + private String dashboardHtml; + } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameIdentifierSchemeTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameIdentifierSchemeTypeDto.java similarity index 68% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameIdentifierSchemeTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameIdentifierSchemeTypeDto.java index 3ea4c2d7f8..028abf15f2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameIdentifierSchemeTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameIdentifierSchemeTypeDto.java @@ -1,5 +1,5 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import lombok.Getter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameTypeDto.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameTypeDto.java index d9f2a16bf5..6de88e1bb1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/NameTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/NameTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -12,7 +12,7 @@ public enum NameTypeDto { @JsonProperty("Organizational") ORGANIZATIONAL("Organizational"); - private String name; + private final String name; NameTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedIdentifierDto.java similarity index 69% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedIdentifierDto.java index 7205bc6e0b..5aec478064 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedIdentifierDto.java @@ -1,17 +1,11 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.user.UserDto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import jakarta.validation.constraints.NotNull; import lombok.extern.jackson.Jacksonized; -import org.springframework.data.annotation.Id; -import java.time.Instant; import java.util.UUID; @Getter diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedTypeDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedTypeDto.java index 1e75513abc..76fabca029 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelatedTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -60,7 +60,7 @@ public enum RelatedTypeDto { @JsonProperty("w3id") W3ID("w3id"); - private String name; + private final String name; RelatedTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelationTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelationTypeDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelationTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelationTypeDto.java index fb43cc5b46..bc43f0c81e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelationTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/RelationTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -108,7 +108,7 @@ public enum RelationTypeDto { @JsonProperty("Obsoletes") OBSOLETES("Obsoletes"); - private String name; + private final String name; RelationTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierCreatorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierCreatorDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierCreatorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierCreatorDto.java index 0866a5cb3b..ce3d92480b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierCreatorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierCreatorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierDescriptionDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierDescriptionDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierDescriptionDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierDescriptionDto.java index bc1ad4f3df..0abfa73128 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierDescriptionDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierDescriptionDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierFunderDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierFunderDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierFunderDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierFunderDto.java index 1709c109b2..f877f45829 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierFunderDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierFunderDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierTitleDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierTitleDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierTitleDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierTitleDto.java index 07ebc35e2c..99a95c45d5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveIdentifierTitleDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveIdentifierTitleDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; -import at.tuwien.api.database.LanguageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.LanguageTypeDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveRelatedIdentifierDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveRelatedIdentifierDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveRelatedIdentifierDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveRelatedIdentifierDto.java index d22c8216e3..ccb47cac43 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/SaveRelatedIdentifierDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/SaveRelatedIdentifierDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/TitleTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/TitleTypeDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/TitleTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/TitleTypeDto.java index 72b30dd315..d1d5379a7e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/TitleTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/TitleTypeDto.java @@ -1,5 +1,5 @@ -package at.tuwien.api.identifier; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -19,7 +19,7 @@ public enum TitleTypeDto { @JsonProperty("Other") OTHER("Other"); - private String name; + private final String name; TitleTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdCreatorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdCreatorDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdCreatorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdCreatorDto.java index 0bde2d2968..8d983afb3d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdCreatorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdCreatorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier.ld; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdDatasetDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdDatasetDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdDatasetDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdDatasetDto.java index bab1deb2d1..e599f66d8c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/ld/LdDatasetDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/identifier/ld/LdDatasetDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.identifier.ld; +package at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialDto.java index 172b844e1b..71a279519d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialTypeDto.java similarity index 79% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialTypeDto.java index 4992f74cf9..71530c5edc 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/CredentialTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/CredentialTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -9,7 +9,7 @@ public enum CredentialTypeDto { @JsonProperty("password") PASSWORD("password"); - private String name; + private final String name; CredentialTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/ModifyUserDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/ModifyUserDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/ModifyUserDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/ModifyUserDto.java index 26d700e798..8ad43b34c2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/ModifyUserDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/ModifyUserDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/RoleRepresentationDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/RoleRepresentationDto.java index 8f7d795fdb..bc3137d421 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/RoleRepresentationDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/TokenDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/TokenDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/TokenDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/TokenDto.java index dcd14c4d2a..8cde17a095 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/TokenDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/TokenDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; -import at.tuwien.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UpdateCredentialsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UpdateCredentialsDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UpdateCredentialsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UpdateCredentialsDto.java index c8bac04d45..3994b1aaab 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UpdateCredentialsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UpdateCredentialsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserAttributesDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserAttributesDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserAttributesDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserAttributesDto.java index 50718bc803..0e7ab89f66 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserAttributesDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserAttributesDto.java @@ -1,12 +1,10 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.util.UUID; - @Getter @Setter @Builder diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateAttributesDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateAttributesDto.java index 6df8ce5e8f..e2357a4e94 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateAttributesDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateDto.java index 2a80811b62..b8879ae24e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserCreateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserIdAttributesDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserIdAttributesDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserIdAttributesDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserIdAttributesDto.java index 3155d75f02..0a34e5fe61 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserIdAttributesDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/keycloak/UserIdAttributesDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.keycloak; +package at.ac.tuwien.ifs.dbrepo.core.api.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ldap/UserDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ldap/UserDto.java index e6aec08226..f06844ef7d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ldap/UserDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.ldap; +package at.ac.tuwien.ifs.dbrepo.core.api.ldap; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageBriefDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageBriefDto.java index a11c70f621..72ca75913f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.api.maintenance; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageCreateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageCreateDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageCreateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageCreateDto.java index f7466d3e2c..3526258d80 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageCreateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageCreateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.api.maintenance; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageDto.java similarity index 96% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageDto.java index d344ccd6b4..9e2f094b69 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.api.maintenance; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageTypeDto.java similarity index 83% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageTypeDto.java index 8a867f5ea4..16e9b8a810 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.api.maintenance; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -15,7 +15,7 @@ public enum BannerMessageTypeDto { @JsonProperty("info") INFO("info"); - private String name; + private final String name; BannerMessageTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageUpdateDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageUpdateDto.java index f6aad1989e..4551adaa40 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/maintenance/BannerMessageUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.api.maintenance; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/OrcidDto.java similarity index 66% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/OrcidDto.java index c4ea89b005..e25b7240fa 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/OrcidDto.java @@ -1,7 +1,7 @@ -package at.tuwien.api.orcid; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid; -import at.tuwien.api.orcid.activities.OrcidActivitiesSummaryDto; -import at.tuwien.api.orcid.person.OrcidPersonDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.OrcidActivitiesSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.OrcidPersonDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/OrcidActivitiesSummaryDto.java similarity index 65% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/OrcidActivitiesSummaryDto.java index 625611abd2..3bd62fd915 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/OrcidActivitiesSummaryDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities; -import at.tuwien.api.orcid.activities.employments.OrcidEmploymentsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.OrcidEmploymentsDto; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/OrcidEmploymentsDto.java similarity index 66% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/OrcidEmploymentsDto.java index dea853b62b..fee281294b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/OrcidEmploymentsDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities.employments; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments; -import at.tuwien.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java similarity index 57% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java index a82a88869b..bbda576a4a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities.employments.affiliation; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation; -import at.tuwien.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java similarity index 63% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java index 984dc8a6d0..159e83a3a5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities.employments.affiliation.group; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.OrcidSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.OrcidSummaryDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java similarity index 69% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java index 1377a73dba..1dfd21700a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities.employments.affiliation.group.summary; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.OrcidOrganizationDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.OrcidOrganizationDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java similarity index 60% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java index 149af1b3e6..7146bcf175 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java similarity index 78% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java index c5ed53e37f..e8ea1dba39 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java new file mode 100644 index 0000000000..83169ad79c --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedSourceTypeDto.java @@ -0,0 +1,6 @@ +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated; + +public enum OrcidDisambiguatedSourceTypeDto { + RINGGOLD, + ROR +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/OrcidPersonDto.java similarity index 64% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/OrcidPersonDto.java index f7de2794d7..afb1d6d80f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/OrcidPersonDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.orcid.person; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.person; -import at.tuwien.api.orcid.person.name.OrcidNameDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name.OrcidNameDto; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidNameDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidNameDto.java index 44c2ac0e6b..2b638ff20a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidNameDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.orcid.person.name; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidValueDto.java similarity index 79% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidValueDto.java index 251a39c23c..bcfd0d3a16 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/orcid/person/name/OrcidValueDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.orcid.person.name; +package at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ror/RorDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ror/RorDto.java index 8e9407885c..19776bcf09 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/ror/RorDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.ror; +package at.ac.tuwien.ifs.dbrepo.core.api.ror; import lombok.*; import lombok.extern.jackson.Jacksonized; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/EntityDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/EntityDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/EntityDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/EntityDto.java index 5c1d6cc13a..a9f31f97f0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/EntityDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/EntityDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyBriefDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyBriefDto.java index 29d5116a70..81caa34ad1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyCreateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyCreateDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyCreateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyCreateDto.java index 1e2cf44167..aa11b34e55 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyCreateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyCreateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyDto.java index a3e7c46d01..afbb818e1b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyDto.java @@ -1,7 +1,5 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; -import at.tuwien.api.user.UserBriefDto; -import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -9,7 +7,6 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.UUID; @Getter diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyModifyDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyModifyDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyModifyDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyModifyDto.java index f003790922..b73891b342 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyModifyDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/OntologyModifyDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/TableColumnEntityDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/TableColumnEntityDto.java index f4a2147a29..1bb401e5ca 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/semantics/TableColumnEntityDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.semantics; +package at.ac.tuwien.ifs.dbrepo.core.api.semantics; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/ExchangeUpdatePermissionsDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/ExchangeUpdatePermissionsDto.java index f545f62041..3b775a2318 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/ExchangeUpdatePermissionsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/GrantedAuthorityDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/GrantedAuthorityDto.java index 07e0029a71..cabc0b1d07 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/GrantedAuthorityDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/RoleTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/RoleTypeDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/RoleTypeDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/RoleTypeDto.java index 4b2c877435..30f2cc2b8b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/RoleTypeDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/RoleTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -15,7 +15,7 @@ public enum RoleTypeDto { @JsonProperty("data_steward") ROLE_DATA_STEWARD("data_steward"); - private String name; + private final String name; RoleTypeDto(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserAttributesDto.java similarity index 94% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserAttributesDto.java index ef9bae650c..b365199cec 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserAttributesDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserBriefDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserBriefDto.java index d245bbaf4c..58a2aeab88 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserBriefDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDetailsDto.java similarity index 95% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDetailsDto.java index 2ab170d616..8f4b3c3892 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDetailsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDto.java similarity index 92% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDto.java index e7367e2fb4..c5db991725 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; -import at.tuwien.api.CacheableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.CacheableDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserEmailDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserEmailDto.java index caaf332497..a8ccd56b8d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserEmailDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserForgotDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserForgotDto.java index 5ebcbae742..4895a04c70 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserForgotDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserModifyPasswordDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserModifyPasswordDto.java index 2b86672cc2..9b1e1a72cc 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserModifyPasswordDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserPasswordDto.java similarity index 86% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserPasswordDto.java index dcf5393284..f549047c4e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserPasswordDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserResetDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserResetDto.java index 6cac59a904..260b5f67ca 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserResetDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserRolesDto.java similarity index 87% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserRolesDto.java index 5667f38ec6..8ed18d5101 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserRolesDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserThemeSetDto.java similarity index 88% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserThemeSetDto.java index 3f5b899df8..ebc7292edf 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserThemeSetDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdateDto.java similarity index 93% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdateDto.java index 68d674a7c2..099d3e7b08 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdatePermissionsDto.java similarity index 89% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdatePermissionsDto.java index 99f1eab30a..dd7742c2f5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/UserUpdatePermissionsDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user; +package at.ac.tuwien.ifs.dbrepo.core.api.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalMetadataDto.java similarity index 78% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalMetadataDto.java index fb40af0948..c169e27fe5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalMetadataDto.java @@ -1,6 +1,6 @@ -package at.tuwien.api.user.external; +package at.ac.tuwien.ifs.dbrepo.core.api.user.external; -import at.tuwien.api.user.external.affiliation.ExternalAffiliationDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.affiliation.ExternalAffiliationDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalResultType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalResultType.java similarity index 82% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalResultType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalResultType.java index e3eca17346..e3cb61abf1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalResultType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/ExternalResultType.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user.external; +package at.ac.tuwien.ifs.dbrepo.core.api.user.external; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; @@ -12,7 +12,7 @@ public enum ExternalResultType { @JsonProperty("Organizational") ORGANIZATIONAL("Organizational"); - private String name; + private final String name; ExternalResultType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/affiliation/ExternalAffiliationDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/affiliation/ExternalAffiliationDto.java index d8d30894bc..8a0a493503 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/external/affiliation/ExternalAffiliationDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user.external.affiliation; +package at.ac.tuwien.ifs.dbrepo.core.api.user.external.affiliation; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/internal/UpdateUserPasswordDto.java similarity index 85% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/internal/UpdateUserPasswordDto.java index c89e795bd3..8f1cffdd62 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/user/internal/UpdateUserPasswordDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.user.internal; +package at.ac.tuwien.ifs.dbrepo.core.api.user.internal; import jakarta.validation.constraints.NotBlank; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/Container.java similarity index 88% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/Container.java index 458dcec7eb..7390124cac 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/Container.java @@ -1,7 +1,7 @@ -package at.tuwien.entities.container; +package at.ac.tuwien.ifs.dbrepo.core.entity.container; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; @@ -84,6 +84,12 @@ public class Container { @Column private String privilegedPassword; + @Column + private String readonlyUsername; + + @Column + private String readonlyPassword; + @PrePersist public void prePersist() { if (this.id == null) { diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/ContainerImage.java similarity index 95% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/ContainerImage.java index 336a278d7d..7629976bf1 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/ContainerImage.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.container.image; +package at.ac.tuwien.ifs.dbrepo.core.entity.container.image; -import at.tuwien.entities.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/DataType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/DataType.java similarity index 97% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/DataType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/DataType.java index 347ca47e96..502474bee2 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/DataType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/DataType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.container.image; +package at.ac.tuwien.ifs.dbrepo.core.entity.container.image; import jakarta.persistence.*; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/Operator.java similarity index 94% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/Operator.java index adeb6dd8ef..5e629d2673 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/container/image/Operator.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.container.image; +package at.ac.tuwien.ifs.dbrepo.core.entity.container.image; import jakarta.persistence.*; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/AccessType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/AccessType.java similarity index 63% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/AccessType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/AccessType.java index 19a642ff96..c17ba90844 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/AccessType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/AccessType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; import lombok.Getter; import lombok.ToString; @@ -8,5 +8,5 @@ import lombok.ToString; public enum AccessType { READ, WRITE_OWN, - WRITE_ALL; + WRITE_ALL } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java similarity index 86% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java index b57f040668..2aefc232a3 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java @@ -1,9 +1,8 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.user.User; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; @@ -18,8 +17,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) @@ -32,13 +29,13 @@ import static jakarta.persistence.GenerationType.IDENTITY; @UniqueConstraint(columnNames = {"cid", "internalName"}) }) @NamedQueries({ - @NamedQuery(name = "Database.findAllDesc", query = "select distinct d from Database d order by d.id desc"), - @NamedQuery(name = "Database.findAllByInternalNameDesc", query = "select distinct d from Database d where d.internalName = ?1 order by d.id desc"), - @NamedQuery(name = "Database.findAllAtLestReadAccessDesc", query = "select distinct d from Database d where exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.id desc"), - @NamedQuery(name = "Database.findAllPublicOrSchemaPublicDesc", query = "select distinct d from Database d where d.isPublic = true or d.isSchemaPublic = true order by d.id desc"), - @NamedQuery(name = "Database.findAllPublicOrSchemaPublicOrReadAccessDesc", query = "select distinct d from Database d where d.isPublic = true or d.isSchemaPublic = true or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.id desc"), - @NamedQuery(name = "Database.findAllPublicOrSchemaPublicOrReadAccessByInternalNameDesc", query = "select distinct d from Database d where (d.isPublic = true or d.isSchemaPublic = true) and d.internalName = ?2 or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.id desc"), - @NamedQuery(name = "Database.findAllPublicOrSchemaPublicByInternalNameDesc", query = "select distinct d from Database d where (d.isPublic = true or d.isSchemaPublic = true) and d.internalName = ?1 order by d.id desc"), + @NamedQuery(name = "Database.findAllDesc", query = "select distinct d from Database d order by d.created desc"), + @NamedQuery(name = "Database.findAllByInternalNameDesc", query = "select distinct d from Database d where d.internalName = ?1 order by d.created desc"), + @NamedQuery(name = "Database.findAllAtLestReadAccessDesc", query = "select distinct d from Database d where exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.created desc"), + @NamedQuery(name = "Database.findAllPublicOrSchemaPublicDesc", query = "select distinct d from Database d where d.isPublic = true or d.isSchemaPublic = true order by d.created desc"), + @NamedQuery(name = "Database.findAllPublicOrSchemaPublicOrReadAccessDesc", query = "select distinct d from Database d where d.isPublic = true or d.isSchemaPublic = true or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.created desc"), + @NamedQuery(name = "Database.findAllPublicOrSchemaPublicOrReadAccessByInternalNameDesc", query = "select distinct d from Database d where (d.isPublic = true or d.isSchemaPublic = true) and d.internalName = ?2 or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.created desc"), + @NamedQuery(name = "Database.findAllPublicOrSchemaPublicByInternalNameDesc", query = "select distinct d from Database d where (d.isPublic = true or d.isSchemaPublic = true) and d.internalName = ?1 order by d.created desc"), }) public class Database implements Serializable { @@ -47,6 +44,9 @@ public class Database implements Serializable { @Column(columnDefinition = "VARCHAR(36)") private UUID id; + @Column(name = "grafana_dashboard_uid") + private String dashboardUid; + @JdbcTypeCode(java.sql.Types.VARCHAR) @Column(name = "owned_by", columnDefinition = "VARCHAR(36)") private UUID ownedBy; @@ -101,7 +101,7 @@ public class Database implements Serializable { @OrderBy("id DESC") @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "database", orphanRemoval = true) - private List<Table> tables; + private List<at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table> tables; @OrderBy("id DESC") @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "database", orphanRemoval = true) @@ -116,6 +116,9 @@ public class Database implements Serializable { @Column(nullable = false, columnDefinition = "boolean default true") private Boolean isSchemaPublic; + @Column(nullable = false, columnDefinition = "boolean default true") + private Boolean isDashboardEnabled; + @Lob @Basic(fetch = FetchType.LAZY) @Column(columnDefinition = "LONGBLOB") diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccess.java similarity index 89% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccess.java index e5f7dd3012..b0e110a676 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccess.java @@ -1,14 +1,11 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; -import at.tuwien.entities.user.User; -import com.fasterxml.jackson.annotation.JsonFormat; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; -import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import java.time.Instant; import java.util.UUID; @Data diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccessKey.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccessKey.java similarity index 80% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccessKey.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccessKey.java index b6963c290c..a1a55ab60e 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccessKey.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/DatabaseAccessKey.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; import lombok.EqualsAndHashCode; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/LanguageType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/LanguageType.java similarity index 97% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/LanguageType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/LanguageType.java index 35effb9cb8..b4e6ddb261 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/LanguageType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/LanguageType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; import lombok.Getter; @@ -373,7 +373,7 @@ public enum LanguageType { ZU("zu"); - private String name; + private final String name; LanguageType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/License.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/License.java similarity index 91% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/License.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/License.java index 4d43a3ba04..ce449e61ca 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/License.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/License.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; import lombok.*; import org.springframework.data.jpa.domain.support.AuditingEntityListener; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java similarity index 96% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java index 8f84a8f066..d84b75530b 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java @@ -1,7 +1,7 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.user.User; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ViewColumn.java similarity index 92% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ViewColumn.java index 2b18132e8c..aa2cfcd845 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ViewColumn.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.database; +package at.ac.tuwien.ifs.dbrepo.core.entity.database; -import at.tuwien.entities.database.table.columns.TableColumnType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnType; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; @@ -8,8 +8,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java similarity index 91% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java index 1e2aa72b92..42faf301ca 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java @@ -1,10 +1,10 @@ -package at.tuwien.entities.database.table; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.constraints.Constraints; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.user.User; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.Constraints; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.Identifier; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; @@ -21,8 +21,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnEnum.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnEnum.java similarity index 89% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnEnum.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnEnum.java index 99002c8129..dddf3fd501 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnEnum.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnEnum.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; import jakarta.persistence.*; import lombok.*; @@ -6,8 +6,6 @@ import org.hibernate.annotations.JdbcTypeCode; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnSet.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnSet.java similarity index 89% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnSet.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnSet.java index 036c0202db..a5925f9c2e 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/ColumnSet.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/ColumnSet.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; import jakarta.persistence.*; import lombok.*; @@ -6,8 +6,6 @@ import org.hibernate.annotations.JdbcTypeCode; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumn.java similarity index 96% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumn.java index eefa648dfd..010c919f05 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumn.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; -import at.tuwien.entities.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; @@ -16,8 +16,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnConcept.java similarity index 95% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnConcept.java index edf39d84e3..7b576cf792 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnConcept.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; @@ -11,8 +11,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnType.java similarity index 85% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnType.java index 7f95c476dd..9562193a2d 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; import lombok.Getter; import lombok.ToString; @@ -35,5 +35,5 @@ public enum TableColumnType { DATETIME, TIMESTAMP, TIME, - YEAR; + YEAR } \ No newline at end of file diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnUnit.java similarity index 95% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnUnit.java index 9d48062d33..39341261ff 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/columns/TableColumnUnit.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.columns; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; @@ -11,8 +11,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/Constraints.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/Constraints.java similarity index 71% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/Constraints.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/Constraints.java index 2676eaf3e1..f009c69f7f 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/Constraints.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/Constraints.java @@ -1,8 +1,8 @@ -package at.tuwien.entities.database.table.constraints; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; -import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; -import at.tuwien.entities.database.table.constraints.unique.Unique; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey.PrimaryKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique.Unique; import lombok.*; import jakarta.persistence.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKey.java similarity index 92% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKey.java index 92271b3232..c7414e3c1d 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKey.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.database.table.constraints.foreignKey; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey; -import at.tuwien.entities.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKeyReference.java similarity index 89% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKeyReference.java index 850b25ac5c..8ac36e4fa8 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ForeignKeyReference.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.database.table.constraints.foreignKey; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey; -import at.tuwien.entities.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; @@ -8,8 +8,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ReferenceType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ReferenceType.java similarity index 67% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ReferenceType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ReferenceType.java index 88be5c81aa..5e5aacb0bd 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ReferenceType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/foreignKey/ReferenceType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.database.table.constraints.foreignKey; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey; import lombok.Getter; import lombok.ToString; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/primaryKey/PrimaryKey.java similarity index 85% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/primaryKey/PrimaryKey.java index 26e0f13299..ddf3abdf9a 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/primaryKey/PrimaryKey.java @@ -1,7 +1,7 @@ -package at.tuwien.entities.database.table.constraints.primaryKey; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/unique/Unique.java similarity index 87% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/unique/Unique.java index e1ad4c4c4d..8dcf9ccbfd 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/constraints/unique/Unique.java @@ -1,7 +1,7 @@ -package at.tuwien.entities.database.table.constraints.unique; +package at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/AffiliationIdentifierSchemeType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/AffiliationIdentifierSchemeType.java similarity index 66% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/AffiliationIdentifierSchemeType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/AffiliationIdentifierSchemeType.java index 0d794ff431..8660ce1936 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/AffiliationIdentifierSchemeType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/AffiliationIdentifierSchemeType.java @@ -1,5 +1,5 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Creator.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java similarity index 96% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Creator.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java index cdbcf79777..8a2bcf25e2 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Creator.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import jakarta.persistence.*; import lombok.*; @@ -7,8 +7,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/DescriptionType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/DescriptionType.java similarity index 82% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/DescriptionType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/DescriptionType.java index 1d9ab52d78..ef85f04e72 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/DescriptionType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/DescriptionType.java @@ -1,5 +1,5 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; @@ -18,7 +18,7 @@ public enum DescriptionType { OTHER("Other"); - private String name; + private final String name; DescriptionType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java similarity index 95% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java index 43dbb849e3..04471509c6 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java @@ -1,9 +1,9 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.LanguageType; -import at.tuwien.entities.database.License; -import at.tuwien.entities.user.User; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.LanguageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.License; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.*; @@ -17,8 +17,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder(toBuilder = true) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierDescription.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java similarity index 93% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierDescription.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java index 32adddccfc..ab73de406e 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierDescription.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; -import at.tuwien.entities.database.LanguageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.LanguageType; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; @@ -9,8 +9,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.io.Serializable; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunder.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java similarity index 93% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunder.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java index 5b69b2e8f7..eb3c21e617 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunder.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import jakarta.persistence.*; import lombok.*; @@ -8,8 +8,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.io.Serializable; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunderType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunderType.java similarity index 64% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunderType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunderType.java index ea538dcbfb..d805d7e7a2 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierFunderType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunderType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; public enum IdentifierFunderType { CROSSREF_FUNDER_ID, diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierStatusType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierStatusType.java similarity index 53% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierStatusType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierStatusType.java index 6dd545a732..242a41e4a7 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierStatusType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierStatusType.java @@ -1,9 +1,9 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; @Getter public enum IdentifierStatusType { DRAFT, - PUBLISHED; + PUBLISHED } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierTitle.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java similarity index 93% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierTitle.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java index 769ff12a67..8dbbdac0a9 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierTitle.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; -import at.tuwien.entities.database.LanguageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.LanguageType; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.JdbcTypeCode; @@ -9,8 +9,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.io.Serializable; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierType.java similarity index 60% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierType.java index 51e2f01ef6..85fb127d98 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/IdentifierType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; @@ -7,5 +7,5 @@ public enum IdentifierType { DATABASE, SUBSET, TABLE, - VIEW; + VIEW } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameIdentifierSchemeType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameIdentifierSchemeType.java similarity index 66% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameIdentifierSchemeType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameIdentifierSchemeType.java index 6a7eb73a12..645ec69d89 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/NameIdentifierSchemeType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameIdentifierSchemeType.java @@ -1,5 +1,5 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameType.java new file mode 100644 index 0000000000..ce2f1585e4 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/NameType.java @@ -0,0 +1,9 @@ +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; + +import lombok.Getter; + +@Getter +public enum NameType { + PERSONAL, + ORGANIZATIONAL +} diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java similarity index 97% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java index 24ac7adb1f..e0eb28d11b 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import jakarta.persistence.*; import lombok.*; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedType.java similarity index 85% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedType.java index 34f98ef591..7310ff455b 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelatedType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; public enum RelatedType { @@ -38,7 +38,7 @@ public enum RelatedType { W3ID("w3id"); - private String name; + private final String name; RelatedType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelationType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelationType.java similarity index 94% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelationType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelationType.java index 65fc23fddb..94bebb0117 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/RelationType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelationType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; public enum RelationType { @@ -70,7 +70,7 @@ public enum RelationType { OBSOLETES("Obsoletes"); - private String name; + private final String name; RelationType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/TitleType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/TitleType.java similarity index 79% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/TitleType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/TitleType.java index 5dce16f771..a4b5f36b67 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/identifier/TitleType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/TitleType.java @@ -1,5 +1,5 @@ -package at.tuwien.entities.identifier; +package at.ac.tuwien.ifs.dbrepo.core.entity.identifier; import lombok.Getter; @@ -14,7 +14,7 @@ public enum TitleType { OTHER("Other"); - private String name; + private final String name; TitleType(String name) { this.name = name; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessage.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessage.java similarity index 93% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessage.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessage.java index 8a5f2d76a3..ef6f3533e9 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessage.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessage.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.entity.maintenance; import jakarta.persistence.*; import lombok.*; @@ -8,8 +8,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.Instant; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessageType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessageType.java similarity index 65% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessageType.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessageType.java index ca83865741..34cf2bc6d4 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/maintenance/BannerMessageType.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/maintenance/BannerMessageType.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.maintenance; +package at.ac.tuwien.ifs.dbrepo.core.entity.maintenance; import lombok.Getter; import lombok.ToString; @@ -8,5 +8,5 @@ import lombok.ToString; public enum BannerMessageType { WARNING, ERROR, - INFO; + INFO } \ No newline at end of file diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/semantics/Ontology.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/semantics/Ontology.java similarity index 94% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/semantics/Ontology.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/semantics/Ontology.java index 664b284c3d..8cf3250a04 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/semantics/Ontology.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/semantics/Ontology.java @@ -1,4 +1,4 @@ -package at.tuwien.entities.semantics; +package at.ac.tuwien.ifs.dbrepo.core.entity.semantics; import jakarta.persistence.*; import lombok.*; @@ -10,8 +10,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.Instant; import java.util.UUID; -import static jakarta.persistence.GenerationType.IDENTITY; - @Data @Entity @Builder diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/user/User.java similarity index 93% rename from dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/user/User.java index 44d36e5e03..f3a65f1de5 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/user/User.java @@ -1,6 +1,6 @@ -package at.tuwien.entities.user; +package at.ac.tuwien.ifs.dbrepo.core.entity.user; -import at.tuwien.entities.database.DatabaseAccess; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.DatabaseAccess; import jakarta.persistence.*; import lombok.*; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccessNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccessNotFoundException.java index d308361ae1..9cac5ca8f8 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccessNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccountNotSetupException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccountNotSetupException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccountNotSetupException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccountNotSetupException.java index 395e63d423..ed00129ca9 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccountNotSetupException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AccountNotSetupException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AnalyseServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AnalyseServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AnalyseServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AnalyseServiceException.java index 44cd0d3dc8..d86344bc86 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AnalyseServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AnalyseServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceConnectionException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceConnectionException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceConnectionException.java index 08cb54f9de..abca69a27b 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceConnectionException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceConnectionException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceException.java index de43ce1cbe..de5969c4a8 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AuthServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/AuthServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceConnectionException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceConnectionException.java index 6efa16fa87..7a5f17d0ed 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceConnectionException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceException.java index 86201c5d69..c0ca429d66 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/BrokerServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ConceptNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ConceptNotFoundException.java index 33e093ae5a..6be6c9dd8f 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ConceptNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerAlreadyExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerAlreadyExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerAlreadyExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerAlreadyExistsException.java index f27ea0aa19..348bcf51f3 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerAlreadyExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerAlreadyExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerNotFoundException.java index 0d17faafab..a81b036e26 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerQuotaException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerQuotaException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerQuotaException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerQuotaException.java index 6679775f00..9d01a33607 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerQuotaException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ContainerQuotaException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/CredentialsInvalidException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/CredentialsInvalidException.java index 984c70f485..afe130463f 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/CredentialsInvalidException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceConnectionException.java new file mode 100644 index 0000000000..cbac75cfff --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceConnectionException.java @@ -0,0 +1,21 @@ +package at.ac.tuwien.ifs.dbrepo.core.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "error.dashboard.connection") +public class DashboardServiceConnectionException extends Exception { + + public DashboardServiceConnectionException(String msg) { + super(msg); + } + + public DashboardServiceConnectionException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public DashboardServiceConnectionException(Throwable thr) { + super(thr); + } + +} diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceException.java new file mode 100644 index 0000000000..8ab1d1ef23 --- /dev/null +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DashboardServiceException.java @@ -0,0 +1,21 @@ +package at.ac.tuwien.ifs.dbrepo.core.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.dashboard.invalid") +public class DashboardServiceException extends Exception { + + public DashboardServiceException(String message) { + super(message); + } + + public DashboardServiceException(String message, Throwable thr) { + super(message, thr); + } + + public DashboardServiceException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceConnectionException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceConnectionException.java index 0125a781ad..156d8be729 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceConnectionException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceException.java index f76e662a65..66ea9a4e9b 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DataServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseMalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseMalformedException.java index 4bdc362256..7973419705 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseMalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseNotFoundException.java index c50349f33b..41cdcc8d4b 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseUnavailableException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseUnavailableException.java index 12c13d0754..1f40dd0832 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DatabaseUnavailableException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DoiNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DoiNotFoundException.java index 3b8e1732cc..790c43f28d 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/DoiNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/EmailExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/EmailExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/EmailExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/EmailExistsException.java index 4ce6c9b0ba..c82f6438bd 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/EmailExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/EmailExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExchangeNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExchangeNotFoundException.java index 251f09081e..f6e32e047a 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExchangeNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExternalServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExternalServiceException.java index d5f399c402..0866ee86d1 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ExternalServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FilterBadRequestException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FilterBadRequestException.java index 88689409ae..0c584430a6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FilterBadRequestException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FormatNotAvailableException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FormatNotAvailableException.java similarity index 90% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FormatNotAvailableException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FormatNotAvailableException.java index 2681e8d442..f977c087cb 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FormatNotAvailableException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/FormatNotAvailableException.java @@ -1,10 +1,8 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -import java.io.IOException; - @ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE, reason = "error.identifier.format") public class FormatNotAvailableException extends Exception { diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotFoundException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotFoundException.java index dee6a00035..a17825aed3 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotSupportedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotSupportedException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotSupportedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotSupportedException.java index 23b26ac6d6..07d090a2a3 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotSupportedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/IdentifierNotSupportedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageAlreadyExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageAlreadyExistsException.java index 2db757ed21..98e854ca18 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageAlreadyExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageInvalidException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageInvalidException.java index 401b587aed..4b4eeef07c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageInvalidException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageNotFoundException.java index a0235cc753..4e0bcf905c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ImageNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/LicenseNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/LicenseNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/LicenseNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/LicenseNotFoundException.java index fec3ad4128..1b4ad4f10e 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/LicenseNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/LicenseNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MalformedException.java index 974c2dadd6..f358709de7 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MessageNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MessageNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MessageNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MessageNotFoundException.java index 9090590551..53294e85d2 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MessageNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MessageNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceConnectionException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceConnectionException.java index 329de6ffc4..10599ab339 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceConnectionException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceException.java index a6784d6dd0..ec86fd55f2 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/MetadataServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/NotAllowedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/NotAllowedException.java index 52a2867b01..79332fe74a 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/NotAllowedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OntologyNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OntologyNotFoundException.java index 5f15403d67..283219e780 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OntologyNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OrcidNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OrcidNotFoundException.java index cf1ad7c067..2ad3560a8e 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/OrcidNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/PaginationException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/PaginationException.java index 5d71d0c404..4eae0a8bc6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/PaginationException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryMalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryMalformedException.java index 0782bc3269..571ae5e313 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryMalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotFoundException.java index 631fb1f0d8..0bdba4634e 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotSupportedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotSupportedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotSupportedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotSupportedException.java index e5894f0fdd..6a5df4f9e1 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotSupportedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryNotSupportedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreCreateException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreCreateException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreCreateException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreCreateException.java index 27ddb85e2c..d69c7757c5 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreCreateException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreCreateException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreGCException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreGCException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreGCException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreGCException.java index 00302c55ea..d4f40910bc 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreGCException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreGCException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreInsertException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreInsertException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreInsertException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreInsertException.java index 564383c844..0b7713d2ed 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreInsertException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStoreInsertException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStorePersistException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStorePersistException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStorePersistException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStorePersistException.java index 5b17442a3a..4cf73af90b 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStorePersistException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueryStorePersistException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueueNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueueNotFoundException.java index d06eca7438..69e1550046 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/QueueNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RemoteUnavailableException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RemoteUnavailableException.java index 6c2b14bb9b..0ab1bb158d 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RemoteUnavailableException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RorNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RorNotFoundException.java index afee080b5e..12a9e3ce06 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/RorNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceConnectionException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceConnectionException.java index d68185102a..ee6b4ab5ba 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceConnectionException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceException.java index aef3ae7f7c..a2ca63f200 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SearchServiceException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SemanticEntityNotFoundException.java similarity index 92% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SemanticEntityNotFoundException.java index 83c2f07f57..78540ac51c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SemanticEntityNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SortException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SortException.java index f70f0fbef9..bf9f1dd2b7 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/SortException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageNotFoundException.java index bbb780ea91..2bef9e7a75 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageUnavailableException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageUnavailableException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageUnavailableException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageUnavailableException.java index 08e49ada9e..813cbd58ad 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/StorageUnavailableException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/StorageUnavailableException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableExistsException.java index 252c1b0fa6..7eca5f85e0 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableMalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableMalformedException.java index 0878f36070..0440a939bf 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableMalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableNotFoundException.java index 5380be1e60..e40bf35f76 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableSchemaException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableSchemaException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableSchemaException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableSchemaException.java index 539e39897e..47d0456aa5 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableSchemaException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/TableSchemaException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UnitNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UnitNotFoundException.java index 1cc0308755..b8204c40e7 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UnitNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UriMalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UriMalformedException.java index 05d10c1323..fa4317280a 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UriMalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserExistsException.java index 712e79fa26..e2640b3039 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserNotFoundException.java index 1aa6adafec..47c78d0b08 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/UserNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewExistsException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewExistsException.java index 265974db55..c45e0022f0 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewExistsException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewMalformedException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewMalformedException.java index 0f8d5bef55..e8158644fa 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewMalformedException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewNotFoundException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewNotFoundException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewNotFoundException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewNotFoundException.java index 2c8cf52e0e..fea56d5edd 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewNotFoundException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewNotFoundException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewSchemaException.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewSchemaException.java similarity index 91% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewSchemaException.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewSchemaException.java index 4761b6e964..035842aab7 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewSchemaException.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/exception/ViewSchemaException.java @@ -1,4 +1,4 @@ -package at.tuwien.exception; +package at.ac.tuwien.ifs.dbrepo.core.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java similarity index 79% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java index 7428478924..3db28cc7d6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java @@ -1,79 +1,87 @@ -package at.tuwien.mapper; - -import at.tuwien.api.container.ContainerBriefDto; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.CreateContainerDto; -import at.tuwien.api.container.image.DataTypeDto; -import at.tuwien.api.container.image.ImageBriefDto; -import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.api.container.image.ImageDto; -import at.tuwien.api.crossref.CrossrefDto; -import at.tuwien.api.database.*; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.columns.ColumnBriefDto; -import at.tuwien.api.database.table.columns.ColumnDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; -import at.tuwien.api.database.table.columns.concepts.ConceptDto; -import at.tuwien.api.database.table.columns.concepts.ConceptSaveDto; -import at.tuwien.api.database.table.columns.concepts.UnitDto; -import at.tuwien.api.database.table.columns.concepts.UnitSaveDto; -import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyBriefDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; -import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; -import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; -import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.datacite.doi.*; -import at.tuwien.api.identifier.*; -import at.tuwien.api.identifier.ld.LdCreatorDto; -import at.tuwien.api.identifier.ld.LdDatasetDto; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.keycloak.UserCreateDto; -import at.tuwien.api.maintenance.BannerMessageBriefDto; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageDto; -import at.tuwien.api.maintenance.BannerMessageTypeDto; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedSourceTypeDto; -import at.tuwien.api.ror.RorDto; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.OntologyBriefDto; -import at.tuwien.api.semantics.OntologyCreateDto; -import at.tuwien.api.semantics.OntologyDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.api.user.UserUpdateDto; -import at.tuwien.api.user.external.ExternalMetadataDto; -import at.tuwien.api.user.external.ExternalResultType; -import at.tuwien.api.user.external.affiliation.ExternalAffiliationDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.container.image.DataType; -import at.tuwien.entities.database.*; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnConcept; -import at.tuwien.entities.database.table.columns.TableColumnUnit; -import at.tuwien.entities.database.table.constraints.Constraints; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference; -import at.tuwien.entities.database.table.constraints.foreignKey.ReferenceType; -import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; -import at.tuwien.entities.database.table.constraints.unique.Unique; -import at.tuwien.entities.identifier.*; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.entities.maintenance.BannerMessageType; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.entities.user.User; +package at.ac.tuwien.ifs.dbrepo.core.mapper; + +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.CreateContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.DataTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.ImageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.crossref.CrossrefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.ColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.CreateTableColumnDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.ConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ForeignKeyReferenceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.ReferenceTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary.PrimaryKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.*; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.PermissionTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld.LdCreatorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.ld.LdDatasetDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.TokenDto; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.UserCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.OrcidActivitiesSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.OrcidEmploymentsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.OrcidSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.OrcidOrganizationDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.disambiguated.OrcidDisambiguatedSourceTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.OrcidPersonDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name.OrcidNameDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name.OrcidValueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.ror.RorDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.EntityDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.OntologyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalMetadataDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.ExternalResultType; +import at.ac.tuwien.ifs.dbrepo.core.api.user.external.affiliation.ExternalAffiliationDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.DataType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.Constraints; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKeyReference; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ReferenceType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey.PrimaryKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique.Unique; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.idm.UserRepresentation; import org.mapstruct.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.text.Normalizer; import java.time.Instant; @@ -86,7 +94,7 @@ import java.util.stream.Collectors; @Mapper(componentModel = "spring", imports = {LinkedList.class, ExternalResultType.class}) public interface MetadataMapper { - org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MetadataMapper.class); + Logger log = LoggerFactory.getLogger(MetadataMapper.class); @Mappings({ @Mapping(target = "dMin", source = "DMin"), @@ -96,6 +104,12 @@ public interface MetadataMapper { }) DataTypeDto dataTypeToDataTypeDto(DataType data); + @Mappings({ + @Mapping(target = "databaseName", source = "internalName"), + @Mapping(target = "ownerUsername", source = "owner.username") + }) + CreateDashboardDto databaseToCreateDashboardDto(Database database); + @Mappings({ @Mapping(target = "id", ignore = true), /* id attribute is ignored by the library anyway, just making it explicit */ @Mapping(target = "attributes", ignore = true) @@ -267,6 +281,38 @@ public interface MetadataMapper { }) ExternalMetadataDto orcidDtoToExternalMetadataDto(OrcidDto data); + default OrcidDto userToOrcidDto(User data) { + return OrcidDto.builder() + .person(OrcidPersonDto.builder() + .name(OrcidNameDto.builder() + .givenNames(OrcidValueDto.builder() + .value(data.getFirstname()) + .build()) + .familyName(OrcidValueDto.builder() + .value(data.getLastname()) + .build()) + .build()) + .build()) + .activitiesSummary(OrcidActivitiesSummaryDto.builder() + .employments(OrcidEmploymentsDto.builder() + .affiliationGroup(new OrcidAffiliationGroupDto[]{ + OrcidAffiliationGroupDto.builder() + .summaries(new OrcidEmploymentSummaryDto[]{ + OrcidEmploymentSummaryDto.builder() + .employmentSummary(OrcidSummaryDto.builder() + .organization(OrcidOrganizationDto.builder() + .name(data.getAffiliation()) + .build()) + .build()) + .build() + }) + .build() + }) + .build()) + .build()) + .build(); + } + @Mappings({ @Mapping(target = "organizationName", source = "employmentSummary.organization.name"), @Mapping(target = "ringgoldId", expression = "java(disambiguatedOrganizationToRinggoldId(data.getEmploymentSummary().getOrganization().getDisambiguatedOrganization()))"), @@ -289,6 +335,16 @@ public interface MetadataMapper { return null; } + default PermissionTypeDto accessTypeDtoToPermissionTypeDto(AccessTypeDto data) { + if (data == null) { + return PermissionTypeDto.NONE; + } + return switch (data) { + case READ -> PermissionTypeDto.VIEW; + case WRITE_OWN, WRITE_ALL -> PermissionTypeDto.EDITOR; + }; + } + default ExternalMetadataDto rorDtoToExternalMetadataDto(RorDto data) { return ExternalMetadataDto.builder() .affiliations(new ExternalAffiliationDto[]{ @@ -336,6 +392,9 @@ public interface MetadataMapper { case SUBSET -> links.setData("/api/database/" + data.getDatabase().getId() + "/subset/" + data.getQueryId() + "/data"); } + if (data.getDatabase().getIsDashboardEnabled()) { + links.setDashboardHtml("/d/" + data.getDatabase().getDashboardUid()); + } return links; } @@ -400,12 +459,18 @@ public interface MetadataMapper { .build(); } - Identifier identifierCreateDtoToIdentifier(CreateIdentifierDto data); + Identifier createIdentifierDtoToIdentifier(CreateIdentifierDto data); - Identifier identifierUpdateDtoToIdentifier(IdentifierSaveDto data); + Identifier identifierSaveDtoToIdentifier(IdentifierSaveDto data); + + IdentifierSaveDto identifierToIdentifierSaveDto(Identifier data); + + CreateIdentifierDto identifierToCreateIdentifierDto(Identifier data); License licenseDtoToLicense(LicenseDto data); + ImageCreateDto containerImageToImageCreateDto(ContainerImage data); + IdentifierTitle identifierCreateTitleDtoToIdentifierTitle(SaveIdentifierTitleDto data); IdentifierDescription identifierCreateDescriptionDtoToIdentifierDescription(SaveIdentifierDescriptionDto data); @@ -512,8 +577,12 @@ public interface MetadataMapper { ConceptDto tableColumnConceptToConceptDto(TableColumnConcept data); + ConceptBriefDto tableColumnConceptToConceptBriefDto(TableColumnConcept data); + UnitDto tableColumnUnitToUnitDto(TableColumnUnit data); + UnitBriefDto tableColumnUnitToUnitBriefDto(TableColumnUnit data); + TableColumnUnit unitSaveDtoToTableColumnUnit(UnitSaveDto data); TableColumnUnit entityDtoToTableColumnUnit(EntityDto data); @@ -588,6 +657,7 @@ public interface MetadataMapper { .identifiers(new LinkedList<>()) .columns(new LinkedList<>()) .constraints(constraintsToConstraintsDto(data.getConstraints())) + .created(data.getCreated()) .build(); if (data.getIdentifiers() != null) { table.setIdentifiers(new LinkedList<>(data.getIdentifiers() @@ -866,10 +936,8 @@ public interface MetadataMapper { String nowhitespace = WHITESPACE.matcher(data).replaceAll("_"); String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); String slug = NONLATIN.matcher(normalized).replaceAll("_"); - final String name = slug.toLowerCase(Locale.ENGLISH) + return slug.toLowerCase(Locale.ENGLISH) .replaceAll("-", "_"); - log.debug("mapping name {} to internal name {}", data, name); - return name; } LanguageType languageTypeDtoToLanguageType(LanguageTypeDto data); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java similarity index 69% rename from dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java index 490c902295..d2f622fbd1 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java @@ -1,73 +1,76 @@ -package at.tuwien.test; - -import at.tuwien.ExportResourceDto; -import at.tuwien.api.amqp.CreateVirtualHostDto; -import at.tuwien.api.amqp.ExchangeDto; -import at.tuwien.api.amqp.GrantVirtualHostPermissionsDto; -import at.tuwien.api.amqp.QueueDto; -import at.tuwien.api.auth.CreateUserDto; -import at.tuwien.api.container.ContainerBriefDto; -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.table.*; -import at.tuwien.api.database.table.columns.*; -import at.tuwien.api.database.table.columns.concepts.*; -import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; -import at.tuwien.api.database.table.constraints.foreign.*; -import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; -import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.api.datacite.DataCiteBody; -import at.tuwien.api.datacite.DataCiteData; -import at.tuwien.api.datacite.doi.DataCiteDoi; -import at.tuwien.api.identifier.*; -import at.tuwien.api.keycloak.*; -import at.tuwien.api.maintenance.BannerMessageCreateDto; -import at.tuwien.api.maintenance.BannerMessageDto; -import at.tuwien.api.maintenance.BannerMessageTypeDto; -import at.tuwien.api.maintenance.BannerMessageUpdateDto; -import at.tuwien.api.orcid.OrcidDto; -import at.tuwien.api.orcid.activities.OrcidActivitiesSummaryDto; -import at.tuwien.api.orcid.activities.employments.OrcidEmploymentsDto; -import at.tuwien.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.OrcidSummaryDto; -import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.organization.OrcidOrganizationDto; -import at.tuwien.api.orcid.person.OrcidPersonDto; -import at.tuwien.api.orcid.person.name.OrcidNameDto; -import at.tuwien.api.orcid.person.name.OrcidValueDto; -import at.tuwien.api.semantics.*; -import at.tuwien.api.user.UserAttributesDto; -import at.tuwien.api.user.*; -import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.container.image.Operator; -import at.tuwien.entities.database.*; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnConcept; -import at.tuwien.entities.database.table.columns.TableColumnType; -import at.tuwien.entities.database.table.columns.TableColumnUnit; -import at.tuwien.entities.database.table.constraints.Constraints; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; -import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference; -import at.tuwien.entities.database.table.constraints.foreignKey.ReferenceType; -import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; -import at.tuwien.entities.database.table.constraints.unique.Unique; -import at.tuwien.entities.identifier.*; -import at.tuwien.entities.maintenance.BannerMessage; -import at.tuwien.entities.maintenance.BannerMessageType; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.entities.user.User; -import at.tuwien.test.utils.ArrayUtils; +package at.ac.tuwien.ifs.dbrepo.core.test; + +import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.CreateVirtualHostDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.ExchangeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.GrantVirtualHostPermissionsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.amqp.QueueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.auth.CreateUserDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerBriefDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto; +import at.ac.tuwien.ifs.dbrepo.core.api.container.image.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.query.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.columns.concepts.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.ConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.CreateTableConstraintsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.foreign.*; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.primary.PrimaryKeyDto; +import at.ac.tuwien.ifs.dbrepo.core.api.database.table.constraints.unique.UniqueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.DataCiteBody; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.DataCiteData; +import at.ac.tuwien.ifs.dbrepo.core.api.datacite.doi.DataCiteDoi; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardDto; +import at.ac.tuwien.ifs.dbrepo.core.api.grafana.CreateDashboardResponseDto; +import at.ac.tuwien.ifs.dbrepo.core.api.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.api.keycloak.*; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageCreateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageTypeDto; +import at.ac.tuwien.ifs.dbrepo.core.api.maintenance.BannerMessageUpdateDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.OrcidDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.OrcidActivitiesSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.OrcidEmploymentsDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.OrcidAffiliationGroupDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.OrcidEmploymentSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.OrcidSummaryDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.activities.employments.affiliation.group.summary.organization.OrcidOrganizationDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.OrcidPersonDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name.OrcidNameDto; +import at.ac.tuwien.ifs.dbrepo.core.api.orcid.person.name.OrcidValueDto; +import at.ac.tuwien.ifs.dbrepo.core.api.semantics.*; +import at.ac.tuwien.ifs.dbrepo.core.api.user.*; +import at.ac.tuwien.ifs.dbrepo.core.api.user.UserAttributesDto; +import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.ContainerImage; +import at.ac.tuwien.ifs.dbrepo.core.entity.container.image.Operator; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumn; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnConcept; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.columns.TableColumnUnit; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.Constraints; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ForeignKeyReference; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.foreignKey.ReferenceType; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.primaryKey.PrimaryKey; +import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.constraints.unique.Unique; +import at.ac.tuwien.ifs.dbrepo.core.entity.identifier.*; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessage; +import at.ac.tuwien.ifs.dbrepo.core.entity.maintenance.BannerMessageType; +import at.ac.tuwien.ifs.dbrepo.core.entity.semantics.Ontology; +import at.ac.tuwien.ifs.dbrepo.core.entity.user.User; +import at.ac.tuwien.ifs.dbrepo.core.test.utils.ArrayUtils; import org.springframework.core.io.InputStreamResource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.test.context.TestPropertySource; import java.io.InputStream; import java.math.BigDecimal; @@ -77,7 +80,6 @@ import java.time.Instant; import java.time.LocalDate; import java.time.ZoneOffset; import java.util.*; -import java.util.stream.Collectors; import static java.time.temporal.ChronoUnit.HOURS; import static java.time.temporal.ChronoUnit.MINUTES; @@ -121,183 +123,180 @@ import static java.time.temporal.ChronoUnit.MINUTES; * </ul> * <p> * Database 4 (Public Data, Public Schema, User 4) -> Container 4 + * <ul> * <li>Table 9</li> * <li>Identifier 7</li> * <li>Query 7</li> - * <ul> * </ul> - * <br /> - * User 1 (read) - * <br /> - * User 2 (write-own) - * <br /> - * User 3 (write-all) */ -public abstract class BaseTest { - - public static final String MINIO_IMAGE = "minio/minio:RELEASE.2024-06-06T09-36-42Z"; - - public static final String MARIADB_IMAGE = "mariadb:11.3.2"; +@TestPropertySource(locations = "classpath:application.properties") +public class BaseTest { - public static final String RABBITMQ_IMAGE = "rabbitmq:3.13.7"; + public final static String MINIO_IMAGE = "minio/minio:RELEASE.2024-06-06T09-36-42Z"; + public final static String MARIADB_IMAGE = "mariadb:11.3.2"; + public final static String RABBITMQ_IMAGE = "rabbitmq:3.13.7"; + public final static String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak:26.0.4"; - public static final String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak:26.0.4"; + public final static String REALM_DBREPO_NAME = "dbrepo"; - public static final String[] DEFAULT_SEMANTICS_HANDLING = new String[]{"default-semantics-handling", + public final static String[] DEFAULT_SEMANTICS_HANDLING = new String[]{"default-semantics-handling", "create-semantic-unit", "execute-semantic-query", "table-semantic-analyse", "create-semantic-concept"}; - public static final String[] DEFAULT_VIEW_HANDLING = new String[]{"update-database-view", "create-database-view", + public final static String[] DEFAULT_VIEW_HANDLING = new String[]{"update-database-view", "create-database-view", "delete-database-view", "list-database-views", "modify-view-visibility", "find-database-view"}; - public static final String[] ESCALATED_SEMANTICS_HANDLING = new String[]{"escalated-semantics-handling", + public final static String[] ESCALATED_SEMANTICS_HANDLING = new String[]{"escalated-semantics-handling", "update-semantic-concept", "modify-foreign-table-column-semantics", "delete-ontology", "list-ontologies", "update-semantic-unit", "create-ontology", "update-ontology"}; - public static final String[] DEFAULT_CONTAINER_HANDLING = new String[]{"default-container-handling", + public final static String[] DEFAULT_CONTAINER_HANDLING = new String[]{"default-container-handling", "create-container", "list-containers", "modify-container-state"}; - public static final String[] ESCALATED_CONTAINER_HANDLING = new String[]{"escalated-container-handling", + public final static String[] ESCALATED_CONTAINER_HANDLING = new String[]{"escalated-container-handling", "modify-foreign-container-state", "delete-container"}; - public static final String[] DEFAULT_DATABASE_HANDLING = new String[]{"default-database-handling", + public final static String[] DEFAULT_DATABASE_HANDLING = new String[]{"default-database-handling", "update-database-access", "modify-database-visibility", "create-database", "modify-database-owner", "delete-database-access", "check-database-access", "list-databases", "modify-database-image", "create-database-access", "find-database", "import-database-data"}; - public static final String[] ESCALATED_DATABASE_HANDLING = new String[]{"escalated-database-handling", + public final static String[] ESCALATED_DATABASE_HANDLING = new String[]{"escalated-database-handling", "delete-database"}; - public static final String[] DEFAULT_IDENTIFIER_HANDLING = new String[]{"default-identifier-handling", + public final static String[] DEFAULT_IDENTIFIER_HANDLING = new String[]{"default-identifier-handling", "create-identifier", "find-identifier", "list-identifiers", "publish-identifier", "delete-identifier"}; - public static final String[] ESCALATED_IDENTIFIER_HANDLING = new String[]{"escalated-identifier-handling", + public final static String[] ESCALATED_IDENTIFIER_HANDLING = new String[]{"escalated-identifier-handling", "modify-identifier-metadata", "update-foreign-identifier", "create-foreign-identifier"}; - public static final String[] DEFAULT_QUERY_HANDLING = new String[]{"default-query-handling", "view-table-data", + public final static String[] DEFAULT_QUERY_HANDLING = new String[]{"default-query-handling", "view-table-data", "execute-query", "view-table-history", "list-database-views", "export-query-data", "create-database-view", "delete-database-view", "delete-table-data", "export-table-data", "persist-query", "re-execute-query", "insert-table-data", "find-database-view"}; - public static final String[] ESCALATED_QUERY_HANDLING = new String[]{"escalated-query-handling"}; + public final static String[] ESCALATED_QUERY_HANDLING = new String[]{"escalated-query-handling"}; - public static final String[] DEFAULT_TABLE_HANDLING = new String[]{"default-table-handling", - "list-tables", "create-table", "modify-table-column-semantics", "find-table", "delete-table", - "update-table-statistic", "update-table"}; + public final static String[] DEFAULT_TABLE_HANDLING = new String[]{"default-table-handling", "list-tables", + "create-table", "modify-table-column-semantics", "find-table", "delete-table", "update-table-statistic", + "update-table"}; - public static final String[] ESCALATED_TABLE_HANDLING = new String[]{"escalated-table-handling", + public final static String[] ESCALATED_TABLE_HANDLING = new String[]{"escalated-table-handling", "delete-foreign-table"}; - public static final String[] DEFAULT_USER_HANDLING = new String[]{"default-user-handling", "modify-user-theme", + public final static String[] DEFAULT_USER_HANDLING = new String[]{"default-user-handling", "modify-user-theme", "modify-user-information"}; - public static final String[] ESCALATED_USER_HANDLING = new String[]{"escalated-user-handling", "find-user"}; - - public static final String[] DEFAULT_RESEARCHER_ROLES = ArrayUtils.merge(List.of(new String[]{"default-researcher-roles"}, - DEFAULT_CONTAINER_HANDLING, DEFAULT_DATABASE_HANDLING, DEFAULT_IDENTIFIER_HANDLING, DEFAULT_QUERY_HANDLING, - DEFAULT_TABLE_HANDLING, DEFAULT_USER_HANDLING, DEFAULT_SEMANTICS_HANDLING, DEFAULT_VIEW_HANDLING)); - - public static final String[] DEFAULT_DEVELOPER_ROLES = ArrayUtils.merge(List.of(new String[]{"default-developer-roles"}, - DEFAULT_CONTAINER_HANDLING, DEFAULT_DATABASE_HANDLING, DEFAULT_IDENTIFIER_HANDLING, DEFAULT_QUERY_HANDLING, - DEFAULT_TABLE_HANDLING, DEFAULT_USER_HANDLING, ESCALATED_USER_HANDLING, ESCALATED_CONTAINER_HANDLING, - ESCALATED_DATABASE_HANDLING, ESCALATED_IDENTIFIER_HANDLING, ESCALATED_QUERY_HANDLING, - ESCALATED_TABLE_HANDLING, DEFAULT_VIEW_HANDLING)); - - public static final String[] DEFAULT_DATA_STEWARD_ROLES = ArrayUtils.merge(List.of(new String[]{"default-data-steward-roles"}, - ESCALATED_IDENTIFIER_HANDLING, DEFAULT_SEMANTICS_HANDLING, ESCALATED_SEMANTICS_HANDLING, DEFAULT_VIEW_HANDLING)); - - public static final String[] DEFAULT_LOCAL_ADMIN_ROLES = new String[]{"system"}; - - public static final List<GrantedAuthorityDto> AUTHORITY_LOCAL_ADMIN_ROLES = Arrays.stream(DEFAULT_LOCAL_ADMIN_ROLES) - .map(GrantedAuthorityDto::new) - .collect(Collectors.toList()); - - public static final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_RESEARCHER_ROLES = Arrays.stream(DEFAULT_RESEARCHER_ROLES) - .map(GrantedAuthorityDto::new) - .collect(Collectors.toList()); - - public static final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_DEVELOPER_ROLES = Arrays.stream(DEFAULT_DEVELOPER_ROLES) - .map(GrantedAuthorityDto::new) - .collect(Collectors.toList()); - - public static final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_DATA_STEWARD_ROLES = Arrays.stream(DEFAULT_DATA_STEWARD_ROLES) - .map(GrantedAuthorityDto::new) - .collect(Collectors.toList()); - - public static final List<GrantedAuthority> AUTHORITY_DEFAULT_LOCAL_ADMIN_AUTHORITIES = AUTHORITY_LOCAL_ADMIN_ROLES.stream() - .map(a -> new SimpleGrantedAuthority(a.getAuthority())) - .collect(Collectors.toList()); - - public static final List<GrantedAuthority> AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES = AUTHORITY_DEFAULT_RESEARCHER_ROLES.stream() - .map(a -> new SimpleGrantedAuthority(a.getAuthority())) - .collect(Collectors.toList()); - - public static final List<GrantedAuthority> AUTHORITY_DEFAULT_DEVELOPER_AUTHORITIES = AUTHORITY_DEFAULT_DEVELOPER_ROLES.stream() - .map(a -> new SimpleGrantedAuthority(a.getAuthority())) - .collect(Collectors.toList()); - - public static final List<GrantedAuthority> AUTHORITY_DEFAULT_DATA_STEWARD_AUTHORITIES = AUTHORITY_DEFAULT_DATA_STEWARD_ROLES.stream() - .map(a -> new SimpleGrantedAuthority(a.getAuthority())) - .collect(Collectors.toList()); - - public static final UUID REALM_DBREPO_ID = UUID.fromString("6264bf7b-d1d3-4562-9c07-ce4364a8f9d3"); - public static final String REALM_DBREPO_NAME = "dbrepo"; - public static final Boolean REALM_DBREPO_ENABLED = true; - - public static final UUID ROLE_DEFAULT_REALM_DBREPO_ROLES_ID = UUID.fromString("c74cbbe7-3ab1-4472-9211-cc904567268"); - public static final String ROLE_DEFAULT_REALM_DBREPO_ROLES_NAME = "default-dbrepo-roles"; - public static final UUID ROLE_DEFAULT_REALM_DBREPO_ROLES_REALM_ID = REALM_DBREPO_ID; - - public static final UUID ROLE_DEFAULT_RESEARCHER_ROLES_ID = UUID.fromString("c74cbbe7-3ab1-4472-9211-cc9045672682"); - public static final String ROLE_DEFAULT_RESEARCHER_ROLES_NAME = "default-researcher-roles"; - public static final UUID ROLE_DEFAULT_RESEARCHER_ROLES_REALM_ID = REALM_DBREPO_ID; - - public static final CreateAccessDto UPDATE_DATABASE_ACCESS_READ_DTO = CreateAccessDto.builder() + public final static String[] ESCALATED_USER_HANDLING = new String[]{"escalated-user-handling", "find-user"}; + + public final static String[] DEFAULT_RESEARCHER_ROLES = ArrayUtils.merge(List.of( + new String[]{"default-researcher-roles"}, DEFAULT_CONTAINER_HANDLING, DEFAULT_DATABASE_HANDLING, + DEFAULT_IDENTIFIER_HANDLING, DEFAULT_QUERY_HANDLING, DEFAULT_TABLE_HANDLING, DEFAULT_USER_HANDLING, + DEFAULT_SEMANTICS_HANDLING, DEFAULT_VIEW_HANDLING)); + + public final static String[] DEFAULT_DEVELOPER_ROLES = ArrayUtils.merge(List.of( + new String[]{"default-developer-roles"}, DEFAULT_CONTAINER_HANDLING, DEFAULT_DATABASE_HANDLING, + DEFAULT_IDENTIFIER_HANDLING, DEFAULT_QUERY_HANDLING, DEFAULT_TABLE_HANDLING, DEFAULT_USER_HANDLING, + ESCALATED_USER_HANDLING, ESCALATED_CONTAINER_HANDLING, ESCALATED_DATABASE_HANDLING, + ESCALATED_IDENTIFIER_HANDLING, ESCALATED_QUERY_HANDLING, ESCALATED_TABLE_HANDLING, DEFAULT_VIEW_HANDLING)); + + public final static String[] DEFAULT_DATA_STEWARD_ROLES = ArrayUtils.merge(List.of( + new String[]{"default-data-steward-roles"}, ESCALATED_IDENTIFIER_HANDLING, DEFAULT_SEMANTICS_HANDLING, + ESCALATED_SEMANTICS_HANDLING, DEFAULT_VIEW_HANDLING)); + + public final static String[] DEFAULT_LOCAL_ADMIN_ROLES = ArrayUtils.merge(List.of(new String[]{"system"}, + DEFAULT_RESEARCHER_ROLES)); + + public final List<GrantedAuthorityDto> AUTHORITY_LOCAL_ADMIN_ROLES = + Arrays.stream(DEFAULT_LOCAL_ADMIN_ROLES) + .map(GrantedAuthorityDto::new) + .toList(); + + public final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_RESEARCHER_ROLES = + Arrays.stream(DEFAULT_RESEARCHER_ROLES) + .map(GrantedAuthorityDto::new) + .toList(); + + public final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_DEVELOPER_ROLES = + Arrays.stream(DEFAULT_DEVELOPER_ROLES) + .map(GrantedAuthorityDto::new) + .toList(); + + public final List<GrantedAuthorityDto> AUTHORITY_DEFAULT_DATA_STEWARD_ROLES = + Arrays.stream(DEFAULT_DATA_STEWARD_ROLES) + .map(GrantedAuthorityDto::new) + .toList(); + + public final List<GrantedAuthority> AUTHORITY_DEFAULT_LOCAL_ADMIN_AUTHORITIES = + AUTHORITY_LOCAL_ADMIN_ROLES + .stream() + .map(a -> (GrantedAuthority) new SimpleGrantedAuthority(a.getAuthority())) + .toList(); + + public final List<GrantedAuthority> AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES = + AUTHORITY_DEFAULT_RESEARCHER_ROLES + .stream() + .map(a -> (GrantedAuthority) new SimpleGrantedAuthority(a.getAuthority())) + .toList(); + + public final List<GrantedAuthority> AUTHORITY_DEFAULT_DEVELOPER_AUTHORITIES = + AUTHORITY_DEFAULT_DEVELOPER_ROLES + .stream() + .map(a -> (GrantedAuthority) new SimpleGrantedAuthority(a.getAuthority())) + .toList(); + + public final List<GrantedAuthority> AUTHORITY_DEFAULT_DATA_STEWARD_AUTHORITIES = + AUTHORITY_DEFAULT_DATA_STEWARD_ROLES + .stream() + .map(a -> (GrantedAuthority) new SimpleGrantedAuthority(a.getAuthority())) + .toList(); + + public final CreateAccessDto UPDATE_DATABASE_ACCESS_READ_DTO = CreateAccessDto.builder() .type(AccessTypeDto.READ) .build(); - public static final CreateAccessDto UPDATE_DATABASE_ACCESS_WRITE_OWN_DTO = CreateAccessDto.builder() + public final CreateAccessDto UPDATE_DATABASE_ACCESS_WRITE_OWN_DTO = CreateAccessDto.builder() .type(AccessTypeDto.WRITE_OWN) .build(); - public static final CreateAccessDto UPDATE_DATABASE_ACCESS_WRITE_ALL_DTO = CreateAccessDto.builder() + public final CreateAccessDto UPDATE_DATABASE_ACCESS_WRITE_ALL_DTO = CreateAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .build(); - public static final String TOKEN_ACCESS_TOKEN = "ey.yee.skrr"; - public static final String TOKEN_ACCESS_SCOPE = "openid"; + public final static String TOKEN_ACCESS_TOKEN = "ey.yee.skrr"; + public final static String TOKEN_ACCESS_SCOPE = "openid"; - public static final TokenDto TOKEN_DTO = TokenDto.builder() + public final TokenDto TOKEN_DTO = TokenDto.builder() .accessToken(TOKEN_ACCESS_TOKEN) .scope(TOKEN_ACCESS_SCOPE) .build(); - public static final UUID CONCEPT_1_ID = UUID.fromString("8cabc011-4bdf-44d4-9d33-b2648e2ddbf1"); - public static final String CONCEPT_1_NAME = "precipitation"; - public static final String CONCEPT_1_URI = "http://www.wikidata.org/entity/Q25257"; - public static final String CONCEPT_1_DESCRIPTION = null; - public static final Instant CONCEPT_1_CREATED = Instant.ofEpochSecond(1701976048L) /* 2023-12-07 19:07:27 (UTC) */; + public final static UUID CONCEPT_1_ID = UUID.fromString("8cabc011-4bdf-44d4-9d33-b2648e2ddbf1"); + public final static String CONCEPT_1_NAME = "precipitation"; + public final static String CONCEPT_1_URI = "http://www.wikidata.org/entity/Q25257"; + public final static String CONCEPT_1_DESCRIPTION = null; + public final static Instant CONCEPT_1_CREATED = Instant.ofEpochSecond(1701976048L) /* 2023-12-07 19:07:27 (UTC) */; - public static final ConceptSaveDto CONCEPT_1_SAVE_DTO = ConceptSaveDto.builder() + public final ConceptSaveDto CONCEPT_1_SAVE_DTO = ConceptSaveDto.builder() .uri(CONCEPT_1_URI) .name(CONCEPT_1_NAME) .description(CONCEPT_1_DESCRIPTION) .build(); - public static final ConceptDto CONCEPT_1_DTO = ConceptDto.builder() + public final ConceptDto CONCEPT_1_DTO = ConceptDto.builder() .id(CONCEPT_1_ID) .uri(CONCEPT_1_URI) .name(CONCEPT_1_NAME) .description(CONCEPT_1_DESCRIPTION) .build(); - public static final ConceptBriefDto CONCEPT_1_BRIEF_DTO = ConceptBriefDto.builder() + public final ConceptBriefDto CONCEPT_1_BRIEF_DTO = ConceptBriefDto.builder() .id(CONCEPT_1_ID) .uri(CONCEPT_1_URI) .name(CONCEPT_1_NAME) .description(CONCEPT_1_DESCRIPTION) .build(); - public static final TableColumnConcept CONCEPT_1 = TableColumnConcept.builder() + public final TableColumnConcept CONCEPT_1 = TableColumnConcept.builder() .id(CONCEPT_1_ID) .uri(CONCEPT_1_URI) .name(CONCEPT_1_NAME) @@ -305,39 +304,39 @@ public abstract class BaseTest { .created(CONCEPT_1_CREATED) .build(); - public static final EntityDto CONCEPT_1_ENTITY_DTO = EntityDto.builder() + public final EntityDto CONCEPT_1_ENTITY_DTO = EntityDto.builder() .uri(CONCEPT_1_URI) .description(CONCEPT_1_DESCRIPTION) .label(CONCEPT_1_NAME) .build(); - public static final UUID CONCEPT_2_ID = UUID.fromString("c5cf9914-15c1-4813-af11-eb2a070d59a9"); - public static final String CONCEPT_2_NAME = "FAIR data"; - public static final String CONCEPT_2_URI = "http://www.wikidata.org/entity/Q29032648"; - public static final String CONCEPT_2_DESCRIPTION = "data compliant with the terms of the FAIR Data Principles"; - public static final Instant CONCEPT_2_CREATED = Instant.now(); + public final static UUID CONCEPT_2_ID = UUID.fromString("c5cf9914-15c1-4813-af11-eb2a070d59a9"); + public final static String CONCEPT_2_NAME = "FAIR data"; + public final static String CONCEPT_2_URI = "http://www.wikidata.org/entity/Q29032648"; + public final static String CONCEPT_2_DESCRIPTION = "data compliant with the terms of the FAIR Data Principles"; + public final static Instant CONCEPT_2_CREATED = Instant.ofEpochSecond(1701976049L) /* 2023-12-07 19:07:28 (UTC) */; - public static final ConceptSaveDto CONCEPT_2_SAVE_DTO = ConceptSaveDto.builder() + public final ConceptSaveDto CONCEPT_2_SAVE_DTO = ConceptSaveDto.builder() .uri(CONCEPT_2_URI) .name(CONCEPT_2_NAME) .description(CONCEPT_2_DESCRIPTION) .build(); - public static final ConceptDto CONCEPT_2_DTO = ConceptDto.builder() + public final ConceptDto CONCEPT_2_DTO = ConceptDto.builder() .id(CONCEPT_2_ID) .uri(CONCEPT_2_URI) .name(CONCEPT_2_NAME) .description(CONCEPT_2_DESCRIPTION) .build(); - public static final ConceptBriefDto CONCEPT_2_BRIEF_DTO = ConceptBriefDto.builder() + public final ConceptBriefDto CONCEPT_2_BRIEF_DTO = ConceptBriefDto.builder() .id(CONCEPT_2_ID) .uri(CONCEPT_2_URI) .name(CONCEPT_2_NAME) .description(CONCEPT_2_DESCRIPTION) .build(); - public static final TableColumnConcept CONCEPT_2 = TableColumnConcept.builder() + public final TableColumnConcept CONCEPT_2 = TableColumnConcept.builder() .id(CONCEPT_2_ID) .uri(CONCEPT_2_URI) .name(CONCEPT_2_NAME) @@ -345,33 +344,33 @@ public abstract class BaseTest { .created(CONCEPT_2_CREATED) .build(); - public static final UUID UNIT_1_ID = UUID.fromString("1fee60e4-42f8-4883-85a8-e282fddf6a62"); - public static final String UNIT_1_NAME = "millimetre"; - public static final String UNIT_1_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/millimetre"; - public static final String UNIT_1_DESCRIPTION = "The millimetre is a unit of length defined as 1.0e-3 metre."; - public static final Instant UNIT_1_CREATED = Instant.ofEpochSecond(1701976282L) /* 2023-12-07 19:11:22 */; + public final static UUID UNIT_1_ID = UUID.fromString("1fee60e4-42f8-4883-85a8-e282fddf6a62"); + public final static String UNIT_1_NAME = "millimetre"; + public final static String UNIT_1_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/millimetre"; + public final static String UNIT_1_DESCRIPTION = "The millimetre is a unit of length defined as 1.0e-3 metre."; + public final static Instant UNIT_1_CREATED = Instant.ofEpochSecond(1701976282L) /* 2023-12-07 19:11:22 */; - public static final UnitSaveDto UNIT_1_SAVE_DTO = UnitSaveDto.builder() + public final UnitSaveDto UNIT_1_SAVE_DTO = UnitSaveDto.builder() .uri(UNIT_1_URI) .name(UNIT_1_NAME) .description(UNIT_1_DESCRIPTION) .build(); - public static final UnitDto UNIT_1_DTO = UnitDto.builder() + public final UnitDto UNIT_1_DTO = UnitDto.builder() .id(UNIT_1_ID) .uri(UNIT_1_URI) .name(UNIT_1_NAME) .description(UNIT_1_DESCRIPTION) .build(); - public static final UnitBriefDto UNIT_1_BRIEF_DTO = UnitBriefDto.builder() + public final UnitBriefDto UNIT_1_BRIEF_DTO = UnitBriefDto.builder() .id(UNIT_1_ID) .uri(UNIT_1_URI) .name(UNIT_1_NAME) .description(UNIT_1_DESCRIPTION) .build(); - public static final TableColumnUnit UNIT_1 = TableColumnUnit.builder() + public final TableColumnUnit UNIT_1 = TableColumnUnit.builder() .id(UNIT_1_ID) .uri(UNIT_1_URI) .name(UNIT_1_NAME) @@ -379,39 +378,39 @@ public abstract class BaseTest { .created(UNIT_1_CREATED) .build(); - public static final EntityDto UNIT_1_ENTITY_DTO = EntityDto.builder() + public final EntityDto UNIT_1_ENTITY_DTO = EntityDto.builder() .uri(UNIT_1_URI) .description(UNIT_1_DESCRIPTION) .label(UNIT_1_NAME) .build(); - public static final UUID UNIT_2_ID = UUID.fromString("d88591a9-5171-4b12-8381-bcff1cfe7442"); - public static final String UNIT_2_NAME = "tonne"; - public static final String UNIT_2_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/tonne"; - public static final String UNIT_2_DESCRIPTION = "The tonne is a unit of mass defined as 1000 kilogram."; - public static final Instant UNIT_2_CREATED = Instant.ofEpochSecond(1701976462L) /* 2023-12-07 19:14:22 */; + public final static UUID UNIT_2_ID = UUID.fromString("d88591a9-5171-4b12-8381-bcff1cfe7442"); + public final static String UNIT_2_NAME = "tonne"; + public final static String UNIT_2_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/tonne"; + public final static String UNIT_2_DESCRIPTION = "The tonne is a unit of mass defined as 1000 kilogram."; + public final static Instant UNIT_2_CREATED = Instant.ofEpochSecond(1701976462L) /* 2023-12-07 19:14:22 */; - public static final UnitSaveDto UNIT_2_SAVE_DTO = UnitSaveDto.builder() + public final UnitSaveDto UNIT_2_SAVE_DTO = UnitSaveDto.builder() .uri(UNIT_2_URI) .name(UNIT_2_NAME) .description(UNIT_2_DESCRIPTION) .build(); - public static final UnitDto UNIT_2_DTO = UnitDto.builder() + public final UnitDto UNIT_2_DTO = UnitDto.builder() .id(UNIT_2_ID) .uri(UNIT_2_URI) .name(UNIT_2_NAME) .description(UNIT_2_DESCRIPTION) .build(); - public static final UnitBriefDto UNIT_2_BRIEF_DTO = UnitBriefDto.builder() + public final UnitBriefDto UNIT_2_BRIEF_DTO = UnitBriefDto.builder() .id(UNIT_2_ID) .uri(UNIT_2_URI) .name(UNIT_2_NAME) .description(UNIT_2_DESCRIPTION) .build(); - public static final TableColumnUnit UNIT_2 = TableColumnUnit.builder() + public final TableColumnUnit UNIT_2 = TableColumnUnit.builder() .id(UNIT_2_ID) .uri(UNIT_2_URI) .name(UNIT_2_NAME) @@ -419,29 +418,29 @@ public abstract class BaseTest { .created(UNIT_2_CREATED) .build(); - public static final String USER_BROKER_USERNAME = "guest"; + public final static String USER_BROKER_USERNAME = "guest"; @SuppressWarnings("java:S2068") - public static final String USER_BROKER_PASSWORD = "guest"; + public final static String USER_BROKER_PASSWORD = "guest"; - public static final UUID USER_LOCAL_ADMIN_ID = UUID.fromString("a54dcb2e-a644-4e82-87e7-05a96413983d"); - public static final UUID USER_LOCAL_ADMIN_KEYCLOAK_ID = UUID.fromString("703c2ca0-8fc3-4c03-9bc5-4dae6b211e78"); - public static final String USER_LOCAL_ADMIN_USERNAME = "admin"; + public final static UUID USER_LOCAL_ADMIN_ID = UUID.fromString("a54dcb2e-a644-4e82-87e7-05a96413983d"); + public final static UUID USER_LOCAL_ADMIN_KEYCLOAK_ID = UUID.fromString("703c2ca0-8fc3-4c03-9bc5-4dae6b211e78"); + public final static String USER_LOCAL_ADMIN_USERNAME = "admin"; @SuppressWarnings("java:S2068") - public static final String USER_LOCAL_ADMIN_PASSWORD = "admin"; - public static final String USER_LOCAL_ADMIN_THEME = "dark"; - public static final Boolean USER_LOCAL_ADMIN_IS_INTERNAL = true; - public static final Boolean USER_LOCAL_ADMIN_ENABLED = true; + public final static String USER_LOCAL_ADMIN_PASSWORD = "admin"; + public final static String USER_LOCAL_ADMIN_THEME = "dark"; + public final static Boolean USER_LOCAL_ADMIN_IS_INTERNAL = true; + public final static Boolean USER_LOCAL_ADMIN_ENABLED = true; @SuppressWarnings("java:S2068") - public static final String USER_LOCAL_ADMIN_MARIADB_PASSWORD = "*440BA4FD1A87A0999647DB67C0EE258198B247BA"; + public final static String USER_LOCAL_ADMIN_MARIADB_PASSWORD = "*440BA4FD1A87A0999647DB67C0EE258198B247BA"; - public static final UserDetails USER_LOCAL_ADMIN_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_LOCAL_ADMIN_DETAILS = UserDetailsDto.builder() .id(USER_LOCAL_ADMIN_ID.toString()) .username(USER_LOCAL_ADMIN_USERNAME) .password(USER_LOCAL_ADMIN_PASSWORD) .authorities(AUTHORITY_DEFAULT_LOCAL_ADMIN_AUTHORITIES) .build(); - public static final User USER_LOCAL = User.builder() + public final User USER_LOCAL = User.builder() .id(USER_LOCAL_ADMIN_ID) .keycloakId(USER_LOCAL_ADMIN_KEYCLOAK_ID) .username(USER_LOCAL_ADMIN_USERNAME) @@ -450,34 +449,34 @@ public abstract class BaseTest { .isInternal(USER_LOCAL_ADMIN_IS_INTERNAL) .build(); - public static final Principal USER_LOCAL_ADMIN_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_LOCAL_ADMIN_DETAILS, - USER_LOCAL_ADMIN_PASSWORD, USER_LOCAL_ADMIN_DETAILS.getAuthorities()); + public final Principal USER_LOCAL_ADMIN_PRINCIPAL = new UsernamePasswordAuthenticationToken( + USER_LOCAL_ADMIN_DETAILS, USER_LOCAL_ADMIN_PASSWORD, USER_LOCAL_ADMIN_DETAILS.getAuthorities()); - public static final UUID USER_1_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); - public static final UUID USER_1_KEYCLOAK_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); - public static final String USER_1_USERNAME = "junit1"; + public final static UUID USER_1_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); + public final static UUID USER_1_KEYCLOAK_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); + public final static String USER_1_USERNAME = "junit1"; @SuppressWarnings("java:S2068") - public static final String USER_1_PASSWORD = "junit1"; + public final static String USER_1_PASSWORD = "junit1"; @SuppressWarnings("java:S2068") - public static final String USER_1_DATABASE_PASSWORD = "*440BA4FD1A87A0999647DB67C0EE258198B247BA" /* junit1 */; - public static final String USER_1_FIRSTNAME = "John"; - public static final String USER_1_LASTNAME = "Doe"; - public static final String USER_1_QUALIFIED_NAME = USER_1_FIRSTNAME + " " + USER_1_LASTNAME + " — @" + USER_1_USERNAME; - public static final String USER_1_NAME = "John Doe"; - public static final String USER_1_AFFILIATION = "TU Graz"; - public static final String USER_1_ORCID_URL = "https://orcid.org/0000-0003-4216-302X"; - public static final Boolean USER_1_ENABLED = true; - public static final Boolean USER_1_IS_INTERNAL = false; - public static final String USER_1_THEME = "light"; - public static final String USER_1_LANGUAGE = "en"; - public static final Instant USER_1_CREATED = Instant.ofEpochSecond(1677399441L) /* 2023-02-26 08:17:21 (UTC) */; - - public static final UpdateUserPasswordDto USER_1_UPDATE_PASSWORD_DTO = UpdateUserPasswordDto.builder() + public final static String USER_1_DATABASE_PASSWORD = "*440BA4FD1A87A0999647DB67C0EE258198B247BA" /* junit1 */; + public final static String USER_1_FIRSTNAME = "John"; + public final static String USER_1_LASTNAME = "Doe"; + public final static String USER_1_QUALIFIED_NAME = USER_1_FIRSTNAME + " " + USER_1_LASTNAME + " — @" + USER_1_USERNAME; + public final static String USER_1_NAME = "John Doe"; + public final static String USER_1_AFFILIATION = "TU Graz"; + public final static String USER_1_ORCID_URL = "https://orcid.org/0000-0003-4216-302X"; + public final static Boolean USER_1_ENABLED = true; + public final static Boolean USER_1_IS_INTERNAL = false; + public final static String USER_1_THEME = "light"; + public final static String USER_1_LANGUAGE = "en"; + public final static Instant USER_1_CREATED = Instant.ofEpochSecond(1677399441L) /* 2023-02-26 08:17:21 (UTC) */; + + public final UpdateUserPasswordDto USER_1_UPDATE_PASSWORD_DTO = UpdateUserPasswordDto.builder() .username(USER_1_USERNAME) .password(USER_1_PASSWORD) .build(); - public static final UserAttributesDto USER_1_ATTRIBUTES_DTO = UserAttributesDto.builder() + public final UserAttributesDto USER_1_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_1_THEME) .orcid(USER_1_ORCID_URL) .affiliation(USER_1_AFFILIATION) @@ -485,19 +484,19 @@ public abstract class BaseTest { .language(USER_1_LANGUAGE) .build(); - public static final CredentialDto USER_1_KEYCLOAK_CREDENTIAL_1 = CredentialDto.builder() + public final CredentialDto USER_1_KEYCLOAK_CREDENTIAL_1 = CredentialDto.builder() .type(CredentialTypeDto.PASSWORD) .temporary(false) .value(USER_1_PASSWORD) .build(); - public static final CredentialDto USER_LOCAL_KEYCLOAK_CREDENTIAL_1 = CredentialDto.builder() + public final CredentialDto USER_LOCAL_KEYCLOAK_CREDENTIAL_1 = CredentialDto.builder() .type(CredentialTypeDto.PASSWORD) .temporary(false) .value(USER_LOCAL_ADMIN_PASSWORD) .build(); - public static final UserCreateDto USER_1_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() + public final UserCreateDto USER_1_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() .username(USER_1_USERNAME) .enabled(USER_1_ENABLED) .credentials(new LinkedList<>(List.of(USER_1_KEYCLOAK_CREDENTIAL_1))) @@ -506,7 +505,7 @@ public abstract class BaseTest { .build()) .build(); - public static final UserCreateDto USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() + public final UserCreateDto USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() .username(USER_LOCAL_ADMIN_USERNAME) .enabled(USER_LOCAL_ADMIN_ENABLED) .credentials(new LinkedList<>(List.of(USER_LOCAL_KEYCLOAK_CREDENTIAL_1))) @@ -516,7 +515,7 @@ public abstract class BaseTest { .build()) .build(); - public static final User USER_1 = User.builder() + public final User USER_1 = User.builder() .id(USER_1_ID) .keycloakId(USER_1_KEYCLOAK_ID) .username(USER_1_USERNAME) @@ -528,9 +527,10 @@ public abstract class BaseTest { .mariadbPassword(USER_1_DATABASE_PASSWORD) .language(USER_1_LANGUAGE) .isInternal(USER_1_IS_INTERNAL) + .accesses(new LinkedList<>()) .build(); - public static final UserDto USER_1_DTO = UserDto.builder() + public final UserDto USER_1_DTO = UserDto.builder() .id(USER_1_ID) .username(USER_1_USERNAME) .firstname(USER_1_FIRSTNAME) @@ -540,7 +540,7 @@ public abstract class BaseTest { .qualifiedName(USER_1_QUALIFIED_NAME) .build(); - public static final CreateUserDto USER_1_CREATE_USER_DTO = CreateUserDto.builder() + public final CreateUserDto USER_1_CREATE_USER_DTO = CreateUserDto.builder() .id(USER_1_KEYCLOAK_ID) .ldapId(USER_1_ID) .givenName(USER_1_FIRSTNAME) @@ -548,7 +548,7 @@ public abstract class BaseTest { .username(USER_1_USERNAME) .build(); - public static final UserUpdateDto USER_1_UPDATE_DTO = UserUpdateDto.builder() + public final UserUpdateDto USER_1_UPDATE_DTO = UserUpdateDto.builder() .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) @@ -557,11 +557,11 @@ public abstract class BaseTest { .language(USER_1_LANGUAGE) .build(); - public static final UserPasswordDto USER_1_PASSWORD_DTO = UserPasswordDto.builder() + public final UserPasswordDto USER_1_PASSWORD_DTO = UserPasswordDto.builder() .password(USER_1_PASSWORD) .build(); - public static final UserBriefDto USER_1_BRIEF_DTO = UserBriefDto.builder() + public final UserBriefDto USER_1_BRIEF_DTO = UserBriefDto.builder() .id(USER_1_ID) .username(USER_1_USERNAME) .firstname(USER_1_FIRSTNAME) @@ -571,34 +571,34 @@ public abstract class BaseTest { .orcid(USER_1_ORCID_URL) .build(); - public static final UserDetails USER_1_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_1_DETAILS = UserDetailsDto.builder() .id(USER_1_ID.toString()) .username(USER_1_USERNAME) .password(USER_1_PASSWORD) .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); - public static final Principal USER_1_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_1_DETAILS, + public final Principal USER_1_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_1_DETAILS, USER_1_PASSWORD, USER_1_DETAILS.getAuthorities()); - public static final UUID USER_2_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); - public static final UUID USER_2_KEYCLOAK_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); - public static final String USER_2_USERNAME = "junit2"; - public static final String USER_2_FIRSTNAME = "Jane"; - public static final String USER_2_LASTNAME = "Doe"; - public static final String USER_2_NAME = "Jane Doe"; - public static final String USER_2_AFFILIATION = "TU Wien"; - public static final String USER_2_ORCID_URL = "https://orcid.org/0000-0002-9272-6225"; + public final static UUID USER_2_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); + public final static UUID USER_2_KEYCLOAK_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); + public final static String USER_2_USERNAME = "junit2"; + public final static String USER_2_FIRSTNAME = "Jane"; + public final static String USER_2_LASTNAME = "Doe"; + public final static String USER_2_NAME = "Jane Doe"; + public final static String USER_2_AFFILIATION = "TU Wien"; + public final static String USER_2_ORCID_URL = "https://orcid.org/0000-0002-9272-6225"; @SuppressWarnings("java:S2068") - public static final String USER_2_PASSWORD = "junit2"; + public final static String USER_2_PASSWORD = "junit2"; @SuppressWarnings("java:S2068") - public static final String USER_2_DATABASE_PASSWORD = "*9AA70A8B0EEFAFCB5BED5BDEF6EE264D5DA915AE" /* junit2 */; - public static final String USER_2_QUALIFIED_NAME = USER_2_FIRSTNAME + " " + USER_2_LASTNAME + " — @" + USER_2_USERNAME; - public static final Boolean USER_2_IS_INTERNAL = false; - public static final String USER_2_THEME = "light"; - public static final String USER_2_LANGUAGE = "de"; + public final static String USER_2_DATABASE_PASSWORD = "*9AA70A8B0EEFAFCB5BED5BDEF6EE264D5DA915AE" /* junit2 */; + public final static String USER_2_QUALIFIED_NAME = USER_2_FIRSTNAME + " " + USER_2_LASTNAME + " — @" + USER_2_USERNAME; + public final static Boolean USER_2_IS_INTERNAL = false; + public final static String USER_2_THEME = "light"; + public final static String USER_2_LANGUAGE = "de"; - public static final UserAttributesDto USER_2_ATTRIBUTES_DTO = UserAttributesDto.builder() + public final UserAttributesDto USER_2_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_2_THEME) .orcid(USER_2_ORCID_URL) .affiliation(USER_2_AFFILIATION) @@ -606,7 +606,7 @@ public abstract class BaseTest { .language(USER_2_LANGUAGE) .build(); - public static final User USER_2 = User.builder() + public final User USER_2 = User.builder() .id(USER_2_ID) .keycloakId(USER_2_KEYCLOAK_ID) .username(USER_2_USERNAME) @@ -618,9 +618,10 @@ public abstract class BaseTest { .mariadbPassword(USER_2_DATABASE_PASSWORD) .language(USER_2_LANGUAGE) .isInternal(USER_2_IS_INTERNAL) + .accesses(new LinkedList<>()) .build(); - public static final UserDto USER_2_DTO = UserDto.builder() + public final UserDto USER_2_DTO = UserDto.builder() .id(USER_2_ID) .username(USER_2_USERNAME) .firstname(USER_2_FIRSTNAME) @@ -630,7 +631,7 @@ public abstract class BaseTest { .attributes(USER_2_ATTRIBUTES_DTO) .build(); - public static final UserBriefDto USER_2_BRIEF_DTO = UserBriefDto.builder() + public final UserBriefDto USER_2_BRIEF_DTO = UserBriefDto.builder() .id(USER_2_ID) .username(USER_2_USERNAME) .firstname(USER_2_FIRSTNAME) @@ -640,46 +641,46 @@ public abstract class BaseTest { .qualifiedName(USER_2_QUALIFIED_NAME) .build(); - public static final UserDetails USER_2_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_2_DETAILS = UserDetailsDto.builder() .id(USER_2_ID.toString()) .username(USER_2_USERNAME) .password(USER_2_PASSWORD) .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); - public static final at.tuwien.api.amqp.UserDetailsDto USER_2_DETAILS_DTO = at.tuwien.api.amqp.UserDetailsDto.builder() - .name(USER_2_USERNAME) - .tags(new String[]{}) - .build(); + public final at.ac.tuwien.ifs.dbrepo.core.api.amqp.UserDetailsDto USER_2_DETAILS_DTO = + at.ac.tuwien.ifs.dbrepo.core.api.amqp.UserDetailsDto.builder() + .name(USER_2_USERNAME) + .tags(new String[]{}) + .build(); - public static final Principal USER_2_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_2_DETAILS, + public final Principal USER_2_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_2_DETAILS, USER_2_PASSWORD, USER_2_DETAILS.getAuthorities()); - public static final UUID USER_3_ID = UUID.fromString("7b080e33-d8db-4276-9d53-47208e657006"); - public static final UUID USER_3_KEYCLOAK_ID = UUID.fromString("b0108bc3-95aa-4a3f-8868-dc301286aeca"); - public static final String USER_3_USERNAME = "junit3"; - public static final String USER_3_FIRSTNAME = "System"; - public static final String USER_3_LASTNAME = "System"; - public static final String USER_3_NAME = "System System"; - public static final String USER_3_AFFILIATION = "TU Wien"; - public static final String USER_3_ORCID_URL = null; - public static final String USER_3_ORCID_UNCOMPRESSED = null; + public final static UUID USER_3_ID = UUID.fromString("7b080e33-d8db-4276-9d53-47208e657006"); + public final static UUID USER_3_KEYCLOAK_ID = UUID.fromString("b0108bc3-95aa-4a3f-8868-dc301286aeca"); + public final static String USER_3_USERNAME = "junit3"; + public final static String USER_3_FIRSTNAME = "System"; + public final static String USER_3_LASTNAME = "System"; + public final static String USER_3_NAME = "System System"; + public final static String USER_3_AFFILIATION = "TU Wien"; + public final static String USER_3_ORCID_URL = null; @SuppressWarnings("java:S2068") - public static final String USER_3_PASSWORD = "password"; + public final static String USER_3_PASSWORD = "password"; @SuppressWarnings("java:S2068") - public static final String USER_3_DATABASE_PASSWORD = "*D65FCA043964B63E849DD6334699ECB065905DA4" /* junit3 */; - public static final String USER_3_QUALIFIED_NAME = USER_3_FIRSTNAME + " " + USER_3_LASTNAME + " — @" + USER_3_USERNAME; - public static final Boolean USER_3_IS_INTERNAL = false; - public static final String USER_3_THEME = "light"; + public final static String USER_3_DATABASE_PASSWORD = "*D65FCA043964B63E849DD6334699ECB065905DA4" /* junit3 */; + public final static String USER_3_QUALIFIED_NAME = USER_3_FIRSTNAME + " " + USER_3_LASTNAME + " — @" + USER_3_USERNAME; + public final static Boolean USER_3_IS_INTERNAL = false; + public final static String USER_3_THEME = "light"; - public static final UserAttributesDto USER_3_ATTRIBUTES_DTO = UserAttributesDto.builder() + public final UserAttributesDto USER_3_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_3_THEME) - .orcid(USER_3_ORCID_UNCOMPRESSED) + .orcid(USER_3_ORCID_URL) .affiliation(USER_3_AFFILIATION) .mariadbPassword(USER_3_DATABASE_PASSWORD) .build(); - public static final User USER_3 = User.builder() + public final User USER_3 = User.builder() .id(USER_3_ID) .keycloakId(USER_3_KEYCLOAK_ID) .username(USER_3_USERNAME) @@ -690,9 +691,10 @@ public abstract class BaseTest { .theme(USER_3_THEME) .mariadbPassword(USER_3_DATABASE_PASSWORD) .isInternal(USER_3_IS_INTERNAL) + .accesses(new LinkedList<>()) .build(); - public static final UserDto USER_3_DTO = UserDto.builder() + public final UserDto USER_3_DTO = UserDto.builder() .id(USER_3_ID) .username(USER_3_USERNAME) .firstname(USER_3_FIRSTNAME) @@ -702,7 +704,7 @@ public abstract class BaseTest { .attributes(USER_3_ATTRIBUTES_DTO) .build(); - public static final UserBriefDto USER_3_BRIEF_DTO = UserBriefDto.builder() + public final UserBriefDto USER_3_BRIEF_DTO = UserBriefDto.builder() .id(USER_3_ID) .username(USER_3_USERNAME) .firstname(USER_3_FIRSTNAME) @@ -711,45 +713,46 @@ public abstract class BaseTest { .qualifiedName(USER_3_QUALIFIED_NAME) .build(); - public static final UserDetails USER_3_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_3_DETAILS = UserDetailsDto.builder() .id(USER_3_ID.toString()) .username(USER_3_USERNAME) .password(USER_3_PASSWORD) .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); - public static final Principal USER_3_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, + public final Principal USER_3_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, USER_3_PASSWORD, USER_3_DETAILS.getAuthorities()); - public static final at.tuwien.api.amqp.UserDetailsDto USER_3_DETAILS_DTO = at.tuwien.api.amqp.UserDetailsDto.builder() - .name(USER_3_USERNAME) - .tags(new String[]{}) - .build(); - - public static final UUID USER_4_ID = UUID.fromString("791d58c5-bfab-4520-b4fc-b44d4ab9feb0"); - public static final UUID USER_4_KEYCLOAK_ID = UUID.fromString("25040ad3-6d57-4052-b357-6b4c8a6e7f4d"); - public static final String USER_4_USERNAME = "junit4"; - public static final String USER_4_FIRSTNAME = "JUnit"; - public static final String USER_4_LASTNAME = "4"; - public static final String USER_4_NAME = "JUnit 4"; - public static final String USER_4_AFFILIATION = "TU Wien"; - public static final String USER_4_ORCID_URL = null; + public final at.ac.tuwien.ifs.dbrepo.core.api.amqp.UserDetailsDto USER_3_DETAILS_DTO = + at.ac.tuwien.ifs.dbrepo.core.api.amqp.UserDetailsDto.builder() + .name(USER_3_USERNAME) + .tags(new String[]{}) + .build(); + + public final static UUID USER_4_ID = UUID.fromString("791d58c5-bfab-4520-b4fc-b44d4ab9feb0"); + public final static UUID USER_4_KEYCLOAK_ID = UUID.fromString("25040ad3-6d57-4052-b357-6b4c8a6e7f4d"); + public final static String USER_4_USERNAME = "junit4"; + public final static String USER_4_FIRSTNAME = "JUnit"; + public final static String USER_4_LASTNAME = "4"; + public final static String USER_4_NAME = "JUnit 4"; + public final static String USER_4_AFFILIATION = "TU Wien"; + public final static String USER_4_ORCID_URL = null; @SuppressWarnings("java:S2068") - public static final String USER_4_PASSWORD = "junit4"; + public final static String USER_4_PASSWORD = "junit4"; @SuppressWarnings("java:S2068") - public static final String USER_4_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit4 */; - public static final String USER_4_QUALIFIED_NAME = USER_4_FIRSTNAME + " " + USER_4_LASTNAME + " — @" + USER_4_USERNAME; - public static final Boolean USER_4_IS_INTERNAL = false; - public static final String USER_4_THEME = "light"; + public final static String USER_4_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit4 */; + public final static String USER_4_QUALIFIED_NAME = USER_4_FIRSTNAME + " " + USER_4_LASTNAME + " — @" + USER_4_USERNAME; + public final static Boolean USER_4_IS_INTERNAL = false; + public final static String USER_4_THEME = "light"; - public static final UserAttributesDto USER_4_ATTRIBUTES_DTO = UserAttributesDto.builder() + public final UserAttributesDto USER_4_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_4_THEME) .orcid(USER_4_ORCID_URL) .affiliation(USER_4_AFFILIATION) .mariadbPassword(USER_4_DATABASE_PASSWORD) .build(); - public static final User USER_4 = User.builder() + public final User USER_4 = User.builder() .id(USER_4_ID) .keycloakId(USER_4_KEYCLOAK_ID) .username(USER_4_USERNAME) @@ -760,9 +763,10 @@ public abstract class BaseTest { .theme(USER_4_THEME) .mariadbPassword(USER_4_DATABASE_PASSWORD) .isInternal(USER_4_IS_INTERNAL) + .accesses(new LinkedList<>()) .build(); - public static final UserDto USER_4_DTO = UserDto.builder() + public final UserDto USER_4_DTO = UserDto.builder() .id(USER_4_ID) .username(USER_4_USERNAME) .firstname(USER_4_FIRSTNAME) @@ -772,7 +776,7 @@ public abstract class BaseTest { .qualifiedName(USER_4_QUALIFIED_NAME) .build(); - public static final UserBriefDto USER_4_BRIEF_DTO = UserBriefDto.builder() + public final UserBriefDto USER_4_BRIEF_DTO = UserBriefDto.builder() .id(USER_4_ID) .username(USER_4_USERNAME) .firstname(USER_4_FIRSTNAME) @@ -781,38 +785,38 @@ public abstract class BaseTest { .qualifiedName(USER_4_QUALIFIED_NAME) .build(); - public static final UserDetails USER_4_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_4_DETAILS = UserDetailsDto.builder() .id(USER_4_ID.toString()) .username(USER_4_USERNAME) .password(USER_4_PASSWORD) .authorities(new LinkedList<>()) .build(); - public static final Principal USER_4_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_4_DETAILS, + public final Principal USER_4_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_4_DETAILS, USER_4_PASSWORD, USER_4_DETAILS.getAuthorities()); - public static final UUID USER_5_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); - public static final UUID USER_5_KEYCLOAK_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); - public static final String USER_5_USERNAME = "nobody"; - public static final String USER_5_FIRSTNAME = "No"; - public static final String USER_5_LASTNAME = "Body"; - public static final String USER_5_NAME = "No Body"; - public static final String USER_5_AFFILIATION = "TU Wien"; + public final static UUID USER_5_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); + public final static UUID USER_5_KEYCLOAK_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); + public final static String USER_5_USERNAME = "nobody"; + public final static String USER_5_FIRSTNAME = "No"; + public final static String USER_5_LASTNAME = "Body"; + public final static String USER_5_NAME = "No Body"; + public final static String USER_5_AFFILIATION = "TU Wien"; @SuppressWarnings("java:S2068") - public static final String USER_5_PASSWORD = "junit5"; + public final static String USER_5_PASSWORD = "junit5"; @SuppressWarnings("java:S2068") - public static final String USER_5_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit5 */; - public static final String USER_5_QUALIFIED_NAME = USER_5_FIRSTNAME + " " + USER_5_LASTNAME + " — @" + USER_5_USERNAME; - public static final Boolean USER_5_IS_INTERNAL = false; - public static final String USER_5_THEME = "dark"; + public final static String USER_5_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit5 */; + public final static String USER_5_QUALIFIED_NAME = USER_5_FIRSTNAME + " " + USER_5_LASTNAME + " — @" + USER_5_USERNAME; + public final static Boolean USER_5_IS_INTERNAL = false; + public final static String USER_5_THEME = "dark"; - public static final UserAttributesDto USER_5_ATTRIBUTES_DTO = UserAttributesDto.builder() + public final UserAttributesDto USER_5_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_5_THEME) .affiliation(USER_5_AFFILIATION) .mariadbPassword(USER_5_DATABASE_PASSWORD) .build(); - public static final UserDto USER_5_DTO = UserDto.builder() + public final UserDto USER_5_DTO = UserDto.builder() .id(USER_5_ID) .username(USER_5_USERNAME) .firstname(USER_5_FIRSTNAME) @@ -822,7 +826,7 @@ public abstract class BaseTest { .attributes(USER_5_ATTRIBUTES_DTO) .build(); - public static final UserBriefDto USER_5_BRIEF_DTO = UserBriefDto.builder() + public final UserBriefDto USER_5_BRIEF_DTO = UserBriefDto.builder() .id(USER_5_ID) .username(USER_5_USERNAME) .firstname(USER_5_FIRSTNAME) @@ -830,17 +834,17 @@ public abstract class BaseTest { .qualifiedName(USER_5_QUALIFIED_NAME) .build(); - public static final UserDetails USER_5_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_5_DETAILS = UserDetailsDto.builder() .id(USER_5_ID.toString()) .username(USER_5_USERNAME) .password(USER_5_PASSWORD) .authorities(AUTHORITY_DEFAULT_DEVELOPER_AUTHORITIES) .build(); - public static final Principal USER_5_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_5_DETAILS, + public final Principal USER_5_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_5_DETAILS, USER_5_PASSWORD, USER_5_DETAILS.getAuthorities()); - public static final User USER_5 = User.builder() + public final User USER_5 = User.builder() .id(USER_5_ID) .keycloakId(USER_5_KEYCLOAK_ID) .username(USER_5_USERNAME) @@ -850,111 +854,124 @@ public abstract class BaseTest { .theme(USER_5_THEME) .mariadbPassword(USER_5_DATABASE_PASSWORD) .isInternal(USER_5_IS_INTERNAL) + .accesses(new LinkedList<>()) .build(); - public static final UUID USER_6_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); - public static final String USER_6_USERNAME = "system"; - public static final String USER_6_FIRSTNAME = "System"; - public static final String USER_6_LASTNAME = "System"; - public static final String USER_6_NAME = "System System"; - public static final String USER_6_AFFILIATION = "TU Wien"; - public static final String USER_6_ORCID = null; + public final static UUID USER_6_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); + public final static UUID USER_6_KEYCLOAK_ID = UUID.fromString("0fddf102-8958-4223-8653-5d4dc51b3a18"); + public final static String USER_6_USERNAME = "system"; + public final static String USER_6_FIRSTNAME = "System"; + public final static String USER_6_LASTNAME = "System"; + public final static String USER_6_NAME = "System System"; + public final static String USER_6_AFFILIATION = "TU Wien"; + public final static String USER_6_ORCID = null; @SuppressWarnings("java:S2068") - public static final String USER_6_PASSWORD = "junit5"; + public final static String USER_6_PASSWORD = "junit5"; @SuppressWarnings("java:S2068") - public static final String USER_6_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit5 */; - public static final Boolean USER_6_VERIFIED = true; - public static final Boolean USER_6_ENABLED = true; - public static final Boolean USER_6_IS_INTERNAL = false; - public static final Boolean USER_6_THEME_DARK = false; - public static final Instant USER_6_CREATED = Instant.ofEpochSecond(1677399592L) /* 2023-02-26 08:19:52 (UTC) */; - public static final UUID USER_6_REALM_ID = REALM_DBREPO_ID; - - public static final UserDto USER_6_DTO = UserDto.builder() + public final static String USER_6_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit5 */; + public final static Boolean USER_6_VERIFIED = true; + public final static Boolean USER_6_ENABLED = true; + public final static Boolean USER_6_IS_INTERNAL = false; + public final static String USER_6_THEME = "light"; + public final static Instant USER_6_CREATED = Instant.ofEpochSecond(1677399592L) /* 2023-02-26 08:19:52 (UTC) */; + + public final User USER_6 = User.builder() + .id(USER_6_ID) + .keycloakId(USER_6_KEYCLOAK_ID) + .username(USER_6_USERNAME) + .firstname(USER_6_FIRSTNAME) + .lastname(USER_6_LASTNAME) + .affiliation(USER_6_AFFILIATION) + .theme(USER_6_THEME) + .mariadbPassword(USER_6_DATABASE_PASSWORD) + .isInternal(USER_6_IS_INTERNAL) + .accesses(new LinkedList<>()) + .build(); + + public final UserDto USER_6_DTO = UserDto.builder() .id(USER_6_ID) .username(USER_6_USERNAME) .firstname(USER_6_FIRSTNAME) .lastname(USER_6_LASTNAME) .build(); - public static final UserDetails USER_6_DETAILS = UserDetailsDto.builder() + public final UserDetails USER_6_DETAILS = UserDetailsDto.builder() .id(USER_6_ID.toString()) .username(USER_6_USERNAME) .password(USER_6_PASSWORD) .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); - public static final Principal USER_6_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_6_DETAILS, + public final Principal USER_6_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_6_DETAILS, USER_6_PASSWORD, USER_6_DETAILS.getAuthorities()); - public static final UUID IMAGE_1_ID = UUID.fromString("e5449ade-acc1-4ba4-8858-e3496cdecd9c"); - public static final String IMAGE_1_REGISTRY = "docker.io"; - public static final String IMAGE_1_NAME = "mariadb"; - public static final String IMAGE_1_VERSION = "11.1.3"; - public static final String IMAGE_1_DIALECT = "org.hibernate.dialect.MariaDBDialect"; - public static final String IMAGE_1_DRIVER = "org.mariadb.jdbc.Driver"; - public static final String IMAGE_1_JDBC = "mariadb"; - public static final Integer IMAGE_1_PORT = 3306; - public static final Boolean IMAGE_1_IS_DEFAULT = true; - - public static final ImageCreateDto IMAGE_1_CREATE_DTO = ImageCreateDto.builder() + public final static UUID IMAGE_1_ID = UUID.fromString("e5449ade-acc1-4ba4-8858-e3496cdecd9c"); + public final static String IMAGE_1_REGISTRY = "docker.io"; + public final static String IMAGE_1_NAME = "mariadb"; + public final static String IMAGE_1_VERSION = "11.1.3"; + public final static String IMAGE_1_DIALECT = "org.hibernate.dialect.MariaDBDialect"; + public final static String IMAGE_1_DRIVER = "org.mariadb.jdbc.Driver"; + public final static String IMAGE_1_JDBC_METHOD = "mariadb"; + public final static Integer IMAGE_1_DEFAULT_PORT = 3306; + public final static Boolean IMAGE_1_IS_DEFAULT = true; + + public final ImageCreateDto IMAGE_1_CREATE_DTO = ImageCreateDto.builder() .registry(IMAGE_1_REGISTRY) .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .driverClass(IMAGE_1_DRIVER) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .build(); - public static final ImageChangeDto IMAGE_1_CHANGE_DTO = ImageChangeDto.builder() + public final ImageChangeDto IMAGE_1_CHANGE_DTO = ImageChangeDto.builder() .registry(IMAGE_1_REGISTRY) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .driverClass(IMAGE_1_DRIVER) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .build(); - public static final ContainerImage IMAGE_1 = ContainerImage.builder() + public final ContainerImage IMAGE_1 = ContainerImage.builder() .id(IMAGE_1_ID) .name(IMAGE_1_NAME) .registry(IMAGE_1_REGISTRY) .version(IMAGE_1_VERSION) .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .driverClass(IMAGE_1_DRIVER) - .defaultPort(IMAGE_1_PORT) + .defaultPort(IMAGE_1_DEFAULT_PORT) .isDefault(IMAGE_1_IS_DEFAULT) - .operators(new LinkedList<>()) /* IMAGE_1_OPERATORS */ + .operators(null) .build(); - public static final ImageDto IMAGE_1_DTO = ImageDto.builder() + public final ImageDto IMAGE_1_DTO = ImageDto.builder() .id(IMAGE_1_ID) .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) .isDefault(IMAGE_1_IS_DEFAULT) - .jdbcMethod(IMAGE_1_JDBC) + .jdbcMethod(IMAGE_1_JDBC_METHOD) .operators(null) /* IMAGE_1_OPERATORS_DTO */ .build(); - public static final ImageBriefDto IMAGE_1_BRIEF_DTO = ImageBriefDto.builder() + public final ImageBriefDto IMAGE_1_BRIEF_DTO = ImageBriefDto.builder() .id(IMAGE_1_ID) .name(IMAGE_1_NAME) .version(IMAGE_1_VERSION) .isDefault(IMAGE_1_IS_DEFAULT) .build(); - public static final UUID IMAGE_1_OPERATORS_1_ID = UUID.fromString("42a56348-38bd-4aba-b0f2-ac813d5d2da1"); - public static final String IMAGE_1_OPERATORS_1_DISPLAY_NAME = "XOR"; - public static final String IMAGE_1_OPERATORS_1_VALUE = "XOR"; - public static final String IMAGE_1_OPERATORS_1_DOCUMENTATION = "https://mariadb.com/kb/en/xor/"; + public final static UUID IMAGE_1_OPERATORS_1_ID = UUID.fromString("42a56348-38bd-4aba-b0f2-ac813d5d2da1"); + public final static String IMAGE_1_OPERATORS_1_DISPLAY_NAME = "XOR"; + public final static String IMAGE_1_OPERATORS_1_VALUE = "XOR"; + public final static String IMAGE_1_OPERATORS_1_DOCUMENTATION = "https://mariadb.com/kb/en/xor/"; + public final static UUID IMAGE_1_OPERATORS_2_ID = UUID.fromString("42a56348-38bd-4aba-b0f2-ac813d5d2da2"); + public final static String IMAGE_1_OPERATORS_2_DISPLAY_NAME = "="; + public final static String IMAGE_1_OPERATORS_2_VALUE = "="; + public final static String IMAGE_1_OPERATORS_2_DOCUMENTATION = "https://mariadb.com/kb/en/equal/"; - public static final UUID IMAGE_1_OPERATORS_2_ID = UUID.fromString("42a56348-38bd-4aba-b0f2-ac813d5d2da2"); - public static final String IMAGE_1_OPERATORS_2_DISPLAY_NAME = "="; - public static final String IMAGE_1_OPERATORS_2_VALUE = "="; - public static final String IMAGE_1_OPERATORS_2_DOCUMENTATION = "https://mariadb.com/kb/en/equal/"; - - public static final List<Operator> IMAGE_1_OPERATORS = new LinkedList<>(List.of( + public final List<Operator> IMAGE_1_OPERATORS = new LinkedList<>(List.of( Operator.builder() .id(IMAGE_1_OPERATORS_1_ID) .image(IMAGE_1) @@ -970,7 +987,7 @@ public abstract class BaseTest { .documentation(IMAGE_1_OPERATORS_2_DOCUMENTATION) .build())); - public static final List<OperatorDto> IMAGE_1_OPERATORS_DTO = new LinkedList<>(List.of( + public final List<OperatorDto> IMAGE_1_OPERATORS_DTO = new LinkedList<>(List.of( OperatorDto.builder() .id(IMAGE_1_OPERATORS_1_ID) .displayName(IMAGE_1_OPERATORS_1_DISPLAY_NAME) @@ -984,25 +1001,25 @@ public abstract class BaseTest { .documentation(IMAGE_1_OPERATORS_2_DOCUMENTATION) .build())); - public static final UUID CONTAINER_1_ID = UUID.fromString("7ddb7e87-b965-43a2-9a24-4fa406d998f4"); - public static final String CONTAINER_1_NAME = "u01"; - public static final String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-u01"; - public static final String CONTAINER_1_UI_HOST = "localhost"; - public static final Integer CONTAINER_1_UI_PORT = 3306; - public static final String CONTAINER_1_UI_ADDITIONAL_FLAGS = "?sslMode=disable"; - public static final Integer CONTAINER_1_QUOTA = 4; - public static final Integer CONTAINER_1_COUNT = 3; - public static final String CONTAINER_1_HOST = "localhost"; - public static final Integer CONTAINER_1_PORT = 3308; - public static final String CONTAINER_1_PRIVILEGED_USERNAME = "root"; + public final static UUID CONTAINER_1_ID = UUID.fromString("7ddb7e87-b965-43a2-9a24-4fa406d998f4"); + public final static String CONTAINER_1_NAME = "u01"; + public final static String CONTAINER_1_INTERNAL_NAME = "dbrepo-userdb-u01"; + public final static String CONTAINER_1_UI_HOST = "localhost"; + public final static Integer CONTAINER_1_UI_PORT = 3306; + public final static String CONTAINER_1_UI_ADDITIONAL_FLAGS = "?sslMode=disable"; + public final static Integer CONTAINER_1_QUOTA = 4; + public final static Integer CONTAINER_1_COUNT = 3; + public final static String CONTAINER_1_HOST = "localhost"; + public final static Integer CONTAINER_1_PORT = 3308; + public final static String CONTAINER_1_PRIVILEGED_USERNAME = "root"; @SuppressWarnings("java:S2068") - public static final String CONTAINER_1_PRIVILEGED_PASSWORD = "dbrepo"; - public static final Instant CONTAINER_1_CREATED = Instant.ofEpochSecond(1677399629L) /* 2023-02-26 08:20:29 (UTC) */; + public final static String CONTAINER_1_PRIVILEGED_PASSWORD = "dbrepo"; + public final static Instant CONTAINER_1_CREATED = Instant.ofEpochSecond(1677399629L) /* 2023-02-26 08:20:29 (UTC) */; - public static final Container CONTAINER_1 = Container.builder() + public final Container CONTAINER_1 = Container.builder() .id(CONTAINER_1_ID) .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) + .internalName(CONTAINER_1_INTERNAL_NAME) .image(IMAGE_1) .created(CONTAINER_1_CREATED) .host(CONTAINER_1_HOST) @@ -1013,31 +1030,31 @@ public abstract class BaseTest { .uiAdditionalFlags(CONTAINER_1_UI_ADDITIONAL_FLAGS) .privilegedUsername(CONTAINER_1_PRIVILEGED_USERNAME) .privilegedPassword(CONTAINER_1_PRIVILEGED_PASSWORD) - .databases(null) /* DATABASE_1, DATABASE_2, DATABASE_3 */ + .databases(new LinkedList<>()) .build(); - public static final ContainerDto CONTAINER_1_DTO = ContainerDto.builder() + public final ContainerDto CONTAINER_1_DTO = ContainerDto.builder() .id(CONTAINER_1_ID) .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) + .internalName(CONTAINER_1_INTERNAL_NAME) .image(IMAGE_1_DTO) .host(CONTAINER_1_HOST) .port(CONTAINER_1_PORT) .build(); - public static final ContainerBriefDto CONTAINER_1_BRIEF_DTO = ContainerBriefDto.builder() + public final ContainerBriefDto CONTAINER_1_BRIEF_DTO = ContainerBriefDto.builder() .id(CONTAINER_1_ID) .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) + .internalName(CONTAINER_1_INTERNAL_NAME) .quota(CONTAINER_1_QUOTA) .count(CONTAINER_1_COUNT) .image(IMAGE_1_BRIEF_DTO) .build(); - public static final ContainerDto CONTAINER_1_PRIVILEGED_DTO = ContainerDto.builder() + public final ContainerDto CONTAINER_1_PRIVILEGED_DTO = ContainerDto.builder() .id(CONTAINER_1_ID) .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) + .internalName(CONTAINER_1_INTERNAL_NAME) .image(IMAGE_1_DTO) .host(CONTAINER_1_HOST) .port(CONTAINER_1_PORT) @@ -1046,25 +1063,23 @@ public abstract class BaseTest { .password(CONTAINER_1_PRIVILEGED_PASSWORD) .build(); - public static final UUID CONTAINER_2_ID = UUID.fromString("c2ec601e-2bfb-4be8-8891-0cb804a08d4a"); - public static final ContainerImage CONTAINER_2_IMAGE = IMAGE_1; - public static final ImageDto CONTAINER_2_IMAGE_DTO = IMAGE_1_DTO; - public static final String CONTAINER_2_NAME = "u02"; - public static final String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-u02"; - public static final String CONTAINER_2_HOST = "localhost"; - public static final Integer CONTAINER_2_PORT = 3309; - public static final Integer CONTAINER_2_QUOTA = 3; - public static final Integer CONTAINER_2_COUNT = 3; - public static final String CONTAINER_2_PRIVILEGED_USERNAME = "root"; + public final static UUID CONTAINER_2_ID = UUID.fromString("c2ec601e-2bfb-4be8-8891-0cb804a08d4a"); + public final static String CONTAINER_2_NAME = "u02"; + public final static String CONTAINER_2_INTERNAL_NAME = "dbrepo-userdb-u02"; + public final static String CONTAINER_2_HOST = "localhost"; + public final static Integer CONTAINER_2_PORT = 3309; + public final static Integer CONTAINER_2_QUOTA = 3; + public final static Integer CONTAINER_2_COUNT = 3; + public final static String CONTAINER_2_PRIVILEGED_USERNAME = "root"; @SuppressWarnings("java:S2068") - public static final String CONTAINER_2_PRIVILEGED_PASSWORD = "dbrepo"; - public static final Instant CONTAINER_2_CREATED = Instant.ofEpochSecond(1677399655L) /* 2023-02-26 08:20:55 (UTC) */; + public final static String CONTAINER_2_PRIVILEGED_PASSWORD = "dbrepo"; + public final static Instant CONTAINER_2_CREATED = Instant.ofEpochSecond(1677399655L) /* 2023-02-26 08:20:55 (UTC) */; - public static final Container CONTAINER_2 = Container.builder() + public final Container CONTAINER_2 = Container.builder() .id(CONTAINER_2_ID) .name(CONTAINER_2_NAME) - .internalName(CONTAINER_2_INTERNALNAME) - .image(CONTAINER_2_IMAGE) + .internalName(CONTAINER_2_INTERNAL_NAME) + .image(IMAGE_1) .created(CONTAINER_2_CREATED) .host(CONTAINER_2_HOST) .port(CONTAINER_2_PORT) @@ -1074,27 +1089,27 @@ public abstract class BaseTest { .privilegedPassword(CONTAINER_2_PRIVILEGED_PASSWORD) .build(); - public static final ContainerDto CONTAINER_2_DTO = ContainerDto.builder() + public final ContainerDto CONTAINER_2_DTO = ContainerDto.builder() .id(CONTAINER_2_ID) .name(CONTAINER_2_NAME) - .internalName(CONTAINER_2_INTERNALNAME) - .image(CONTAINER_2_IMAGE_DTO) + .internalName(CONTAINER_2_INTERNAL_NAME) + .image(IMAGE_1_DTO) .host(CONTAINER_2_HOST) .port(CONTAINER_2_PORT) .build(); - public static final ContainerBriefDto CONTAINER_2_DTO_BRIEF = ContainerBriefDto.builder() + public final ContainerBriefDto CONTAINER_2_DTO_BRIEF = ContainerBriefDto.builder() .id(CONTAINER_2_ID) .name(CONTAINER_2_NAME) - .internalName(CONTAINER_2_INTERNALNAME) + .internalName(CONTAINER_2_INTERNAL_NAME) .quota(CONTAINER_2_QUOTA) .build(); - public static final ContainerDto CONTAINER_2_PRIVILEGED_DTO = ContainerDto.builder() + public final ContainerDto CONTAINER_2_PRIVILEGED_DTO = ContainerDto.builder() .id(CONTAINER_2_ID) .name(CONTAINER_2_NAME) - .internalName(CONTAINER_2_INTERNALNAME) - .image(CONTAINER_2_IMAGE_DTO) + .internalName(CONTAINER_2_INTERNAL_NAME) + .image(IMAGE_1_DTO) .host(CONTAINER_2_HOST) .port(CONTAINER_2_PORT) .lastRetrieved(Instant.now()) @@ -1102,49 +1117,47 @@ public abstract class BaseTest { .password(CONTAINER_2_PRIVILEGED_PASSWORD) .build(); - public static final UUID CONTAINER_3_ID = UUID.fromString("1731c7d2-8bd1-4392-85bc-18a3be99e01d"); - public static final ContainerImage CONTAINER_3_IMAGE = IMAGE_1; - public static final String CONTAINER_3_NAME = "u03"; - public static final String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-u03"; - public static final String CONTAINER_3_HOST = "localhost"; - public static final Integer CONTAINER_3_PORT = 3310; - public static final Integer CONTAINER_3_QUOTA = 20; - public static final String CONTAINER_3_PRIVILEGED_USERNAME = "root"; + public final static UUID CONTAINER_3_ID = UUID.fromString("1731c7d2-8bd1-4392-85bc-18a3be99e01d"); + public final static String CONTAINER_3_NAME = "u03"; + public final static String CONTAINER_3_INTERNAL_NAME = "dbrepo-userdb-u03"; + public final static String CONTAINER_3_HOST = "localhost"; + public final static Integer CONTAINER_3_PORT = 3310; + public final static Integer CONTAINER_3_QUOTA = 20; + public final static String CONTAINER_3_PRIVILEGED_USERNAME = "root"; @SuppressWarnings("java:S2068") - public static final String CONTAINER_3_PRIVILEGED_PASSWORD = "dbrepo"; - public static final Instant CONTAINER_3_CREATED = Instant.ofEpochSecond(1677399672L) /* 2023-02-26 08:21:12 (UTC) */; + public final static String CONTAINER_3_PRIVILEGED_PASSWORD = "dbrepo"; + public final static Instant CONTAINER_3_CREATED = Instant.ofEpochSecond(1677399672L) /* 2023-02-26 08:21:12 (UTC) */; - public static final Container CONTAINER_3 = Container.builder() + public final Container CONTAINER_3 = Container.builder() .id(CONTAINER_3_ID) .name(CONTAINER_3_NAME) - .internalName(CONTAINER_3_INTERNALNAME) - .image(CONTAINER_3_IMAGE) + .internalName(CONTAINER_3_INTERNAL_NAME) + .image(IMAGE_1) .created(CONTAINER_3_CREATED) .host(CONTAINER_3_HOST) .port(CONTAINER_3_PORT) .quota(CONTAINER_3_QUOTA) - .databases(new LinkedList<>(List.of())) + .databases(new LinkedList<>()) .privilegedUsername(CONTAINER_3_PRIVILEGED_USERNAME) .privilegedPassword(CONTAINER_3_PRIVILEGED_PASSWORD) .build(); - public static final UUID CONTAINER_4_ID = UUID.fromString("67aee75c-791c-410b-abbb-175c11ddd252"); - public static final ContainerImage CONTAINER_4_IMAGE = IMAGE_1; - public static final String CONTAINER_4_NAME = "u04"; - public static final String CONTAINER_4_INTERNALNAME = "dbrepo-userdb-u04"; - public static final String CONTAINER_4_HOST = "localhost"; - public static final Integer CONTAINER_4_PORT = 3311; - public static final Integer CONTAINER_4_QUOTA = 0; - public static final String CONTAINER_4_PRIVILEGED_USERNAME = "root"; + public final static UUID CONTAINER_4_ID = UUID.fromString("67aee75c-791c-410b-abbb-175c11ddd252"); + public final static String CONTAINER_4_NAME = "u04"; + public final static String CONTAINER_4_INTERNAL_NAME = "dbrepo-userdb-u04"; + public final static String CONTAINER_4_HOST = "localhost"; + public final static Integer CONTAINER_4_PORT = 3311; + public final static Integer CONTAINER_4_QUOTA = 0; + public final static String CONTAINER_4_PRIVILEGED_USERNAME = "root"; @SuppressWarnings("java:S2068") - public static final String CONTAINER_4_PRIVILEGED_PASSWORD = "dbrepo"; - public static final Instant CONTAINER_4_CREATED = Instant.ofEpochSecond(1677399688L) /* 2023-02-26 08:21:28 (UTC) */; + public final static String CONTAINER_4_PRIVILEGED_PASSWORD = "dbrepo"; + public final static Instant CONTAINER_4_CREATED = Instant.ofEpochSecond(1677399688L) /* 2023-02-26 08:21:28 (UTC) */; - public static final Container CONTAINER_4 = Container.builder() + public final Container CONTAINER_4 = Container.builder() .id(CONTAINER_4_ID) .name(CONTAINER_4_NAME) - .internalName(CONTAINER_4_INTERNALNAME) - .image(CONTAINER_4_IMAGE) + .internalName(CONTAINER_4_INTERNAL_NAME) + .image(IMAGE_1) .created(CONTAINER_4_CREATED) .host(CONTAINER_4_HOST) .port(CONTAINER_4_PORT) @@ -1154,14 +1167,14 @@ public abstract class BaseTest { .databases(null) /* DATABASE_4 */ .build(); - public static final String EXCHANGE_DBREPO_NAME = "dbrepo"; - public static final Boolean EXCHANGE_DBREPO_AUTO_DELETE = true; - public static final Boolean EXCHANGE_DBREPO_DURABLE = true; - public static final Boolean EXCHANGE_DBREPO_INTERNAL = true; - public static final String EXCHANGE_DBREPO_TYPE = "topic"; - public static final String EXCHANGE_DBREPO_VHOST = "dbrepo"; + public final static String EXCHANGE_DBREPO_NAME = "dbrepo"; + public final static Boolean EXCHANGE_DBREPO_AUTO_DELETE = true; + public final static Boolean EXCHANGE_DBREPO_DURABLE = true; + public final static Boolean EXCHANGE_DBREPO_INTERNAL = true; + public final static String EXCHANGE_DBREPO_TYPE = "topic"; + public final static String EXCHANGE_DBREPO_VHOST = "dbrepo"; - public static final ExchangeDto EXCHANGE_DBREPO_DTO = ExchangeDto.builder() + public final ExchangeDto EXCHANGE_DBREPO_DTO = ExchangeDto.builder() .autoDelete(EXCHANGE_DBREPO_AUTO_DELETE) .type(EXCHANGE_DBREPO_TYPE) .name(EXCHANGE_DBREPO_NAME) @@ -1170,25 +1183,26 @@ public abstract class BaseTest { .internal(EXCHANGE_DBREPO_INTERNAL) .build(); - public static final UUID DATABASE_1_ID = UUID.fromString("b3bcb5bf-4f88-40e2-9726-9b0d2ee2b425"); - public static final String DATABASE_1_NAME = "Weather"; - public static final String DATABASE_1_DESCRIPTION = "Weather in Australia"; - public static final String DATABASE_1_INTERNALNAME = "weather"; - public static final Boolean DATABASE_1_PUBLIC = false; - public static final Boolean DATABASE_1_SCHEMA_PUBLIC = false; - public static final String DATABASE_1_EXCHANGE = "dbrepo"; - public static final Instant DATABASE_1_CREATED = Instant.ofEpochSecond(1677399741L) /* 2023-02-26 08:22:21 (UTC) */; - public static final Instant DATABASE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399741L) /* 2023-02-26 08:22:21 (UTC) */; - public static final UUID DATABASE_1_CREATED_BY = USER_1_ID; + public final static UUID DATABASE_1_ID = UUID.fromString("b3bcb5bf-4f88-40e2-9726-9b0d2ee2b425"); + public final static String DATABASE_1_NAME = "Weather"; + public final static String DATABASE_1_DESCRIPTION = "Weather in Australia"; + public final static String DATABASE_1_INTERNAL_NAME = "weather"; + public final static Boolean DATABASE_1_PUBLIC = false; + public final static Boolean DATABASE_1_SCHEMA_PUBLIC = false; + public final static Boolean DATABASE_1_DASHBOARD_ENABLED = false; + public final static String DATABASE_1_DASHBOARD_UID = "730f0bdde6cf1b"; + public final static String DATABASE_1_EXCHANGE = "dbrepo"; + public final static Instant DATABASE_1_CREATED = Instant.ofEpochSecond(1677399741L) /* 2023-02-26 08:22:21 (UTC) */; + public final static Instant DATABASE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399741L) /* 2023-02-26 08:22:21 (UTC) */; - public static final CreateDatabaseDto DATABASE_1_CREATE = CreateDatabaseDto.builder() + public final CreateDatabaseDto DATABASE_1_CREATE = CreateDatabaseDto.builder() .name(DATABASE_1_NAME) .isPublic(DATABASE_1_PUBLIC) .cid(CONTAINER_1_ID) .build(); - public static final at.tuwien.api.database.internal.CreateDatabaseDto DATABASE_1_CREATE_INTERNAL = at.tuwien.api.database.internal.CreateDatabaseDto.builder() - .internalName(DATABASE_1_INTERNALNAME) + public final at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto DATABASE_1_CREATE_INTERNAL = at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto.builder() + .internalName(DATABASE_1_INTERNAL_NAME) .containerId(CONTAINER_1_ID) .username(USER_1_USERNAME) .password(USER_1_PASSWORD) @@ -1197,41 +1211,44 @@ public abstract class BaseTest { .privilegedPassword(CONTAINER_1_PRIVILEGED_PASSWORD) .build(); - public static final UUID DATABASE_2_ID = UUID.fromString("dd9dfee2-9fbd-46b0-92d5-98f0f8866ffe"); - public static final String DATABASE_2_NAME = "Zoo"; - public static final String DATABASE_2_DESCRIPTION = "Zoo data"; - public static final String DATABASE_2_INTERNALNAME = "zoo"; - public static final Boolean DATABASE_2_PUBLIC = false; - public static final Boolean DATABASE_2_SCHEMA_PUBLIC = true; - public static final String DATABASE_2_EXCHANGE = "dbrepo"; - public static final Instant DATABASE_2_CREATED = Instant.ofEpochSecond(1677399772L) /* 2023-02-26 08:22:52 (UTC) */; - public static final Instant DATABASE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677399772L) /* 2023-02-26 08:22:52 (UTC) */; - public static final UUID DATABASE_2_OWNER = USER_2_ID; - public static final UUID DATABASE_2_CREATOR = USER_2_ID; + public final static UUID DATABASE_2_ID = UUID.fromString("dd9dfee2-9fbd-46b0-92d5-98f0f8866ffe"); + public final static String DATABASE_2_NAME = "Zoo"; + public final static String DATABASE_2_DESCRIPTION = "Zoo data"; + public final static String DATABASE_2_INTERNAL_NAME = "zoo"; + public final static Boolean DATABASE_2_PUBLIC = false; + public final static Boolean DATABASE_2_SCHEMA_PUBLIC = true; + public final static Boolean DATABASE_2_DASHBOARD_ENABLED = true; + public final static String DATABASE_2_DASHBOARD_UID = "c6ab10f377148c"; + public final static String DATABASE_2_EXCHANGE = "dbrepo"; + public final static Instant DATABASE_2_CREATED = Instant.ofEpochSecond(1677399772L) /* 2023-02-26 08:22:52 (UTC) */; + public final static Instant DATABASE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677399772L) /* 2023-02-26 08:22:52 (UTC) */; - public static final CreateDatabaseDto DATABASE_2_CREATE = CreateDatabaseDto.builder() + public final CreateDatabaseDto DATABASE_2_CREATE = CreateDatabaseDto.builder() .name(DATABASE_2_NAME) .isPublic(DATABASE_2_PUBLIC) .cid(CONTAINER_1_ID) .build(); - public static final UUID DATABASE_3_ID = UUID.fromString("9d8cb9a9-9468-4801-a2e0-2dac8bc67c31"); - public static final String DATABASE_3_NAME = "Musicology"; - public static final String DATABASE_3_DESCRIPTION = "Musicology data"; - public static final String DATABASE_3_INTERNALNAME = "musicology"; - public static final Boolean DATABASE_3_PUBLIC = true; - public static final Boolean DATABASE_3_SCHEMA_PUBLIC = false; - public static final String DATABASE_3_EXCHANGE = "dbrepo"; - public static final Instant DATABASE_3_CREATED = Instant.ofEpochSecond(1677399792L) /* 2023-02-26 08:23:12 (UTC) */; - public static final Instant DATABASE_3_LAST_MODIFIED = Instant.ofEpochSecond(1677399792L) /* 2023-02-26 08:23:12 (UTC) */; - public static final UUID DATABASE_3_OWNER = USER_3_ID; + public final static UUID DATABASE_3_ID = UUID.fromString("9d8cb9a9-9468-4801-a2e0-2dac8bc67c31"); + public final static String DATABASE_3_NAME = "Musicology"; + public final static String DATABASE_3_DESCRIPTION = "Musicology data"; + public final static String DATABASE_3_INTERNAL_NAME = "musicology"; + public final static Boolean DATABASE_3_PUBLIC = true; + public final static Boolean DATABASE_3_SCHEMA_PUBLIC = false; + public final static String DATABASE_3_DASHBOARD_UID = "96ef37d5d1b0d1"; + public final static Boolean DATABASE_3_DASHBOARD_ENABLED = true; + public final static String DATABASE_3_EXCHANGE = "dbrepo"; + public final static Instant DATABASE_3_CREATED = Instant.ofEpochSecond(1677399792L) /* 2023-02-26 08:23:12 (UTC) */; + public final static Instant DATABASE_3_LAST_MODIFIED = Instant.ofEpochSecond(1677399792L) /* 2023-02-26 08:23:12 (UTC) */; - public static final DatabaseDto DATABASE_3_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_3_DTO = DatabaseDto.builder() .id(DATABASE_3_ID) .isPublic(DATABASE_3_PUBLIC) .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_3_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_3_DASHBOARD_UID) .name(DATABASE_3_NAME) - .internalName(DATABASE_3_INTERNALNAME) + .internalName(DATABASE_3_INTERNAL_NAME) .owner(USER_3_BRIEF_DTO) .container(CONTAINER_1_DTO) .exchangeName(DATABASE_3_EXCHANGE) @@ -1240,12 +1257,12 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) /* IDENTIFIER_6_DTO */ .build(); - public static final DatabaseDto DATABASE_3_PRIVILEGED_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_3_PRIVILEGED_DTO = DatabaseDto.builder() .id(DATABASE_3_ID) .isPublic(DATABASE_3_PUBLIC) .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) .name(DATABASE_3_NAME) - .internalName(DATABASE_3_INTERNALNAME) + .internalName(DATABASE_3_INTERNAL_NAME) .owner(USER_3_BRIEF_DTO) .container(CONTAINER_1_PRIVILEGED_DTO) .exchangeName(DATABASE_3_EXCHANGE) @@ -1255,63 +1272,63 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); - public static final DatabaseBriefDto DATABASE_3_PRIVILEGED_BRIEF_DTO = DatabaseBriefDto.builder() + public 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) + .internalName(DATABASE_3_INTERNAL_NAME) .ownerId(USER_3_ID) .identifiers(new LinkedList<>()) /* IDENTIFIER_6_DTO */ .build(); - public static final DatabaseBriefDto DATABASE_3_BRIEF_DTO = DatabaseBriefDto.builder() + public final DatabaseBriefDto DATABASE_3_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) + .internalName(DATABASE_3_INTERNAL_NAME) .ownerId(USER_3_ID) .identifiers(new LinkedList<>()) .build(); - public static final CreateDatabaseDto DATABASE_3_CREATE = CreateDatabaseDto.builder() + public final CreateDatabaseDto DATABASE_3_CREATE = CreateDatabaseDto.builder() .name(DATABASE_3_NAME) .isPublic(DATABASE_3_PUBLIC) .cid(CONTAINER_1_ID) .build(); - public static final UUID DATABASE_4_ID = UUID.fromString("c503d7f3-5952-4d97-b26a-da86bea4c20d"); - public static final String DATABASE_4_NAME = "Weather AT"; - public static final String DATABASE_4_DESCRIPTION = "Weather data"; - public static final Boolean DATABASE_4_PUBLIC = true; - public static final Boolean DATABASE_4_SCHEMA_PUBLIC = true; - public static final String DATABASE_4_INTERNALNAME = "weather_at"; - public static final String DATABASE_4_EXCHANGE = "dbrepo"; - public static final Instant DATABASE_4_CREATED = Instant.ofEpochSecond(1677399813L) /* 2023-02-26 08:23:33 (UTC) */; - public static final Instant DATABASE_4_LAST_MODIFIED = Instant.ofEpochSecond(1677399813L) /* 2023-02-26 08:23:33 (UTC) */; - public static final UUID DATABASE_4_OWNER = USER_4_ID; - public static final UUID DATABASE_4_CREATOR = USER_4_ID; + public final static UUID DATABASE_4_ID = UUID.fromString("c503d7f3-5952-4d97-b26a-da86bea4c20d"); + public final static String DATABASE_4_NAME = "Weather AT"; + public final static String DATABASE_4_DESCRIPTION = "Weather data"; + public final static Boolean DATABASE_4_PUBLIC = true; + public final static Boolean DATABASE_4_SCHEMA_PUBLIC = true; + public final static Boolean DATABASE_4_DASHBOARD_ENABLED = true; + public final static String DATABASE_4_DASHBOARD_UID = "045e44890411ef"; + public final static String DATABASE_4_INTERNAL_NAME = "weather_at"; + public final static String DATABASE_4_EXCHANGE = "dbrepo"; + public final static Instant DATABASE_4_CREATED = Instant.ofEpochSecond(1677399813L) /* 2023-02-26 08:23:33 (UTC) */; + public final static Instant DATABASE_4_LAST_MODIFIED = Instant.ofEpochSecond(1677399813L) /* 2023-02-26 08:23:33 (UTC) */; - public static final DatabaseBriefDto DATABASE_4_BRIEF_DTO = DatabaseBriefDto.builder() + public final DatabaseBriefDto DATABASE_4_BRIEF_DTO = DatabaseBriefDto.builder() .id(DATABASE_4_ID) .isPublic(DATABASE_4_PUBLIC) .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) .name(DATABASE_4_NAME) .description(DATABASE_4_DESCRIPTION) - .internalName(DATABASE_4_INTERNALNAME) + .internalName(DATABASE_4_INTERNAL_NAME) .ownerId(USER_4_ID) .identifiers(new LinkedList<>()) .build(); - public static final DatabaseDto DATABASE_4_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_4_DTO = DatabaseDto.builder() .id(DATABASE_4_ID) .isPublic(DATABASE_4_PUBLIC) .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) .name(DATABASE_4_NAME) .container(CONTAINER_2_DTO) .description(DATABASE_4_DESCRIPTION) - .internalName(DATABASE_4_INTERNALNAME) + .internalName(DATABASE_4_INTERNAL_NAME) .exchangeName(DATABASE_4_EXCHANGE) .owner(USER_4_BRIEF_DTO) .tables(new LinkedList<>()) /* TABLE_9_DTO */ @@ -1319,14 +1336,14 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) /* IDENTIFIER_7_DTO */ .build(); - public static final DatabaseDto DATABASE_4_PRIVILEGED_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_4_PRIVILEGED_DTO = DatabaseDto.builder() .id(DATABASE_4_ID) .isPublic(DATABASE_4_PUBLIC) .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) .name(DATABASE_4_NAME) .container(CONTAINER_2_PRIVILEGED_DTO) .description(DATABASE_4_DESCRIPTION) - .internalName(DATABASE_4_INTERNALNAME) + .internalName(DATABASE_4_INTERNAL_NAME) .exchangeName(DATABASE_4_EXCHANGE) .owner(USER_4_BRIEF_DTO) .tables(new LinkedList<>()) /* TABLE_9_DTO */ @@ -1335,13 +1352,15 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); - public static final CreateTableDto TABLE_0_CREATE_DTO = CreateTableDto.builder() + public final CreateTableConstraintsDto TABLE_1_CREATE_CONSTRAINTS_DTO = CreateTableConstraintsDto.builder() + .uniques(new LinkedList<>()) + .foreignKeys(new LinkedList<>()) + .build(); + + public final CreateTableDto TABLE_0_CREATE_DTO = CreateTableDto.builder() .name("full") .description("full example") - .constraints(CreateTableConstraintsDto.builder() - .uniques(new LinkedList<>()) - .foreignKeys(new LinkedList<>()) - .build()) + .constraints(TABLE_1_CREATE_CONSTRAINTS_DTO) .columns(List.of(CreateTableColumnDto.builder() .name("col1a") .type(ColumnTypeDto.CHAR) @@ -1504,24 +1523,23 @@ public abstract class BaseTest { .build())) .build(); - public static final UUID TABLE_1_ID = UUID.fromString("666d0b6b-f017-4f7c-80d8-a47174d8b539"); - public static final String TABLE_1_NAME = "Weather AUS"; - public static final String TABLE_1_INTERNAL_NAME = "weather_aus"; - public static final Boolean TABLE_1_VERSIONED = true; - public static final Boolean TABLE_1_IS_PUBLIC = false; - public static final Boolean TABLE_1_SCHEMA_PUBLIC = false; - public static final Boolean TABLE_1_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_1_DESCRIPTION = "Weather in Australia"; - public static final String TABLE_1_QUEUE_NAME = TABLE_1_INTERNAL_NAME; - public static final String TABLE_1_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID; - public static final Long TABLE_1_AVG_ROW_LENGTH = 3L; - public static final Long TABLE_1_NUM_ROWS = 3L; - public static final Long TABLE_1_DATA_LENGTH = 2000L; - public static final Long TABLE_1_MAX_DATA_LENGTH = Long.MAX_VALUE; - 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 Table TABLE_1 = Table.builder() + public final static UUID TABLE_1_ID = UUID.fromString("666d0b6b-f017-4f7c-80d8-a47174d8b539"); + public final static String TABLE_1_NAME = "Weather AUS"; + public final static String TABLE_1_INTERNAL_NAME = "weather_aus"; + public final static Boolean TABLE_1_VERSIONED = true; + public final static Boolean TABLE_1_IS_PUBLIC = false; + public final static Boolean TABLE_1_SCHEMA_PUBLIC = false; + public final static String TABLE_1_DESCRIPTION = "Weather in Australia"; + public final static String TABLE_1_QUEUE_NAME = TABLE_1_INTERNAL_NAME; + public final static String TABLE_1_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID; + public final static Long TABLE_1_AVG_ROW_LENGTH = 3L; + public final static Long TABLE_1_NUM_ROWS = 3L; + public final static Long TABLE_1_DATA_LENGTH = 2000L; + public final static Long TABLE_1_MAX_DATA_LENGTH = Long.MAX_VALUE; + public final static Instant TABLE_1_CREATED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; + public final static Instant TABLE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; + + public final Table TABLE_1 = Table.builder() .id(TABLE_1_ID) .tdbid(DATABASE_1_ID) .database(null /* DATABASE_1 */) @@ -1534,7 +1552,7 @@ public abstract class BaseTest { .name(TABLE_1_NAME) .queueName(TABLE_1_QUEUE_NAME) .identifiers(new LinkedList<>()) - .columns(new LinkedList<>() /* TABLE_1_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_1_COLUMNS */ .constraints(null) /* TABLE_1_CONSTRAINTS */ .ownedBy(USER_1_ID) .owner(USER_1) @@ -1545,38 +1563,13 @@ public abstract class BaseTest { .maxDataLength(TABLE_1_MAX_DATA_LENGTH) .build(); - public static final TableDto TABLE_1_DTO = TableDto.builder() - .id(TABLE_1_ID) - .databaseId(DATABASE_1_ID) - .internalName(TABLE_1_INTERNAL_NAME) - .isVersioned(TABLE_1_VERSIONED) - .isPublic(TABLE_1_IS_PUBLIC) - .isSchemaPublic(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) - .avgRowLength(TABLE_1_AVG_ROW_LENGTH) - .numRows(TABLE_1_NUM_ROWS) - .dataLength(TABLE_1_DATA_LENGTH) - .maxDataLength(TABLE_1_MAX_DATA_LENGTH) - .build(); - - public static final UUID COLUMN_1_1_ID = UUID.fromString("377c0a6e-938e-458c-ad2b-bbbd75d46412"); - - public static final UUID COLUMN_1_2_ID = UUID.fromString("dbca4821-3023-479b-a25a-c08eb0ec02ce"); - - public static final UUID COLUMN_1_3_ID = UUID.fromString("8ff0351e-4882-4948-94af-598e4b264b25"); + public final static UUID COLUMN_1_1_ID = UUID.fromString("377c0a6e-938e-458c-ad2b-bbbd75d46412"); + public final static UUID COLUMN_1_2_ID = UUID.fromString("dbca4821-3023-479b-a25a-c08eb0ec02ce"); + public final static UUID COLUMN_1_3_ID = UUID.fromString("8ff0351e-4882-4948-94af-598e4b264b25"); + public final static UUID COLUMN_1_4_ID = UUID.fromString("9ab256eb-3324-4e76-af3b-e3e2a58ce161"); + public final static UUID COLUMN_1_5_ID = UUID.fromString("619e9355-51aa-438f-8579-80cec30f35cb"); - public static final UUID COLUMN_1_4_ID = UUID.fromString("9ab256eb-3324-4e76-af3b-e3e2a58ce161"); - - public static final UUID COLUMN_1_5_ID = UUID.fromString("619e9355-51aa-438f-8579-80cec30f35cb"); - - public static final List<ColumnDto> TABLE_1_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_1_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_1_1_ID) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) @@ -1644,7 +1637,36 @@ public abstract class BaseTest { .sets(null) .build()); - public static final TableBriefDto TABLE_1_BRIEF_DTO = TableBriefDto.builder() + public final CreateTableConstraintsDto TABLE_1_CREATE_TABLE_CONSTRAINTS_DTO = + CreateTableConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .primaryKey(new LinkedHashSet<>(List.of("id"))) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>(List.of(List.of("date")))) + .build(); + + public final TableDto TABLE_1_DTO = TableDto.builder() + .id(TABLE_1_ID) + .databaseId(DATABASE_1_ID) + .internalName(TABLE_1_INTERNAL_NAME) + .isVersioned(TABLE_1_VERSIONED) + .isPublic(TABLE_1_IS_PUBLIC) + .isSchemaPublic(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<>()) + .constraints(null) + .owner(USER_1_BRIEF_DTO) + .avgRowLength(TABLE_1_AVG_ROW_LENGTH) + .numRows(TABLE_1_NUM_ROWS) + .dataLength(TABLE_1_DATA_LENGTH) + .maxDataLength(TABLE_1_MAX_DATA_LENGTH) + .build(); + + public final TableBriefDto TABLE_1_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_1_ID) .databaseId(DATABASE_1_ID) .internalName(TABLE_1_INTERNAL_NAME) @@ -1656,9 +1678,10 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final Long TABLE_1_DATA_COUNT = 3L; + public final static Long TABLE_1_DATA_COUNT = 3L; + @SuppressWarnings("java:S3599") - public static final List<Map<String, Object>> TABLE_1_DATA_DTO = new LinkedList<>(List.of( + public final List<Map<String, Object>> TABLE_1_DATA_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put("id", BigInteger.valueOf(1L)); put("date", LocalDate.of(2008, 12, 1).atStartOfDay().toInstant(ZoneOffset.UTC)); @@ -1682,29 +1705,28 @@ public abstract class BaseTest { }} )); - public static final UUID TABLE_2_ID = UUID.fromString("0cc067b6-4e81-4871-b47e-17a38228a574"); - public static final String TABLE_2_NAME = "Weather Location"; - public static final String TABLE_2_INTERNALNAME = "weather_location"; - public static final Boolean TABLE_2_VERSIONED = true; - public static final Boolean TABLE_2_IS_PUBLIC = false; - public static final Boolean TABLE_2_SCHEMA_PUBLIC = true; - public static final Boolean TABLE_2_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_2_DESCRIPTION = "Weather location"; - public static final String TABLE_2_QUEUE_NAME = TABLE_2_INTERNALNAME; - public static final String TABLE_2_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_2_ID; - public static final Instant TABLE_2_CREATED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; - public static final Instant TABLE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; - public static final Long TABLE_2_AVG_ROW_LENGTH = 3L; - public static final Long TABLE_2_NUM_ROWS = 3L; - public static final Long TABLE_2_DATA_LENGTH = 2000L; - public static final Long TABLE_2_MAX_DATA_LENGTH = Long.MAX_VALUE; - - public static final Table TABLE_2 = Table.builder() + public final static UUID TABLE_2_ID = UUID.fromString("0cc067b6-4e81-4871-b47e-17a38228a574"); + public final static String TABLE_2_NAME = "Weather Location"; + public final static String TABLE_2_INTERNAL_NAME = "weather_location"; + public final static Boolean TABLE_2_VERSIONED = true; + public final static Boolean TABLE_2_IS_PUBLIC = false; + public final static Boolean TABLE_2_SCHEMA_PUBLIC = true; + public final static String TABLE_2_DESCRIPTION = "Weather location"; + public final static String TABLE_2_QUEUE_NAME = TABLE_2_INTERNAL_NAME; + public final static String TABLE_2_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_2_ID; + public final static Instant TABLE_2_CREATED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; + public final static Instant TABLE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; + public final static Long TABLE_2_AVG_ROW_LENGTH = 3L; + public final static Long TABLE_2_NUM_ROWS = 3L; + public final static Long TABLE_2_DATA_LENGTH = 2000L; + public final static Long TABLE_2_MAX_DATA_LENGTH = Long.MAX_VALUE; + + public final Table TABLE_2 = Table.builder() .id(TABLE_2_ID) .tdbid(DATABASE_1_ID) .database(null /* DATABASE_1 */) .created(TABLE_2_CREATED) - .internalName(TABLE_2_INTERNALNAME) + .internalName(TABLE_2_INTERNAL_NAME) .isVersioned(TABLE_2_VERSIONED) .isPublic(TABLE_2_IS_PUBLIC) .isSchemaPublic(TABLE_2_SCHEMA_PUBLIC) @@ -1712,7 +1734,7 @@ public abstract class BaseTest { .name(TABLE_2_NAME) .lastModified(TABLE_2_LAST_MODIFIED) .queueName(TABLE_2_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_2_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_2_COLUMNS */ .constraints(null) /* TABLE_2_CONSTRAINTS */ .owner(USER_2) .ownedBy(USER_2_ID) @@ -1722,61 +1744,177 @@ public abstract class BaseTest { .maxDataLength(TABLE_2_MAX_DATA_LENGTH) .build(); - public static final TableDto TABLE_2_DTO = TableDto.builder() + public final TableBriefDto TABLE_2_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_2_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_2_INTERNALNAME) + .internalName(TABLE_2_INTERNAL_NAME) .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) - .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) + .ownedBy(USER_2_ID) + .build(); + + public final static UUID COLUMN_2_1_ID = UUID.fromString("795faa78-7ebb-4dd5-9eb1-e54a9192d0b5"); + public final static UUID COLUMN_2_2_ID = UUID.fromString("f316ced5-7774-4656-aa7f-a874622d99b3"); + public final static UUID COLUMN_2_3_ID = UUID.fromString("11cb1aa2-8582-45ef-a3bb-7056aa94cdf1"); + + public final ColumnBriefDto TABLE_1_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + .id(COLUMN_1_1_ID) + .name("id") + .internalName("id") + .columnType(ColumnTypeDto.BIGINT) + .build(); + + public final List<ColumnDto> TABLE_2_COLUMNS_DTO = List.of(ColumnDto.builder() + .id(COLUMN_2_1_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .ordinalPosition(0) + .name("location") + .internalName("location") + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(false) + .enums(null) + .sets(null) + .build(), + ColumnDto.builder() + .id(COLUMN_2_2_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .ordinalPosition(1) + .name("lat") + .internalName("lat") + .columnType(ColumnTypeDto.DOUBLE) + .size(22L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build(), + ColumnDto.builder() + .id(COLUMN_2_3_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .ordinalPosition(2) + .name("lng") + .internalName("lng") + .columnType(ColumnTypeDto.DOUBLE) + .size(22L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build()); + + public final ColumnBriefDto TABLE_2_COLUMNS_BRIEF_2_DTO = ColumnBriefDto.builder() + .id(COLUMN_2_3_ID) + .name("lng") + .internalName("lng") + .columnType(ColumnTypeDto.DECIMAL) + .build(); + + public final List<ColumnBriefDto> TABLE_2_COLUMNS_BRIEF_DTO = List.of(ColumnBriefDto.builder() + .id(COLUMN_2_1_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .name("location") + .internalName("location") + .columnType(ColumnTypeDto.VARCHAR) + .build(), + ColumnBriefDto.builder() + .id(COLUMN_2_2_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .name("lat") + .internalName("lat") + .columnType(ColumnTypeDto.DOUBLE) + .build(), + ColumnBriefDto.builder() + .id(COLUMN_2_3_ID) + .tableId(TABLE_2_ID) + .databaseId(DATABASE_1_ID) + .name("lng") + .internalName("lng") + .columnType(ColumnTypeDto.DOUBLE) + .build()); + + public final ColumnBriefDto TABLE_2_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + .id(COLUMN_2_1_ID) + .name("location") + .internalName("location") + .columnType(ColumnTypeDto.VARCHAR) .build(); - public static final TableBriefDto TABLE_2_BRIEF_DTO = TableBriefDto.builder() + public final TableDto TABLE_2_DTO = TableDto.builder() .id(TABLE_2_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_2_INTERNALNAME) + .internalName(TABLE_2_INTERNAL_NAME) .isVersioned(TABLE_2_VERSIONED) .isPublic(TABLE_2_IS_PUBLIC) .isSchemaPublic(TABLE_2_SCHEMA_PUBLIC) .description(TABLE_2_DESCRIPTION) .name(TABLE_2_NAME) - .ownedBy(USER_2_ID) + .queueName(TABLE_2_QUEUE_NAME) + .routingKey(TABLE_2_ROUTING_KEY) + .columns(new LinkedList<>()) + .constraints(ConstraintsDto.builder() + .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) + .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() + .id(UUID.fromString("ca833111-1e9a-48a3-bb16-ad6f90196f96")) + .name("fk_location") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(UUID.fromString("8552f282-0403-424d-b2ba-4ed0f760197c")) + .column(TABLE_2_COLUMNS_BRIEF_2_DTO) + .referencedColumn(TABLE_1_COLUMNS_BRIEF_0_DTO) + .foreignKey(null) + .build()))) + .table(TABLE_1_BRIEF_DTO) + .referencedTable(TABLE_2_BRIEF_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build()))) + .uniques(new LinkedList<>(List.of(UniqueDto.builder() + .id(UUID.fromString("b9aba807-dd9c-43a3-9614-2493cb4b26bd")) + .table(TABLE_2_BRIEF_DTO) + .name("uk_1") + .columns(new LinkedList<>(List.of(TABLE_2_COLUMNS_BRIEF_DTO.get(1)))) + .build()))) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_2_BRIEF_DTO) + .column(TABLE_2_COLUMNS_BRIEF_0_DTO) + .id(COLUMN_2_1_ID) + .build()))) + .build()) + .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) .build(); - public static final UUID TABLE_3_ID = UUID.fromString("a94ee518-c235-496b-8613-b0c643bc1b11"); - public static final String TABLE_3_NAME = "Sensor"; - public static final String TABLE_3_INTERNALNAME = "sensor"; - public static final Boolean TABLE_3_VERSIONED = true; - public static final Boolean TABLE_3_IS_PUBLIC = false; - public static final Boolean TABLE_3_SCHEMA_PUBLIC = false; - public static final Boolean TABLE_3_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_3_DESCRIPTION = "Some sensor data"; - public static final String TABLE_3_QUEUE_NAME = TABLE_3_INTERNALNAME; - public static final String TABLE_3_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_3_ID; - public static final Instant TABLE_3_CREATED = Instant.ofEpochSecond(1677400031L) /* 2023-02-26 08:27:11 (UTC) */; - public static final Instant TABLE_3_LAST_MODIFIED = Instant.ofEpochSecond(1677400031L) /* 2023-02-26 08:27:11 (UTC) */; - public static final Long TABLE_3_AVG_ROW_LENGTH = 6L; - public static final Long TABLE_3_NUM_ROWS = 6L; - public static final Long TABLE_3_DATA_LENGTH = 1800L; - public static final Long TABLE_3_MAX_DATA_LENGTH = Long.MAX_VALUE; - - public static final Table TABLE_3 = Table.builder() + public final static UUID TABLE_3_ID = UUID.fromString("a94ee518-c235-496b-8613-b0c643bc1b11"); + public final static String TABLE_3_NAME = "Sensor"; + public final static String TABLE_3_INTERNAL_NAME = "sensor"; + public final static Boolean TABLE_3_VERSIONED = true; + public final static Boolean TABLE_3_IS_PUBLIC = false; + public final static Boolean TABLE_3_SCHEMA_PUBLIC = false; + public final static String TABLE_3_DESCRIPTION = "Some sensor data"; + public final static String TABLE_3_QUEUE_NAME = TABLE_3_INTERNAL_NAME; + public final static String TABLE_3_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_3_ID; + public final static Instant TABLE_3_CREATED = Instant.ofEpochSecond(1677400031L) /* 2023-02-26 08:27:11 (UTC) */; + public final static Instant TABLE_3_LAST_MODIFIED = Instant.ofEpochSecond(1677400031L) /* 2023-02-26 08:27:11 (UTC) */; + public final static Long TABLE_3_AVG_ROW_LENGTH = 6L; + public final static Long TABLE_3_NUM_ROWS = 6L; + public final static Long TABLE_3_DATA_LENGTH = 1800L; + public final static Long TABLE_3_MAX_DATA_LENGTH = Long.MAX_VALUE; + + public final Table TABLE_3 = Table.builder() .id(TABLE_3_ID) .tdbid(DATABASE_1_ID) - .database(null /* DATABASE_1 */) + .database(null) /* DATABASE_1 */ .created(TABLE_3_CREATED) - .internalName(TABLE_3_INTERNALNAME) + .internalName(TABLE_3_INTERNAL_NAME) .isVersioned(TABLE_3_VERSIONED) .isPublic(TABLE_3_IS_PUBLIC) .isSchemaPublic(TABLE_3_SCHEMA_PUBLIC) @@ -1784,7 +1922,7 @@ public abstract class BaseTest { .name(TABLE_3_NAME) .lastModified(TABLE_3_LAST_MODIFIED) .queueName(TABLE_3_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_3_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_3_COLUMNS */ .constraints(null) /* TABLE_3_CONSTRAINTS */ .owner(USER_3) .ownedBy(USER_3_ID) @@ -1794,10 +1932,10 @@ public abstract class BaseTest { .maxDataLength(TABLE_3_MAX_DATA_LENGTH) .build(); - public static final TableDto TABLE_3_DTO = TableDto.builder() + public final TableDto TABLE_3_DTO = TableDto.builder() .id(TABLE_3_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_3_INTERNALNAME) + .internalName(TABLE_3_INTERNAL_NAME) .isVersioned(TABLE_3_VERSIONED) .isPublic(TABLE_3_IS_PUBLIC) .isSchemaPublic(TABLE_3_SCHEMA_PUBLIC) @@ -1814,10 +1952,10 @@ public abstract class BaseTest { .maxDataLength(TABLE_3_MAX_DATA_LENGTH) .build(); - public static final TableBriefDto TABLE_3_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_3_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_3_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_3_INTERNALNAME) + .internalName(TABLE_3_INTERNAL_NAME) .isVersioned(TABLE_3_VERSIONED) .isPublic(TABLE_3_IS_PUBLIC) .isSchemaPublic(TABLE_3_SCHEMA_PUBLIC) @@ -1826,14 +1964,14 @@ public abstract class BaseTest { .ownedBy(USER_3_ID) .build(); - public static final CreateTableConstraintsDto TABLE_3_CONSTRAINTS_CREATE_DTO = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_3_CONSTRAINTS_CREATE_DTO = CreateTableConstraintsDto.builder() .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) .build(); - public static final CreateTableConstraintsDto TABLE_3_CONSTRAINTS_INVALID_CREATE_DTO = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_3_CONSTRAINTS_INVALID_CREATE_DTO = CreateTableConstraintsDto.builder() .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>()) // <<<< .uniques(new LinkedList<>()) @@ -1844,42 +1982,41 @@ public abstract class BaseTest { .build())) .build(); - public static final CreateTableDto TABLE_3_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_3_CREATE_DTO = CreateTableDto.builder() .name(TABLE_3_NAME) .description(TABLE_3_DESCRIPTION) .columns(new LinkedList<>()) .constraints(TABLE_3_CONSTRAINTS_CREATE_DTO) .build(); - public static final CreateTableDto TABLE_3_INVALID_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_3_INVALID_CREATE_DTO = CreateTableDto.builder() .name(TABLE_3_NAME) .description(TABLE_3_DESCRIPTION) .columns(new LinkedList<>()) .constraints(TABLE_3_CONSTRAINTS_INVALID_CREATE_DTO) .build(); - public static final UUID TABLE_5_ID = UUID.fromString("91306cbd-c51f-47d3-8722-debfdbd8a77e"); - public static final String TABLE_5_NAME = "zoo"; - public static final String TABLE_5_INTERNALNAME = "zoo"; - public static final Boolean TABLE_5_VERSIONED = true; - public static final Boolean TABLE_5_IS_PUBLIC = true; - public static final Boolean TABLE_5_SCHEMA_PUBLIC = true; - public static final Boolean TABLE_5_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_5_DESCRIPTION = "Some Kaggle dataset"; - public static final String TABLE_5_QUEUE_NAME = TABLE_5_INTERNALNAME; - public static final String TABLE_5_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_5_ID; - public static final Instant TABLE_5_CREATED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; - public static final Instant TABLE_5_LAST_MODIFIED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; - public static final Long TABLE_5_AVG_ROW_LENGTH = 1080L; - public static final Long TABLE_5_NUM_ROWS = 101L; - public static final Long TABLE_5_DATA_LENGTH = 15200L; - public static final Long TABLE_5_MAX_DATA_LENGTH = Long.MAX_VALUE; - - public static final Table TABLE_5 = Table.builder() + public final static UUID TABLE_5_ID = UUID.fromString("91306cbd-c51f-47d3-8722-debfdbd8a77e"); + public final static String TABLE_5_NAME = "zoo"; + public final static String TABLE_5_INTERNAL_NAME = "zoo"; + public final static Boolean TABLE_5_VERSIONED = true; + public final static Boolean TABLE_5_IS_PUBLIC = true; + public final static Boolean TABLE_5_SCHEMA_PUBLIC = true; + public final static String TABLE_5_DESCRIPTION = "Some Kaggle dataset"; + public final static String TABLE_5_QUEUE_NAME = TABLE_5_INTERNAL_NAME; + public final static String TABLE_5_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_5_ID; + public final static Instant TABLE_5_CREATED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; + public final static Instant TABLE_5_LAST_MODIFIED = Instant.ofEpochSecond(1677400067L) /* 2023-02-26 08:27:47 (UTC) */; + public final static Long TABLE_5_AVG_ROW_LENGTH = 1080L; + public final static Long TABLE_5_NUM_ROWS = 101L; + public final static Long TABLE_5_DATA_LENGTH = 15200L; + public final static Long TABLE_5_MAX_DATA_LENGTH = Long.MAX_VALUE; + + public final Table TABLE_5 = Table.builder() .id(TABLE_5_ID) .tdbid(DATABASE_2_ID) .created(Instant.now()) - .internalName(TABLE_5_INTERNALNAME) + .internalName(TABLE_5_INTERNAL_NAME) .isVersioned(TABLE_5_VERSIONED) .isPublic(TABLE_5_IS_PUBLIC) .isSchemaPublic(TABLE_5_SCHEMA_PUBLIC) @@ -1893,10 +2030,10 @@ public abstract class BaseTest { .owner(USER_1) .build(); - public static final TableDto TABLE_5_DTO = TableDto.builder() + public final TableDto TABLE_5_DTO = TableDto.builder() .id(TABLE_5_ID) .databaseId(DATABASE_2_ID) - .internalName(TABLE_5_INTERNALNAME) + .internalName(TABLE_5_INTERNAL_NAME) .isVersioned(TABLE_5_VERSIONED) .isPublic(TABLE_5_IS_PUBLIC) .isSchemaPublic(TABLE_5_SCHEMA_PUBLIC) @@ -1909,10 +2046,10 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_5_ID) .databaseId(DATABASE_2_ID) - .internalName(TABLE_5_INTERNALNAME) + .internalName(TABLE_5_INTERNAL_NAME) .isVersioned(TABLE_5_VERSIONED) .isPublic(TABLE_5_IS_PUBLIC) .isSchemaPublic(TABLE_5_SCHEMA_PUBLIC) @@ -1921,24 +2058,23 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final UUID TABLE_6_ID = UUID.fromString("ae84d169-d36c-4f5a-a390-153d090f9574"); - public static final String TABLE_6_NAME = "names"; - public static final String TABLE_6_INTERNALNAME = "names"; - public static final Boolean TABLE_6_VERSIONED = true; - public static final Boolean TABLE_6_IS_PUBLIC = true; - public static final Boolean TABLE_6_SCHEMA_PUBLIC = false; - public static final Boolean TABLE_6_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_6_DESCRIPTION = "Some names dataset"; - public static final String TABLE_6_QUEUE_NAME = TABLE_6_INTERNALNAME; - public static final String TABLE_6_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_6_ID; - public static final Instant TABLE_6_CREATED = Instant.ofEpochSecond(1677400117L) /* 2023-02-26 08:28:37 (UTC) */; - public static final Instant TABLE_6_LAST_MODIFIED = Instant.ofEpochSecond(1677400117L) /* 2023-02-26 08:28:37 (UTC) */; - - public static final Table TABLE_6 = Table.builder() + public final static UUID TABLE_6_ID = UUID.fromString("ae84d169-d36c-4f5a-a390-153d090f9574"); + public final static String TABLE_6_NAME = "names"; + public final static String TABLE_6_INTERNAL_NAME = "names"; + public final static Boolean TABLE_6_VERSIONED = true; + public final static Boolean TABLE_6_IS_PUBLIC = true; + public final static Boolean TABLE_6_SCHEMA_PUBLIC = false; + public final static String TABLE_6_DESCRIPTION = "Some names dataset"; + public final static String TABLE_6_QUEUE_NAME = TABLE_6_INTERNAL_NAME; + public final static String TABLE_6_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_6_ID; + public final static Instant TABLE_6_CREATED = Instant.ofEpochSecond(1677400117L) /* 2023-02-26 08:28:37 (UTC) */; + public final static Instant TABLE_6_LAST_MODIFIED = Instant.ofEpochSecond(1677400117L) /* 2023-02-26 08:28:37 (UTC) */; + + public final Table TABLE_6 = Table.builder() .id(TABLE_6_ID) .tdbid(DATABASE_2_ID) .created(TABLE_6_CREATED) - .internalName(TABLE_6_INTERNALNAME) + .internalName(TABLE_6_INTERNAL_NAME) .isVersioned(TABLE_6_VERSIONED) .isPublic(TABLE_6_IS_PUBLIC) .isSchemaPublic(TABLE_6_SCHEMA_PUBLIC) @@ -1953,10 +2089,10 @@ public abstract class BaseTest { .created(TABLE_6_CREATED) .build(); - public static final TableDto TABLE_6_DTO = TableDto.builder() + public final TableDto TABLE_6_DTO = TableDto.builder() .id(TABLE_6_ID) .databaseId(DATABASE_2_ID) - .internalName(TABLE_6_INTERNALNAME) + .internalName(TABLE_6_INTERNAL_NAME) .isVersioned(TABLE_6_VERSIONED) .isPublic(TABLE_6_IS_PUBLIC) .isSchemaPublic(TABLE_6_SCHEMA_PUBLIC) @@ -1969,10 +2105,10 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableBriefDto TABLE_6_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_6_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_6_ID) .databaseId(DATABASE_2_ID) - .internalName(TABLE_6_INTERNALNAME) + .internalName(TABLE_6_INTERNAL_NAME) .isVersioned(TABLE_6_VERSIONED) .isPublic(TABLE_6_IS_PUBLIC) .isSchemaPublic(TABLE_6_SCHEMA_PUBLIC) @@ -1981,20 +2117,19 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final UUID TABLE_7_ID = UUID.fromString("e5d10200-3e4f-45f4-9f36-ff3ca39c6c29"); - public static final String TABLE_7_NAME = "likes"; - public static final String TABLE_7_INTERNAL_NAME = "likes"; - public static final Boolean TABLE_7_VERSIONED = true; - public static final Boolean TABLE_7_IS_PUBLIC = true; - public static final Boolean TABLE_7_SCHEMA_PUBLIC = true; - public static final Boolean TABLE_7_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_7_DESCRIPTION = "Some likes dataset"; - public static final String TABLE_7_QUEUE_NAME = TABLE_7_INTERNAL_NAME; - public static final String TABLE_7_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_7_ID; - public static final Instant TABLE_7_CREATED = Instant.ofEpochSecond(1677400147L) /* 2023-02-26 08:29:07 (UTC) */; - public static final Instant TABLE_7_LAST_MODIFIED = Instant.ofEpochSecond(1677400147L) /* 2023-02-26 08:29:07 (UTC) */; - - public static final Table TABLE_7 = Table.builder() + public final static UUID TABLE_7_ID = UUID.fromString("e5d10200-3e4f-45f4-9f36-ff3ca39c6c29"); + public final static String TABLE_7_NAME = "likes"; + public final static String TABLE_7_INTERNAL_NAME = "likes"; + public final static Boolean TABLE_7_VERSIONED = true; + public final static Boolean TABLE_7_IS_PUBLIC = true; + public final static Boolean TABLE_7_SCHEMA_PUBLIC = true; + public final static String TABLE_7_DESCRIPTION = "Some likes dataset"; + public final static String TABLE_7_QUEUE_NAME = TABLE_7_INTERNAL_NAME; + public final static String TABLE_7_ROUTING_KEY = "dbrepo." + DATABASE_2_ID + "." + TABLE_7_ID; + public final static Instant TABLE_7_CREATED = Instant.ofEpochSecond(1677400147L) /* 2023-02-26 08:29:07 (UTC) */; + public final static Instant TABLE_7_LAST_MODIFIED = Instant.ofEpochSecond(1677400147L) /* 2023-02-26 08:29:07 (UTC) */; + + public final Table TABLE_7 = Table.builder() .id(TABLE_7_ID) .tdbid(DATABASE_2_ID) .created(TABLE_7_CREATED) @@ -2013,7 +2148,7 @@ public abstract class BaseTest { .created(TABLE_7_CREATED) .build(); - public static final TableDto TABLE_7_DTO = TableDto.builder() + public final TableDto TABLE_7_DTO = TableDto.builder() .id(TABLE_7_ID) .databaseId(DATABASE_2_ID) .internalName(TABLE_7_INTERNAL_NAME) @@ -2029,7 +2164,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableBriefDto TABLE_7_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_7_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_7_ID) .databaseId(DATABASE_2_ID) .internalName(TABLE_7_INTERNAL_NAME) @@ -2041,26 +2176,26 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final UUID TABLE_4_ID = UUID.fromString("6c87cbcf-5043-404f-9bf1-b09ddbac25a2"); - public static final String TABLE_4_NAME = "Sensor 2"; - public static final String TABLE_4_INTERNALNAME = "sensor_2"; - public static final Boolean TABLE_4_VERSIONED = true; - public static final Boolean TABLE_4_IS_PUBLIC = true; - public static final Boolean TABLE_4_SCHEMA_PUBLIC = false; - public static final String TABLE_4_DESCRIPTION = "Hello sensor"; - public static final String TABLE_4_QUEUE_NAME = TABLE_4_INTERNALNAME; - public static final String TABLE_4_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_4_ID; - public static final Instant TABLE_4_CREATED = Instant.ofEpochSecond(1677400175L) /* 2023-02-26 08:29:35 (UTC) */; - public static final Instant TABLE_4_LAST_MODIFIED = Instant.ofEpochSecond(1677400175L) /* 2023-02-26 08:29:35 (UTC) */; - public static final Long TABLE_4_AVG_ROW_LENGTH = 0L; - public static final Long TABLE_4_NUM_ROWS = 0L; - public static final Long TABLE_4_DATA_LENGTH = 1000L; - public static final Long TABLE_4_MAX_DATA_LENGTH = Long.MAX_VALUE; - - public static final Table TABLE_4 = Table.builder() + public final static UUID TABLE_4_ID = UUID.fromString("6c87cbcf-5043-404f-9bf1-b09ddbac25a2"); + public final static String TABLE_4_NAME = "Sensor 2"; + public final static String TABLE_4_INTERNAL_NAME = "sensor_2"; + public final static Boolean TABLE_4_VERSIONED = true; + public final static Boolean TABLE_4_IS_PUBLIC = true; + public final static Boolean TABLE_4_SCHEMA_PUBLIC = false; + public final static String TABLE_4_DESCRIPTION = "Hello sensor"; + public final static String TABLE_4_QUEUE_NAME = TABLE_4_INTERNAL_NAME; + public final static String TABLE_4_ROUTING_KEY = "dbrepo." + DATABASE_1_ID + "." + TABLE_4_ID; + public final static Instant TABLE_4_CREATED = Instant.ofEpochSecond(1677400175L) /* 2023-02-26 08:29:35 (UTC) */; + public final static Instant TABLE_4_LAST_MODIFIED = Instant.ofEpochSecond(1677400175L) /* 2023-02-26 08:29:35 (UTC) */; + public final static Long TABLE_4_AVG_ROW_LENGTH = 0L; + public final static Long TABLE_4_NUM_ROWS = 0L; + public final static Long TABLE_4_DATA_LENGTH = 1000L; + public final static Long TABLE_4_MAX_DATA_LENGTH = Long.MAX_VALUE; + + public final Table TABLE_4 = Table.builder() .id(TABLE_4_ID) .tdbid(DATABASE_1_ID) - .internalName(TABLE_4_INTERNALNAME) + .internalName(TABLE_4_INTERNAL_NAME) .description(TABLE_4_DESCRIPTION) .database(null /* DATABASE_1 */) .name(TABLE_4_NAME) @@ -2080,10 +2215,10 @@ public abstract class BaseTest { .maxDataLength(TABLE_4_MAX_DATA_LENGTH) .build(); - public static final TableDto TABLE_4_DTO = TableDto.builder() + public final TableDto TABLE_4_DTO = TableDto.builder() .id(TABLE_4_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_4_INTERNALNAME) + .internalName(TABLE_4_INTERNAL_NAME) .description(TABLE_4_DESCRIPTION) .name(TABLE_4_NAME) .queueName(TABLE_4_QUEUE_NAME) @@ -2100,10 +2235,10 @@ public abstract class BaseTest { .maxDataLength(TABLE_4_MAX_DATA_LENGTH) .build(); - public static final TableBriefDto TABLE_4_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_4_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_4_ID) .databaseId(DATABASE_1_ID) - .internalName(TABLE_4_INTERNALNAME) + .internalName(TABLE_4_INTERNAL_NAME) .description(TABLE_4_DESCRIPTION) .name(TABLE_4_NAME) .isVersioned(TABLE_4_VERSIONED) @@ -2112,18 +2247,17 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final ColumnBriefDto TABLE_4_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final ColumnBriefDto TABLE_4_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(UUID.fromString("360f02be-6dfb-48ea-9d1e-1da488b0e324")) .name("Timestamp") .internalName("timestamp") .columnType(ColumnTypeDto.TIMESTAMP) .build(); - public static final UUID COLUMN_4_1_ID = UUID.fromString("c8ec8a56-dea1-4316-895f-56e6d289cbf7"); - - public static final UUID COLUMN_4_2_ID = UUID.fromString("d06956ae-aabd-474f-a47d-47af1ba043d1"); + public final static UUID COLUMN_4_1_ID = UUID.fromString("c8ec8a56-dea1-4316-895f-56e6d289cbf7"); + public final static UUID COLUMN_4_2_ID = UUID.fromString("d06956ae-aabd-474f-a47d-47af1ba043d1"); - public static final List<TableColumn> TABLE_4_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_4_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_4_1_ID) .ordinalPosition(0) .table(TABLE_4) @@ -2142,7 +2276,7 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final List<CreateTableColumnDto> TABLE_4_COLUMNS_CREATE_DTO = List.of(CreateTableColumnDto.builder() + public final List<CreateTableColumnDto> TABLE_4_COLUMNS_CREATE_DTO = List.of(CreateTableColumnDto.builder() .name("Timestamp") .type(ColumnTypeDto.TIMESTAMP) .nullAllowed(false) @@ -2155,28 +2289,29 @@ public abstract class BaseTest { .d(10L) .build()); - public static final CreateTableConstraintsDto TABLE_4_CONSTRAINTS_CREATE_DTO = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_4_CONSTRAINTS_CREATE_DTO = CreateTableConstraintsDto.builder() .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>(Set.of("Timestamp"))) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>(List.of(List.of("Timestamp")))) .build(); - public static final CreateTableDto TABLE_4_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_4_CREATE_DTO = CreateTableDto.builder() .name(TABLE_4_NAME) .description(TABLE_4_DESCRIPTION) .columns(TABLE_4_COLUMNS_CREATE_DTO) .constraints(TABLE_4_CONSTRAINTS_CREATE_DTO) .build(); - public static final at.tuwien.api.database.table.internal.TableCreateDto TABLE_4_CREATE_INTERNAL_DTO = at.tuwien.api.database.table.internal.TableCreateDto.builder() - .name(TABLE_4_NAME) - .description(TABLE_4_DESCRIPTION) - .columns(TABLE_4_COLUMNS_CREATE_DTO) - .constraints(TABLE_4_CONSTRAINTS_CREATE_DTO) - .build(); + public final at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto TABLE_4_CREATE_INTERNAL_DTO = + at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto.builder() + .name(TABLE_4_NAME) + .description(TABLE_4_DESCRIPTION) + .columns(TABLE_4_COLUMNS_CREATE_DTO) + .constraints(TABLE_4_CONSTRAINTS_CREATE_DTO) + .build(); - public static final List<ColumnDto> TABLE_4_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_4_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_4_1_ID) .databaseId(DATABASE_1_ID) .tableId(TABLE_4_ID) @@ -2195,19 +2330,19 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final UUID TABLE_8_ID = UUID.fromString("2e039d0d-3257-4083-8b32-76d7cfa1f7fd"); - public static final String TABLE_8_NAME = "location"; - public static final String TABLE_8_INTERNAL_NAME = "mfcc"; - public static final Boolean TABLE_8_VERSIONED = true; - public static final Boolean TABLE_8_IS_PUBLIC = false; - public static final Boolean TABLE_8_SCHEMA_PUBLIC = false; - public static final String TABLE_8_DESCRIPTION = "Hello mfcc"; - public static final String TABLE_8_QUEUE_NAME = TABLE_8_INTERNAL_NAME; - public static final String TABLE_8_ROUTING_KEY = "dbrepo." + DATABASE_3_ID + "." + TABLE_8_ID; - public static final Instant TABLE_8_CREATED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; - public static final Instant TABLE_8_LAST_MODIFIED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; - - public static final Table TABLE_8 = Table.builder() + public final static UUID TABLE_8_ID = UUID.fromString("2e039d0d-3257-4083-8b32-76d7cfa1f7fd"); + public final static String TABLE_8_NAME = "location"; + public final static String TABLE_8_INTERNAL_NAME = "mfcc"; + public final static Boolean TABLE_8_VERSIONED = true; + public final static Boolean TABLE_8_IS_PUBLIC = false; + public final static Boolean TABLE_8_SCHEMA_PUBLIC = false; + public final static String TABLE_8_DESCRIPTION = "Hello mfcc"; + public final static String TABLE_8_QUEUE_NAME = TABLE_8_INTERNAL_NAME; + public final static String TABLE_8_ROUTING_KEY = "dbrepo." + DATABASE_3_ID + "." + TABLE_8_ID; + public final static Instant TABLE_8_CREATED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; + public final static Instant TABLE_8_LAST_MODIFIED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; + + public final Table TABLE_8 = Table.builder() .id(TABLE_8_ID) .tdbid(DATABASE_3_ID) .internalName(TABLE_8_INTERNAL_NAME) @@ -2226,7 +2361,7 @@ public abstract class BaseTest { .lastModified(TABLE_8_LAST_MODIFIED) .build(); - public static final TableDto TABLE_8_DTO = TableDto.builder() + public final TableDto TABLE_8_DTO = TableDto.builder() .id(TABLE_8_ID) .databaseId(DATABASE_3_ID) .internalName(TABLE_8_INTERNAL_NAME) @@ -2241,13 +2376,13 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableUpdateDto TABLE_8_UPDATE_DTO = TableUpdateDto.builder() + public final TableUpdateDto TABLE_8_UPDATE_DTO = TableUpdateDto.builder() .description(null) .isPublic(true) .isSchemaPublic(true) .build(); - public static final TableBriefDto TABLE_8_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_8_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_8_ID) .databaseId(DATABASE_3_ID) .internalName(TABLE_8_INTERNAL_NAME) @@ -2259,20 +2394,19 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .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"; - 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 = "Location"; - public static final String TABLE_9_QUEUE_NAME = TABLE_9_INTERNAL_NAME; - 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) */; - - public static final Table TABLE_9 = Table.builder() + public final static UUID TABLE_9_ID = UUID.fromString("9314294f-04fc-4354-8b1f-2a8aeb566453"); + public final static String TABLE_9_NAME = "Weather Location"; + public final static String TABLE_9_INTERNAL_NAME = "weather_location"; + public final static Boolean TABLE_9_VERSIONED = true; + public final static Boolean TABLE_9_IS_PUBLIC = false; + public final static Boolean TABLE_9_SCHEMA_PUBLIC = true; + public final static String TABLE_9_DESCRIPTION = "Location"; + public final static String TABLE_9_QUEUE_NAME = TABLE_9_INTERNAL_NAME; + public final static String TABLE_9_ROUTING_KEY = "dbrepo." + DATABASE_4_ID + "." + TABLE_9_ID; + public final static Instant TABLE_9_CREATED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; + public final static Instant TABLE_9_LAST_MODIFIED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; + + public final Table TABLE_9 = Table.builder() .id(TABLE_9_ID) .tdbid(DATABASE_4_ID) .internalName(TABLE_9_INTERNAL_NAME) @@ -2291,7 +2425,7 @@ public abstract class BaseTest { .lastModified(TABLE_9_LAST_MODIFIED) .build(); - public static final TableDto TABLE_9_DTO = TableDto.builder() + public final TableDto TABLE_9_DTO = TableDto.builder() .id(TABLE_9_ID) .databaseId(DATABASE_4_ID) .internalName(TABLE_9_INTERNAL_NAME) @@ -2306,7 +2440,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableBriefDto TABLE_9_BRIEF_DTO = TableBriefDto.builder() + public final TableBriefDto TABLE_9_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_9_ID) .databaseId(DATABASE_4_ID) .internalName(TABLE_9_INTERNAL_NAME) @@ -2318,22 +2452,21 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .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"; + public final static UUID COLUMN_9_1_ID = UUID.fromString("e03c7578-2d1a-4599-9b11-7174f40efc0a"); + public final static String COLUMN_9_1_NAME = "location"; + public final static String COLUMN_9_1_INTERNAL_NAME = "location"; - public static final ColumnBriefDto TABLE_9_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final ColumnBriefDto TABLE_9_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_9_1_ID) .name(COLUMN_9_1_NAME) .internalName(COLUMN_9_1_INTERNAL_NAME) .columnType(ColumnTypeDto.BIGINT) .build(); - public static final UUID COLUMN_9_2_ID = UUID.fromString("03c07223-17e1-4af5-b1ae-ef9ab434fe2d"); - - public static final UUID COLUMN_9_3_ID = UUID.fromString("ee6590db-923b-4234-beb8-3120da055cf6"); + public final static UUID COLUMN_9_2_ID = UUID.fromString("03c07223-17e1-4af5-b1ae-ef9ab434fe2d"); + public final static UUID COLUMN_9_3_ID = UUID.fromString("ee6590db-923b-4234-beb8-3120da055cf6"); - public static final List<TableColumn> TABLE_9_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_9_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_9_1_ID) .ordinalPosition(0) .table(TABLE_9) @@ -2372,7 +2505,7 @@ public abstract class BaseTest { .sets(null) .build()); - public static final List<ColumnDto> TABLE_9_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_9_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_9_1_ID) .ordinalPosition(0) .name(COLUMN_9_1_NAME) @@ -2408,7 +2541,7 @@ public abstract class BaseTest { .sets(null) .build()); - public static final Constraints TABLE_9_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_9_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -2419,7 +2552,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_9_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_9_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -2430,17 +2563,17 @@ 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 final static UUID QUERY_9_ID = UUID.fromString("df34f0b9-b64c-406c-9109-7a031f4a7f27"); + public final static String QUERY_9_STATEMENT = "SELECT `lat`, `lng` FROM `mfcc` WHERE `location` = 'Fuji'"; + public final static String QUERY_9_QUERY_HASH = "dfcdec827b2ea74d89415f8d1ce39354f59ef304444ba4e12e4f3d9d3f35abe3"; + public final static String QUERY_9_RESULT_HASH = "f0aba070a1fd29e96230d12d7c0b4d08b89820b3cc2dda0575680492010016e7"; + public final static Instant QUERY_9_CREATED = Instant.now().minus(5, MINUTES); + public final static Instant QUERY_9_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Instant QUERY_9_LAST_MODIFIED = Instant.ofEpochSecond(1551588555L); + public final static Long QUERY_9_RESULT_NUMBER = 6L; + public final static Boolean QUERY_9_PERSISTED = true; - public static final QueryDto QUERY_9_DTO = QueryDto.builder() + public final QueryDto QUERY_9_DTO = QueryDto.builder() .id(QUERY_9_ID) .databaseId(DATABASE_3_ID) .query(QUERY_9_STATEMENT) @@ -2453,7 +2586,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final SubsetDto QUERY_9_SUBSET_DTO = SubsetDto.builder() + public 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() @@ -2464,7 +2597,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ViewDto QUERY_9_VIEW_DTO = ViewDto.builder() + public final ViewDto QUERY_9_VIEW_DTO = ViewDto.builder() .query(QUERY_9_STATEMENT) .queryHash(QUERY_9_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -2478,14 +2611,14 @@ public abstract class BaseTest { .build()))) .build(); - public static final String QUEUE_NAME = "dbrepo"; - public static final String QUEUE_VHOST = "dbrepo"; - public static final Boolean QUEUE_AUTO_DELETE = false; - public static final Boolean QUEUE_DURABLE = true; - public static final Boolean QUEUE_EXCLUSIVE = false; - public static final String QUEUE_TYPE = "quorum"; + public final static String QUEUE_NAME = "dbrepo"; + public final static String QUEUE_VHOST = "dbrepo"; + public final static Boolean QUEUE_AUTO_DELETE = false; + public final static Boolean QUEUE_DURABLE = true; + public final static Boolean QUEUE_EXCLUSIVE = false; + public final static String QUEUE_TYPE = "quorum"; - public static final QueueDto QUEUE_DTO = QueueDto.builder() + public final QueueDto QUEUE_DTO = QueueDto.builder() .name(QUEUE_NAME) .vhost(QUEUE_VHOST) .autoDelete(QUEUE_AUTO_DELETE) @@ -2494,18 +2627,17 @@ public abstract class BaseTest { .type(QUEUE_TYPE) .build(); - public static final UUID ONTOLOGY_1_ID = UUID.fromString("dc195d01-0a45-4583-aa83-fd270b874353"); - public static final String ONTOLOGY_1_PREFIX = "om2"; - public static final String ONTOLOGY_1_NEW_PREFIX = "om-2"; - public static final String ONTOLOGY_1_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/"; - public static final String ONTOLOGY_1_URI_PATTERN = "http://www.ontology-of-units-of-measure.org/resource/om-2/.*"; - public static final String ONTOLOGY_1_SPARQL_ENDPOINT = null; - public static final Boolean ONTOLOGY_1_SPARQL = false; - public static final String ONTOLOGY_1_RDF_PATH = "rdf/om-2.0.rdf"; - public static final Boolean ONTOLOGY_1_RDF = true; - public static final UUID ONTOLOGY_1_CREATED_BY = USER_1_ID; + public final static UUID ONTOLOGY_1_ID = UUID.fromString("dc195d01-0a45-4583-aa83-fd270b874353"); + public final static String ONTOLOGY_1_PREFIX = "om2"; + public final static String ONTOLOGY_1_NEW_PREFIX = "om-2"; + public final static String ONTOLOGY_1_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/"; + public final static String ONTOLOGY_1_URI_PATTERN = "http://www.ontology-of-units-of-measure.org/resource/om-2/.*"; + public final static String ONTOLOGY_1_SPARQL_ENDPOINT = null; + public final static Boolean ONTOLOGY_1_SPARQL = false; + public final static String ONTOLOGY_1_RDF_PATH = "rdf/om-2.0.rdf"; + public final static Boolean ONTOLOGY_1_RDF = true; - public static final Ontology ONTOLOGY_1 = Ontology.builder() + public final Ontology ONTOLOGY_1 = Ontology.builder() .id(ONTOLOGY_1_ID) .prefix(ONTOLOGY_1_PREFIX) .uri(ONTOLOGY_1_URI) @@ -2514,7 +2646,7 @@ public abstract class BaseTest { .rdfPath(ONTOLOGY_1_RDF_PATH) .build(); - public static final OntologyDto ONTOLOGY_1_DTO = OntologyDto.builder() + public final OntologyDto ONTOLOGY_1_DTO = OntologyDto.builder() .id(ONTOLOGY_1_ID) .prefix(ONTOLOGY_1_PREFIX) .uri(ONTOLOGY_1_URI) @@ -2525,7 +2657,7 @@ public abstract class BaseTest { .rdf(ONTOLOGY_1_RDF) .build(); - public static final OntologyBriefDto ONTOLOGY_1_BRIEF_DTO = OntologyBriefDto.builder() + public final OntologyBriefDto ONTOLOGY_1_BRIEF_DTO = OntologyBriefDto.builder() .id(ONTOLOGY_1_ID) .prefix(ONTOLOGY_1_PREFIX) .uri(ONTOLOGY_1_URI) @@ -2534,131 +2666,124 @@ public abstract class BaseTest { .rdf(ONTOLOGY_1_RDF) .build(); - public static final OntologyCreateDto ONTOLOGY_1_CREATE_DTO = OntologyCreateDto.builder() + public final OntologyCreateDto ONTOLOGY_1_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_1_PREFIX) .uri(ONTOLOGY_1_URI) .sparqlEndpoint(ONTOLOGY_1_SPARQL_ENDPOINT) .build(); - public static final OntologyModifyDto ONTOLOGY_1_MODIFY_DTO = OntologyModifyDto.builder() + public final OntologyModifyDto ONTOLOGY_1_MODIFY_DTO = OntologyModifyDto.builder() .prefix(ONTOLOGY_1_NEW_PREFIX) .uri(ONTOLOGY_1_URI) .sparqlEndpoint(ONTOLOGY_1_SPARQL_ENDPOINT) .build(); - public static final UUID ONTOLOGY_2_ID = UUID.fromString("41d902a1-f9f8-4d51-ad64-618b72acf5ed"); - public static final String ONTOLOGY_2_PREFIX = "wd"; - public static final String ONTOLOGY_2_URI = "http://www.wikidata.org/"; - public static final String ONTOLOGY_2_SPARQL_ENDPOINT = "https://query.wikidata.org/sparql"; - public static final UUID ONTOLOGY_2_CREATED_BY = USER_1_ID; + public final static UUID ONTOLOGY_2_ID = UUID.fromString("41d902a1-f9f8-4d51-ad64-618b72acf5ed"); + public final static String ONTOLOGY_2_PREFIX = "wd"; + public final static String ONTOLOGY_2_URI = "http://www.wikidata.org/"; + public final static String ONTOLOGY_2_SPARQL_ENDPOINT = "https://query.wikidata.org/sparql"; - public static final Ontology ONTOLOGY_2 = Ontology.builder() + public final Ontology ONTOLOGY_2 = Ontology.builder() .id(ONTOLOGY_2_ID) .prefix(ONTOLOGY_2_PREFIX) .uri(ONTOLOGY_2_URI) .sparqlEndpoint(ONTOLOGY_2_SPARQL_ENDPOINT) .build(); - public static final OntologyCreateDto ONTOLOGY_2_CREATE_DTO = OntologyCreateDto.builder() + public final OntologyCreateDto ONTOLOGY_2_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_2_PREFIX) .uri(ONTOLOGY_2_URI) .sparqlEndpoint(ONTOLOGY_2_SPARQL_ENDPOINT) .build(); - public static final UUID ONTOLOGY_3_ID = UUID.fromString("5b41390b-d2d2-45c6-8038-1258c4b2725f"); - public static final String ONTOLOGY_3_PREFIX = "rdfs"; - public static final String ONTOLOGY_3_URI = "http://www.w3.org/2000/01/rdf-schema#"; - public static final String ONTOLOGY_3_SPARQL_ENDPOINT = null; - public static final UUID ONTOLOGY_3_CREATED_BY = USER_1_ID; + public final static UUID ONTOLOGY_3_ID = UUID.fromString("5b41390b-d2d2-45c6-8038-1258c4b2725f"); + public final static String ONTOLOGY_3_PREFIX = "rdfs"; + public final static String ONTOLOGY_3_URI = "http://www.w3.org/2000/01/rdf-schema#"; + public final static String ONTOLOGY_3_SPARQL_ENDPOINT = null; - public static final Ontology ONTOLOGY_3 = Ontology.builder() + public final Ontology ONTOLOGY_3 = Ontology.builder() .id(ONTOLOGY_3_ID) .prefix(ONTOLOGY_3_PREFIX) .uri(ONTOLOGY_3_URI) .sparqlEndpoint(ONTOLOGY_3_SPARQL_ENDPOINT) .build(); - public static final OntologyCreateDto ONTOLOGY_3_CREATE_DTO = OntologyCreateDto.builder() + public final OntologyCreateDto ONTOLOGY_3_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_3_PREFIX) .uri(ONTOLOGY_3_URI) .sparqlEndpoint(ONTOLOGY_3_SPARQL_ENDPOINT) .build(); - public static final UUID ONTOLOGY_4_ID = UUID.fromString("d6992475-9b71-4a4a-a6eb-bc1fe6a34443"); - public static final String ONTOLOGY_4_PREFIX = "schema"; - public static final String ONTOLOGY_4_URI = "http://schema.org/"; - public static final String ONTOLOGY_4_SPARQL_ENDPOINT = null; - public static final UUID ONTOLOGY_4_CREATED_BY = USER_1_ID; + public final static UUID ONTOLOGY_4_ID = UUID.fromString("d6992475-9b71-4a4a-a6eb-bc1fe6a34443"); + public final static String ONTOLOGY_4_PREFIX = "schema"; + public final static String ONTOLOGY_4_URI = "http://schema.org/"; + public final static String ONTOLOGY_4_SPARQL_ENDPOINT = null; - public static final Ontology ONTOLOGY_4 = Ontology.builder() + public final Ontology ONTOLOGY_4 = Ontology.builder() .id(ONTOLOGY_4_ID) .prefix(ONTOLOGY_4_PREFIX) .uri(ONTOLOGY_4_URI) .sparqlEndpoint(ONTOLOGY_4_SPARQL_ENDPOINT) .build(); - public static final OntologyCreateDto ONTOLOGY_4_CREATE_DTO = OntologyCreateDto.builder() + public final OntologyCreateDto ONTOLOGY_4_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_4_PREFIX) .uri(ONTOLOGY_4_URI) .sparqlEndpoint(ONTOLOGY_4_SPARQL_ENDPOINT) .build(); - public static final UUID ONTOLOGY_5_ID = UUID.fromString("f95d1330-762e-4f5a-875a-3c64da5808a1"); - public static final String ONTOLOGY_5_PREFIX = "db"; - public static final String ONTOLOGY_5_URI = "http://dbpedia.org"; - public static final String ONTOLOGY_5_SPARQL_ENDPOINT = "http://dbpedia.org/sparql"; - public static final UUID ONTOLOGY_5_CREATED_BY = USER_1_ID; + public final static UUID ONTOLOGY_5_ID = UUID.fromString("f95d1330-762e-4f5a-875a-3c64da5808a1"); + public final static String ONTOLOGY_5_PREFIX = "db"; + public final static String ONTOLOGY_5_URI = "http://dbpedia.org"; + public final static String ONTOLOGY_5_SPARQL_ENDPOINT = "http://dbpedia.org/sparql"; - public static final Ontology ONTOLOGY_5 = Ontology.builder() + public final Ontology ONTOLOGY_5 = Ontology.builder() .id(ONTOLOGY_5_ID) .prefix(ONTOLOGY_5_PREFIX) .uri(ONTOLOGY_5_URI) .sparqlEndpoint(ONTOLOGY_5_SPARQL_ENDPOINT) .build(); - public static final OntologyCreateDto ONTOLOGY_5_CREATE_DTO = OntologyCreateDto.builder() + public final OntologyCreateDto ONTOLOGY_5_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_5_PREFIX) .uri(ONTOLOGY_5_URI) .sparqlEndpoint(ONTOLOGY_5_SPARQL_ENDPOINT) .build(); - public static final UUID COLUMN_8_1_ID = UUID.fromString("af362ac6-5dbb-4ede-83ea-5d94b39641c8"); - public static final Integer COLUMN_8_1_ORDINALPOS = 0; - public static final String COLUMN_8_1_NAME = "ID"; - public static final String COLUMN_8_1_INTERNAL_NAME = "id"; - public static final TableColumnType COLUMN_8_1_TYPE = TableColumnType.BIGINT; - public static final ColumnTypeDto COLUMN_8_1_TYPE_DTO = ColumnTypeDto.BIGINT; - public static final Boolean COLUMN_8_1_NULL = false; - public static final Boolean COLUMN_8_1_AUTO_GENERATED = true; - - public static final UUID COLUMN_8_2_ID = UUID.fromString("7ada597b-0766-4612-9ace-67eeee94e2da"); - public static final Integer COLUMN_8_2_ORDINALPOS = 1; - public static final String COLUMN_8_2_NAME = "Value"; - public static final String COLUMN_8_2_INTERNAL_NAME = "value"; - public static final TableColumnType COLUMN_8_2_TYPE = TableColumnType.DECIMAL; - public static final ColumnTypeDto COLUMN_8_2_TYPE_DTO = ColumnTypeDto.DECIMAL; - public static final Long COLUMN_8_2_SIZE = 10L; - public static final Long COLUMN_8_2_D = 10L; - public static final Boolean COLUMN_8_2_NULL = false; - public static final Boolean COLUMN_8_2_AUTO_GENERATED = false; - - public static final UUID COLUMN_8_3_ID = UUID.fromString("8bcd9ef8-f7b8-4730-acc1-a3d43ba69a56"); - public static final Integer COLUMN_8_3_ORDINALPOS = 2; - public static final String COLUMN_8_3_NAME = "raw"; - public static final String COLUMN_8_3_INTERNAL_NAME = "raw"; - public static final TableColumnType COLUMN_8_3_TYPE = TableColumnType.LONGBLOB; - public static final ColumnTypeDto COLUMN_8_3_TYPE_DTO = ColumnTypeDto.LONGBLOB; - public static final Boolean COLUMN_8_3_NULL = true; - public static final Boolean COLUMN_8_3_AUTO_GENERATED = false; - - public static final ColumnBriefDto TABLE_8_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final static UUID COLUMN_8_1_ID = UUID.fromString("af362ac6-5dbb-4ede-83ea-5d94b39641c8"); + public final static Integer COLUMN_8_1_ORDINALPOS = 0; + public final static String COLUMN_8_1_NAME = "ID"; + public final static String COLUMN_8_1_INTERNAL_NAME = "id"; + public final static TableColumnType COLUMN_8_1_TYPE = TableColumnType.BIGINT; + public final static ColumnTypeDto COLUMN_8_1_TYPE_DTO = ColumnTypeDto.BIGINT; + public final static Boolean COLUMN_8_1_NULL = false; + + public final static UUID COLUMN_8_2_ID = UUID.fromString("7ada597b-0766-4612-9ace-67eeee94e2da"); + public final static Integer COLUMN_8_2_ORDINALPOS = 1; + public final static String COLUMN_8_2_NAME = "Value"; + public final static String COLUMN_8_2_INTERNAL_NAME = "value"; + public final static TableColumnType COLUMN_8_2_TYPE = TableColumnType.DECIMAL; + public final static ColumnTypeDto COLUMN_8_2_TYPE_DTO = ColumnTypeDto.DECIMAL; + public final static Long COLUMN_8_2_SIZE = 10L; + public final static Long COLUMN_8_2_D = 10L; + public final static Boolean COLUMN_8_2_NULL = true; + + public final static UUID COLUMN_8_3_ID = UUID.fromString("8bcd9ef8-f7b8-4730-acc1-a3d43ba69a56"); + public final static Integer COLUMN_8_3_ORDINALPOS = 2; + public final static String COLUMN_8_3_NAME = "raw"; + public final static String COLUMN_8_3_INTERNAL_NAME = "raw"; + public final static TableColumnType COLUMN_8_3_TYPE = TableColumnType.LONGBLOB; + public final static ColumnTypeDto COLUMN_8_3_TYPE_DTO = ColumnTypeDto.LONGBLOB; + public final static Boolean COLUMN_8_3_NULL = true; + + public final ColumnBriefDto TABLE_8_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_8_1_ID) .name(COLUMN_8_1_NAME) .internalName(COLUMN_8_1_INTERNAL_NAME) .columnType(ColumnTypeDto.BIGINT) .build(); - public static final List<TableColumn> TABLE_8_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_8_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_8_1_ID) .ordinalPosition(COLUMN_8_1_ORDINALPOS) .table(TABLE_8) @@ -2688,7 +2813,7 @@ public abstract class BaseTest { .isNullAllowed(COLUMN_8_3_NULL) .build()); - public static final List<ColumnDto> TABLE_8_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_8_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_8_1_ID) .ordinalPosition(COLUMN_8_1_ORDINALPOS) .name(COLUMN_8_1_NAME) @@ -2713,9 +2838,9 @@ public abstract class BaseTest { .isNullAllowed(COLUMN_8_3_NULL) .build()); - public static final Long TABLE_8_DATA_COUNT = 6L; + public final static Long TABLE_8_DATA_COUNT = 6L; @SuppressWarnings("java:S3599") - public static final List<Map<String, Object>> TABLE_8_DATA_DTO = new LinkedList<>(List.of( + public final List<Map<String, Object>> TABLE_8_DATA_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, BigInteger.valueOf(1L)); put(COLUMN_8_2_INTERNAL_NAME, 11.2); @@ -2749,29 +2874,27 @@ public abstract class BaseTest { )); @SuppressWarnings("java:S3599") - public static final TableStatisticDto TABLE_8_STATISTIC_DTO = TableStatisticDto.builder() - .columns(new HashMap<>() {{ - put(COLUMN_8_1_INTERNAL_NAME, ColumnStatisticDto.builder() - .min(BigDecimal.valueOf(11.2)) - .max(BigDecimal.valueOf(23.1)) - .mean(BigDecimal.valueOf(13.5333)) - .median(BigDecimal.valueOf(11.4)) - .stdDev(BigDecimal.valueOf(4.2952)) - .build()); - }}) - .build(); - - public static final UUID QUERY_1_ID = UUID.fromString("60494137-f000-459e-acd3-4fcadbdf14ca"); - public static final String QUERY_1_STATEMENT = "SELECT `id`, `date`, `location`, `mintemp`, `rainfall` FROM `weather_aus` ORDER BY id ASC"; - public static final String QUERY_1_DOI = null; - public static final Long QUERY_1_RESULT_NUMBER = 2L; - public static final String QUERY_1_QUERY_HASH = "a3b8ac39e38167d14cf3a9c20a69e4b6954d049525390b973a2c23064953a992"; - public static final String QUERY_1_RESULT_HASH = "8358c8ade4849d2094ab5bb29127afdae57e6bb5acb1db7af603813d406c467a"; - public static final Instant QUERY_1_CREATED = Instant.ofEpochSecond(1677648377L); - public static final Instant QUERY_1_EXECUTION = Instant.now(); - public static final Boolean QUERY_1_PERSISTED = true; - - public static final SubsetDto QUERY_1_SUBSET_DTO = SubsetDto.builder() + public final TableStatisticDto TABLE_8_STATISTIC_DTO = TableStatisticDto.builder() + .columns(new LinkedList<>(List.of(ColumnStatisticDto.builder() + .name(COLUMN_8_1_INTERNAL_NAME) + .min(BigDecimal.valueOf(11.2)) + .max(BigDecimal.valueOf(23.1)) + .mean(BigDecimal.valueOf(13.5333)) + .median(BigDecimal.valueOf(11.4)) + .stdDev(BigDecimal.valueOf(4.2952)) + .build()))) + .build(); + + public final static UUID QUERY_1_ID = UUID.fromString("60494137-f000-459e-acd3-4fcadbdf14ca"); + public final static String QUERY_1_STATEMENT = "SELECT `id`, `date`, `location`, `mintemp`, `rainfall` FROM `weather_aus` ORDER BY id ASC"; + public final static Long QUERY_1_RESULT_NUMBER = 2L; + public final static String QUERY_1_QUERY_HASH = "a3b8ac39e38167d14cf3a9c20a69e4b6954d049525390b973a2c23064953a992"; + public final static String QUERY_1_RESULT_HASH = "8358c8ade4849d2094ab5bb29127afdae57e6bb5acb1db7af603813d406c467a"; + public final static Instant QUERY_1_CREATED = Instant.ofEpochSecond(1677648377L); + public final static Instant QUERY_1_EXECUTION = Instant.now(); + public final static Boolean QUERY_1_PERSISTED = true; + + public 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))) .order(new LinkedList<OrderDto>(List.of(OrderDto.builder() @@ -2780,7 +2903,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ViewDto QUERY_1_VIEW_DTO = ViewDto.builder() + public final ViewDto QUERY_1_VIEW_DTO = ViewDto.builder() .query(QUERY_1_STATEMENT) .queryHash(QUERY_1_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -2806,7 +2929,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final QueryBriefDto QUERY_1_BRIEF_DTO = QueryBriefDto.builder() + public final QueryBriefDto QUERY_1_BRIEF_DTO = QueryBriefDto.builder() .id(QUERY_1_ID) .databaseId(DATABASE_1_ID) .query(QUERY_1_STATEMENT) @@ -2818,49 +2941,32 @@ public abstract class BaseTest { .resultNumber(3L) .build(); - public static final UUID QUERY_2_ID = UUID.fromString("4e0ac92a-7cb3-4222-9b85-0498c73e0afd"); - public static final String QUERY_2_STATEMENT = "SELECT `location` FROM `weather_aus`"; - public static final String QUERY_2_QUERY_HASH = "a2d2dd94ebc7653bb5a3b55dd8ed5e91d3d13c225c6855a1eb4eb7ca14c36ced"; - public static final Long QUERY_2_RESULT_NUMBER = 2L; - public static final String QUERY_2_RESULT_HASH = "ff3f7cbe1b96d296957f6e39e55b8b1b577fa3d205d4795af99594cfd20cb80d"; - public static final Instant QUERY_2_CREATED = Instant.now().minus(2, MINUTES); - public static final Instant QUERY_2_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_2_LAST_MODIFIED = Instant.ofEpochSecond(1541588352L); - public static final Boolean QUERY_2_PERSISTED = false; - - 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"; - public static final String QUERY_3_RESULT_HASH = "ff3f7cbe1b96d396957f6e39e55b8b1b577fa3d305d4795af99594cfd30cb80d"; - public static final Instant QUERY_3_CREATED = Instant.now().minus(3, MINUTES); - public static final Instant QUERY_3_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_3_LAST_MODIFIED = Instant.ofEpochSecond(1541588353L); - public static final Long QUERY_3_RESULT_NUMBER = 2L; - public static final Boolean QUERY_3_PERSISTED = true; - - 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"; - public static final String QUERY_7_RESULT_HASH = "ff4f7cbe1b96d496957f6e49e55b8b1b577fa4d405d4795af99594cfd40cb80d"; - public static final Instant QUERY_7_CREATED = Instant.now().minus(4, MINUTES); - public static final Instant QUERY_7_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_7_LAST_MODIFIED = Instant.ofEpochSecond(1541588454L); - public static final Long QUERY_7_RESULT_NUMBER = 6L; - public static final Long QUERY_7_RESULT_ID = 4L; - public static final Boolean QUERY_7_PERSISTED = false; - - 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"; - public static final String QUERY_4_RESULT_HASH = "ff4f7cbe1b96d496957f6e49e55b8b1b577fa4d405d4795af99594cfd40cb80d"; - public static final Instant QUERY_4_CREATED = Instant.now().minus(4, MINUTES); - public static final Instant QUERY_4_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_4_LAST_MODIFIED = Instant.ofEpochSecond(1541588454L); - public static final Long QUERY_4_RESULT_NUMBER = 6L; - public static final Long QUERY_4_RESULT_ID = 4L; - public static final Boolean QUERY_4_PERSISTED = false; - - public static final List<Map<String, Object>> QUERY_4_RESULT_DTO = new LinkedList<>(List.of( + public final static UUID QUERY_2_ID = UUID.fromString("4e0ac92a-7cb3-4222-9b85-0498c73e0afd"); + public final static String QUERY_2_STATEMENT = "SELECT `location` FROM `weather_aus`"; + public final static String QUERY_2_QUERY_HASH = "a2d2dd94ebc7653bb5a3b55dd8ed5e91d3d13c225c6855a1eb4eb7ca14c36ced"; + public final static Long QUERY_2_RESULT_NUMBER = 2L; + public final static String QUERY_2_RESULT_HASH = "ff3f7cbe1b96d296957f6e39e55b8b1b577fa3d205d4795af99594cfd20cb80d"; + public final static Instant QUERY_2_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Boolean QUERY_2_PERSISTED = false; + + public final static UUID QUERY_3_ID = UUID.fromString("a9849020-45a7-40a8-9a19-d4ae2b28dd46"); + public final static String QUERY_3_STATEMENT = "SELECT `location`, `mintemp` FROM `weather_aus` WHERE `mintemp` > 10"; + public final static String QUERY_3_QUERY_HASH = "a3d3dd94ebc7653bb5a3b55dd8ed5e91d3d13c335c6855a1eb4eb7ca14c36ced"; + public final static String QUERY_3_RESULT_HASH = "ff3f7cbe1b96d396957f6e39e55b8b1b577fa3d305d4795af99594cfd30cb80d"; + public final static Instant QUERY_3_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Long QUERY_3_RESULT_NUMBER = 2L; + public final static Boolean QUERY_3_PERSISTED = true; + + public final static UUID QUERY_4_ID = UUID.fromString("18a98197-51ff-4011-9f40-914a11675a6d"); + public final static String QUERY_4_STATEMENT = "SELECT `id`, `value` FROM `mfcc`"; + public final static String QUERY_4_QUERY_HASH = "df7da3801dfb5c191ff6711d79ce6455f3c09ec8323ce1ff7208ab85387263f5"; + public final static String QUERY_4_RESULT_HASH = "ff4f7cbe1b96d496957f6e49e55b8b1b577fa4d405d4795af99594cfd40cb80d"; + public final static Instant QUERY_4_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Long QUERY_4_RESULT_NUMBER = 6L; + public final static Long QUERY_4_RESULT_ID = 4L; + public final static Boolean QUERY_4_PERSISTED = false; + + public final List<Map<String, Object>> QUERY_4_RESULT_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put("id", BigInteger.valueOf(1L)); put("value", 11.2); @@ -2881,7 +2987,7 @@ public abstract class BaseTest { put("value", 23.1); }})); - public static final QueryDto QUERY_4_DTO = QueryDto.builder() + public final QueryDto QUERY_4_DTO = QueryDto.builder() .id(QUERY_4_ID) .databaseId(DATABASE_3_ID) .query(QUERY_4_STATEMENT) @@ -2894,17 +3000,15 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final UUID QUERY_5_ID = UUID.fromString("1a39f775-e3d5-4865-b4f5-dbbb5693b637"); - public static final String QUERY_5_STATEMENT = "SELECT `id`, `value` FROM `mfcc` WHERE `value` > 0"; - public static final String QUERY_5_QUERY_HASH = "6d6dc48b12cdfd959d39a62887334a6bbd529b93eed4f211f3f671bd9e7d6225"; - public static final String QUERY_5_RESULT_HASH = "ff5f7cbe1b96d596957f6e59e55b8b1b577fa5d505d5795af99595cfd50cb80d"; - public static final Instant QUERY_5_CREATED = Instant.now().minus(5, MINUTES); - public static final Instant QUERY_5_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_5_LAST_MODIFIED = Instant.ofEpochSecond(1551588555L); - public static final Long QUERY_5_RESULT_NUMBER = 6L; - public static final Boolean QUERY_5_PERSISTED = true; + public final static UUID QUERY_5_ID = UUID.fromString("1a39f775-e3d5-4865-b4f5-dbbb5693b637"); + public final static String QUERY_5_STATEMENT = "SELECT `id`, `value` FROM `mfcc` WHERE `value` > 0"; + public final static String QUERY_5_QUERY_HASH = "6d6dc48b12cdfd959d39a62887334a6bbd529b93eed4f211f3f671bd9e7d6225"; + public final static String QUERY_5_RESULT_HASH = "ff5f7cbe1b96d596957f6e59e55b8b1b577fa5d505d5795af99595cfd50cb80d"; + public final static Instant QUERY_5_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Long QUERY_5_RESULT_NUMBER = 6L; + public final static Boolean QUERY_5_PERSISTED = true; - public static final QueryDto QUERY_5_DTO = QueryDto.builder() + public final QueryDto QUERY_5_DTO = QueryDto.builder() .id(QUERY_5_ID) .databaseId(DATABASE_3_ID) .query(QUERY_5_STATEMENT) @@ -2917,7 +3021,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final SubsetDto QUERY_5_SUBSET_DTO = SubsetDto.builder() + public 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() @@ -2928,7 +3032,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ViewDto QUERY_5_VIEW_DTO = ViewDto.builder() + public final ViewDto QUERY_5_VIEW_DTO = ViewDto.builder() .query(QUERY_5_STATEMENT) .queryHash(QUERY_5_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -2942,7 +3046,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final List<Map<String, Object>> QUERY_5_RESULT_DTO = new LinkedList<>(List.of( + public final List<Map<String, Object>> QUERY_5_RESULT_DTO = new LinkedList<>(List.of( Map.of("id", BigInteger.valueOf(1L), "value", 11.2), Map.of("id", BigInteger.valueOf(2L), "value", 11.3), Map.of("id", BigInteger.valueOf(3L), "value", 11.4), @@ -2951,17 +3055,15 @@ public abstract class BaseTest { Map.of("id", BigInteger.valueOf(6L), "value", 23.1) )); - public static final UUID QUERY_6_ID = UUID.fromString("7463412a-20c4-4fc1-8a33-948aea026f49"); - public static final String QUERY_6_STATEMENT = "SELECT `location` FROM `weather_aus` WHERE `id` = 1"; - public static final String QUERY_6_QUERY_HASH = "6d6dc48b12cdfd959d39a62887334a6bbd529b93eed4f211f3f671bd9e7d6225"; - public static final String QUERY_6_RESULT_HASH = "ff5f7cbe1b96d596957f6e59e55b8b1b577fa5d505d5795af99595cfd50cb80d"; - public static final Instant QUERY_6_CREATED = Instant.now().minus(5, MINUTES); - public static final Instant QUERY_6_EXECUTION = Instant.now().minus(1, MINUTES); - public static final Instant QUERY_6_LAST_MODIFIED = Instant.ofEpochSecond(1551588555L); - public static final Long QUERY_6_RESULT_NUMBER = 1L; - public static final Boolean QUERY_6_PERSISTED = true; - - public static final List<TableColumn> TABLE_1_COLUMNS = List.of(TableColumn.builder() + public final static UUID QUERY_6_ID = UUID.fromString("7463412a-20c4-4fc1-8a33-948aea026f49"); + public final static String QUERY_6_STATEMENT = "SELECT `location` FROM `weather_aus` WHERE `id` = 1"; + public final static String QUERY_6_QUERY_HASH = "6d6dc48b12cdfd959d39a62887334a6bbd529b93eed4f211f3f671bd9e7d6225"; + public final static String QUERY_6_RESULT_HASH = "ff5f7cbe1b96d596957f6e59e55b8b1b577fa5d505d5795af99595cfd50cb80d"; + public final static Instant QUERY_6_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Long QUERY_6_RESULT_NUMBER = 1L; + public final static Boolean QUERY_6_PERSISTED = true; + + public final List<TableColumn> TABLE_1_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_1_1_ID) .ordinalPosition(0) .table(TABLE_1) @@ -3014,14 +3116,16 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final ColumnBriefDto TABLE_1_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() - .id(COLUMN_1_1_ID) - .name("id") - .internalName("id") - .columnType(ColumnTypeDto.BIGINT) - .build(); + public final static UUID QUERY_7_ID = UUID.fromString("fe73a325-30a0-444c-b74f-23ce1533e55f"); + public final static 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 final static String QUERY_7_QUERY_HASH = "df7da3801dfb5c191ff6711d79ce6455f3c09ec8323ce1ff7208ab85387263f5"; + public final static String QUERY_7_RESULT_HASH = "ff4f7cbe1b96d496957f6e49e55b8b1b577fa4d405d4795af99594cfd40cb80d"; + public final static Instant QUERY_7_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Long QUERY_7_RESULT_NUMBER = 6L; + public final static Long QUERY_7_RESULT_ID = 4L; + public final static Boolean QUERY_7_PERSISTED = false; - public static final List<CreateTableColumnDto> TABLE_1_COLUMNS_CREATE_DTO = List.of(CreateTableColumnDto.builder() + public final List<CreateTableColumnDto> TABLE_1_COLUMNS_CREATE_DTO = List.of(CreateTableColumnDto.builder() .name("id") .type(ColumnTypeDto.BIGINT) .nullAllowed(false) @@ -3056,48 +3160,37 @@ public abstract class BaseTest { .unitUri(UNIT_1_URI) .build()); - public static final CreateTableConstraintsDto TABLE_1_CONSTRAINTS_CREATE_DTO = CreateTableConstraintsDto.builder() - .checks(new LinkedHashSet<>()) - .primaryKey(new LinkedHashSet<>(List.of("id"))) - .foreignKeys(new LinkedList<>()) - .uniques(new LinkedList<>(List.of(List.of("date")))) - .build(); - - public static final CreateTableConstraintsDto TABLE_1_CONSTRAINTS_CREATE_INVALID_DTO = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_1_CONSTRAINTS_CREATE_INVALID_DTO = CreateTableConstraintsDto.builder() .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>(List.of(List.of("date")))) .build(); - public static final CreateTableDto TABLE_1_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_1_CREATE_DTO = CreateTableDto.builder() .name(TABLE_1_NAME) .description(TABLE_1_DESCRIPTION) .columns(TABLE_1_COLUMNS_CREATE_DTO) - .constraints(TABLE_1_CONSTRAINTS_CREATE_DTO) - .build(); - - public static final at.tuwien.api.database.table.internal.TableCreateDto TABLE_1_CREATE_INTERNAL_DTO = at.tuwien.api.database.table.internal.TableCreateDto.builder() - .name(TABLE_1_NAME) - .description(TABLE_1_DESCRIPTION) - .columns(TABLE_1_COLUMNS_CREATE_DTO) - .constraints(TABLE_1_CONSTRAINTS_CREATE_DTO) - .build(); - - public static final at.tuwien.api.database.table.internal.TableCreateDto TABLE_1_CREATE_INTERNAL_INVALID_DTO = at.tuwien.api.database.table.internal.TableCreateDto.builder() - .name(TABLE_1_NAME) - .description(TABLE_1_DESCRIPTION) - .columns(TABLE_1_COLUMNS_CREATE_DTO) - .constraints(TABLE_1_CONSTRAINTS_CREATE_INVALID_DTO) - .build(); - - public static final UUID COLUMN_2_1_ID = UUID.fromString("795faa78-7ebb-4dd5-9eb1-e54a9192d0b5"); - - public static final UUID COLUMN_2_2_ID = UUID.fromString("f316ced5-7774-4656-aa7f-a874622d99b3"); - - public static final UUID COLUMN_2_3_ID = UUID.fromString("11cb1aa2-8582-45ef-a3bb-7056aa94cdf1"); - - public static final List<TableColumn> TABLE_2_COLUMNS = List.of(TableColumn.builder() + .constraints(TABLE_1_CREATE_CONSTRAINTS_DTO) + .build(); + + public final at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto TABLE_1_CREATE_INTERNAL_DTO = + at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto.builder() + .name(TABLE_1_NAME) + .description(TABLE_1_DESCRIPTION) + .columns(TABLE_1_COLUMNS_CREATE_DTO) + .constraints(TABLE_1_CREATE_CONSTRAINTS_DTO) + .build(); + + public final at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto TABLE_1_CREATE_INTERNAL_INVALID_DTO = + at.ac.tuwien.ifs.dbrepo.core.api.database.table.internal.TableCreateDto.builder() + .name(TABLE_1_NAME) + .description(TABLE_1_DESCRIPTION) + .columns(TABLE_1_COLUMNS_CREATE_DTO) + .constraints(TABLE_1_CONSTRAINTS_CREATE_INVALID_DTO) + .build(); + + public final List<TableColumn> TABLE_2_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_2_1_ID) .ordinalPosition(0) .table(TABLE_2) @@ -3136,163 +3229,50 @@ public abstract class BaseTest { .sets(null) .build()); - public static final ColumnBriefDto TABLE_2_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() - .id(COLUMN_2_1_ID) - .name("location") - .internalName("location") - .columnType(ColumnTypeDto.VARCHAR) - .build(); - - public static final ColumnBriefDto TABLE_2_COLUMNS_BRIEF_2_DTO = ColumnBriefDto.builder() - .id(COLUMN_2_3_ID) - .name("lng") - .internalName("lng") - .columnType(ColumnTypeDto.DECIMAL) - .build(); - - public static final List<ColumnDto> TABLE_2_COLUMNS_DTO = List.of(ColumnDto.builder() - .id(COLUMN_2_1_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .ordinalPosition(0) - .name("location") - .internalName("location") - .columnType(ColumnTypeDto.VARCHAR) - .size(255L) - .isNullAllowed(false) - .enums(null) - .sets(null) - .build(), - ColumnDto.builder() - .id(COLUMN_2_2_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .ordinalPosition(1) - .name("lat") - .internalName("lat") - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) - .isNullAllowed(true) - .enums(null) - .sets(null) - .build(), - ColumnDto.builder() - .id(COLUMN_2_3_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .ordinalPosition(2) - .name("lng") - .internalName("lng") - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) - .isNullAllowed(true) - .enums(null) - .sets(null) - .build()); - - public static final List<ColumnBriefDto> TABLE_2_COLUMNS_BRIEF_DTO = List.of(ColumnBriefDto.builder() - .id(COLUMN_2_1_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .name("location") - .internalName("location") - .columnType(ColumnTypeDto.VARCHAR) - .build(), - ColumnBriefDto.builder() - .id(COLUMN_2_2_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .name("lat") - .internalName("lat") - .columnType(ColumnTypeDto.DOUBLE) - .build(), - ColumnBriefDto.builder() - .id(COLUMN_2_3_ID) - .tableId(TABLE_2_ID) - .databaseId(DATABASE_1_ID) - .name("lng") - .internalName("lng") - .columnType(ColumnTypeDto.DOUBLE) - .build()); - - public static final UUID COLUMN_3_1_ID = UUID.fromString("49cc2735-ba75-4e12-8ac7-8aec87ed7724"); - - public static final UUID COLUMN_3_2_ID = UUID.fromString("2c240d64-3052-4a74-b696-e7490fdff3ea"); - - public static final UUID COLUMN_3_3_ID = UUID.fromString("6fbb0a56-f23a-4aa4-b158-c614a0a30f86"); - - public static final UUID COLUMN_3_4_ID = UUID.fromString("9b01f925-93ee-4f28-bf31-9902900a7099"); - - public static final UUID COLUMN_3_5_ID = UUID.fromString("9bbd66f1-0d94-401c-b7f7-6e329bb9ee21"); - - public static final UUID COLUMN_3_6_ID = UUID.fromString("19ad93d7-b298-495b-9678-9aac80678ff9"); - - public static final UUID COLUMN_3_7_ID = UUID.fromString("4d27d9f4-645f-4222-b5a8-4a91fa6e4275"); - - public static final UUID COLUMN_3_8_ID = UUID.fromString("b4f8fcf8-5824-45ec-8c58-43f20e6dffc5"); - - public static final UUID COLUMN_3_9_ID = UUID.fromString("87247218-369e-484a-9a8f-d758478d8dfc"); - - public static final UUID COLUMN_3_10_ID = UUID.fromString("6e191b97-189a-4d88-901e-888ca889e280"); - - public static final UUID COLUMN_3_11_ID = UUID.fromString("6ac356ff-9be5-4259-9b62-83b6707be7fe"); - - public static final UUID COLUMN_3_12_ID = UUID.fromString("0665b384-c824-4358-b6c5-f17706d46ea4"); - - public static final UUID COLUMN_3_13_ID = UUID.fromString("22d3676e-d28e-4075-b223-91a7ac767bcf"); - - public static final UUID COLUMN_3_14_ID = UUID.fromString("673326e3-ee2b-4c2f-902f-982e2abce1c2"); - - public static final UUID COLUMN_3_15_ID = UUID.fromString("8dcacf4a-736b-4e67-9618-74998cba8940"); - - public static final UUID COLUMN_3_16_ID = UUID.fromString("2b2f5359-76d3-4763-a53f-d18ca6b793fb"); - - public static final UUID COLUMN_3_17_ID = UUID.fromString("674b6120-06cf-4624-b006-1ed48898bd69"); - - public static final UUID COLUMN_3_18_ID = UUID.fromString("13edd7c9-6c88-44d7-b206-34774e49c5af"); - - public static final UUID COLUMN_3_19_ID = UUID.fromString("6977bb3f-4ae2-43ea-bb82-c7f68454c538"); - - public static final UUID COLUMN_3_20_ID = UUID.fromString("c03d2429-53e1-42eb-a1f5-ce342fa23336"); - - public static final UUID COLUMN_3_21_ID = UUID.fromString("06edd332-750e-4aa1-b61b-e757fb2312c3"); - - public static final UUID COLUMN_3_22_ID = UUID.fromString("b6b8631d-f283-49da-8d5e-4bb24def2a40"); - - public static final UUID COLUMN_3_23_ID = UUID.fromString("0393ee00-31ba-44ab-9e82-1f5034a9f57b"); - - public static final UUID COLUMN_3_24_ID = UUID.fromString("a63784ea-f70d-4bda-ace6-1c6a88edf831"); - - public static final UUID COLUMN_3_25_ID = UUID.fromString("720fe829-802c-420b-8e41-bdbb636db43c"); - - public static final UUID COLUMN_3_26_ID = UUID.fromString("5bce38ef-7d49-43b5-9054-068750684b5f"); - - public static final UUID COLUMN_3_27_ID = UUID.fromString("92097c02-3dd3-40ea-bd03-a9135f45a557"); - - public static final UUID COLUMN_3_28_ID = UUID.fromString("7361a38a-828b-495e-8a57-b36cca17d7db"); - - public static final UUID COLUMN_3_29_ID = UUID.fromString("a06812db-03b7-484c-92a6-45d94eef3bb9"); - - public static final UUID COLUMN_3_30_ID = UUID.fromString("05614d89-9216-47ea-96f0-acffc4674acf"); - - public static final UUID COLUMN_3_31_ID = UUID.fromString("05ada13d-361a-48e7-9a0f-1191499509f1"); - - public static final UUID COLUMN_3_32_ID = UUID.fromString("b3f259f6-700a-4b60-8eac-dceaa0dcda9d"); - - public static final UUID COLUMN_3_33_ID = UUID.fromString("9160af06-e168-4b10-a7f9-520f41ae7955"); - - public static final UUID COLUMN_3_34_ID = UUID.fromString("fde20c99-ed9c-4a60-8c18-f46e8603ebb5"); - - public static final UUID COLUMN_3_35_ID = UUID.fromString("071c7f27-1cdd-4af9-b4d6-f932c27c7287"); - - public static final ColumnBriefDto TABLE_3_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final static UUID COLUMN_3_1_ID = UUID.fromString("49cc2735-ba75-4e12-8ac7-8aec87ed7724"); + public final static UUID COLUMN_3_2_ID = UUID.fromString("2c240d64-3052-4a74-b696-e7490fdff3ea"); + public final static UUID COLUMN_3_3_ID = UUID.fromString("6fbb0a56-f23a-4aa4-b158-c614a0a30f86"); + public final static UUID COLUMN_3_4_ID = UUID.fromString("9b01f925-93ee-4f28-bf31-9902900a7099"); + public final static UUID COLUMN_3_5_ID = UUID.fromString("9bbd66f1-0d94-401c-b7f7-6e329bb9ee21"); + public final static UUID COLUMN_3_6_ID = UUID.fromString("19ad93d7-b298-495b-9678-9aac80678ff9"); + public final static UUID COLUMN_3_7_ID = UUID.fromString("4d27d9f4-645f-4222-b5a8-4a91fa6e4275"); + public final static UUID COLUMN_3_8_ID = UUID.fromString("b4f8fcf8-5824-45ec-8c58-43f20e6dffc5"); + public final static UUID COLUMN_3_9_ID = UUID.fromString("87247218-369e-484a-9a8f-d758478d8dfc"); + public final static UUID COLUMN_3_10_ID = UUID.fromString("6e191b97-189a-4d88-901e-888ca889e280"); + public final static UUID COLUMN_3_11_ID = UUID.fromString("6ac356ff-9be5-4259-9b62-83b6707be7fe"); + public final static UUID COLUMN_3_12_ID = UUID.fromString("0665b384-c824-4358-b6c5-f17706d46ea4"); + public final static UUID COLUMN_3_13_ID = UUID.fromString("22d3676e-d28e-4075-b223-91a7ac767bcf"); + public final static UUID COLUMN_3_14_ID = UUID.fromString("673326e3-ee2b-4c2f-902f-982e2abce1c2"); + public final static UUID COLUMN_3_15_ID = UUID.fromString("8dcacf4a-736b-4e67-9618-74998cba8940"); + public final static UUID COLUMN_3_16_ID = UUID.fromString("2b2f5359-76d3-4763-a53f-d18ca6b793fb"); + public final static UUID COLUMN_3_17_ID = UUID.fromString("674b6120-06cf-4624-b006-1ed48898bd69"); + public final static UUID COLUMN_3_18_ID = UUID.fromString("13edd7c9-6c88-44d7-b206-34774e49c5af"); + public final static UUID COLUMN_3_19_ID = UUID.fromString("6977bb3f-4ae2-43ea-bb82-c7f68454c538"); + public final static UUID COLUMN_3_20_ID = UUID.fromString("c03d2429-53e1-42eb-a1f5-ce342fa23336"); + public final static UUID COLUMN_3_21_ID = UUID.fromString("06edd332-750e-4aa1-b61b-e757fb2312c3"); + public final static UUID COLUMN_3_22_ID = UUID.fromString("b6b8631d-f283-49da-8d5e-4bb24def2a40"); + public final static UUID COLUMN_3_23_ID = UUID.fromString("0393ee00-31ba-44ab-9e82-1f5034a9f57b"); + public final static UUID COLUMN_3_24_ID = UUID.fromString("a63784ea-f70d-4bda-ace6-1c6a88edf831"); + public final static UUID COLUMN_3_25_ID = UUID.fromString("720fe829-802c-420b-8e41-bdbb636db43c"); + public final static UUID COLUMN_3_26_ID = UUID.fromString("5bce38ef-7d49-43b5-9054-068750684b5f"); + public final static UUID COLUMN_3_27_ID = UUID.fromString("92097c02-3dd3-40ea-bd03-a9135f45a557"); + public final static UUID COLUMN_3_28_ID = UUID.fromString("7361a38a-828b-495e-8a57-b36cca17d7db"); + public final static UUID COLUMN_3_29_ID = UUID.fromString("a06812db-03b7-484c-92a6-45d94eef3bb9"); + public final static UUID COLUMN_3_30_ID = UUID.fromString("05614d89-9216-47ea-96f0-acffc4674acf"); + public final static UUID COLUMN_3_31_ID = UUID.fromString("05ada13d-361a-48e7-9a0f-1191499509f1"); + public final static UUID COLUMN_3_32_ID = UUID.fromString("b3f259f6-700a-4b60-8eac-dceaa0dcda9d"); + public final static UUID COLUMN_3_33_ID = UUID.fromString("9160af06-e168-4b10-a7f9-520f41ae7955"); + public final static UUID COLUMN_3_34_ID = UUID.fromString("fde20c99-ed9c-4a60-8c18-f46e8603ebb5"); + public final static UUID COLUMN_3_35_ID = UUID.fromString("071c7f27-1cdd-4af9-b4d6-f932c27c7287"); + + public final ColumnBriefDto TABLE_3_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_3_1_ID) .columnType(ColumnTypeDto.BIGINT) .name("id") .internalName("id") .build(); - public static final List<TableColumn> TABLE_3_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_3_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_3_1_ID) .table(TABLE_3) .ordinalPosition(0) @@ -3678,7 +3658,7 @@ public abstract class BaseTest { .sets(new LinkedList<>()) .build()); - public static final List<ColumnDto> TABLE_3_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_3_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_3_1_ID) .tableId(TABLE_3_ID) .databaseId(DATABASE_1_ID) @@ -4064,56 +4044,36 @@ public abstract class BaseTest { .sets(new LinkedList<>()) .build()); - public static final UUID COLUMN_5_1_ID = UUID.fromString("4efd4cbb-ca2e-48e2-8f40-37514956aa67"); - - public static final UUID COLUMN_5_2_ID = UUID.fromString("53061685-c1db-4df6-ad4e-8f384a200104"); - - public static final UUID COLUMN_5_3_ID = UUID.fromString("643f9cda-8db1-47a4-bb08-c10e78e54c10"); - - public static final UUID COLUMN_5_4_ID = UUID.fromString("efeacc15-3b31-4a9f-9dba-f07d62dcddd6"); - - public static final UUID COLUMN_5_5_ID = UUID.fromString("0319db31-473a-47bc-bb9d-fa1edf82fcd5"); - - public static final UUID COLUMN_5_6_ID = UUID.fromString("9ba789ca-59cf-4480-b9f6-3b957b1d7f5c"); - - public static final UUID COLUMN_5_7_ID = UUID.fromString("81c42954-fd1a-4fef-adb1-bc4945469e26"); - - public static final UUID COLUMN_5_8_ID = UUID.fromString("49a38905-52a2-4a9b-b7b9-5e1dcf799b2a"); - - public static final UUID COLUMN_5_9_ID = UUID.fromString("1e1a9b6b-5aee-4773-b52d-ea56a5d1e2c8"); - - public static final UUID COLUMN_5_10_ID = UUID.fromString("42ede62a-ae98-4a14-ba54-76b8ba1c580f"); - - public static final UUID COLUMN_5_11_ID = UUID.fromString("0af0f84a-5a58-418a-8bbc-bde29ed0cda0"); - - public static final UUID COLUMN_5_12_ID = UUID.fromString("d9cb30a2-1566-4bd1-899d-060a8ba47722"); - - public static final UUID COLUMN_5_13_ID = UUID.fromString("e69f7f75-3731-4706-8193-0393aa0c08a7"); - - public static final UUID COLUMN_5_14_ID = UUID.fromString("4441630e-7dfa-4046-8bc2-929860f1c66e"); - - public static final UUID COLUMN_5_15_ID = UUID.fromString("f0a12be0-0b26-4686-bf7e-539cdc7e71b4"); - - public static final UUID COLUMN_5_16_ID = UUID.fromString("b60abdcc-5786-40f8-a309-e4467f7d963c"); - - public static final UUID COLUMN_5_17_ID = UUID.fromString("6d5877e2-daef-43d6-a1b6-1aff3ab1a9a2"); - - public static final UUID COLUMN_5_18_ID = UUID.fromString("bb45455f-d449-496e-94f8-eac4d46ba9c0"); - - public static final UUID COLUMN_5_19_ID = UUID.fromString("44c5484b-b57d-48a4-8f24-d2074de98e1a"); - - public static final UUID COLUMN_5_20_ID = UUID.fromString("6475b937-71fc-4331-bc85-8ee71fa68d99"); - - public static final UUID COLUMN_5_21_ID = UUID.fromString("92ff472f-e203-4c8e-b243-81640229ca19"); - - public static final ColumnBriefDto TABLE_5_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final static UUID COLUMN_5_1_ID = UUID.fromString("4efd4cbb-ca2e-48e2-8f40-37514956aa67"); + public final static UUID COLUMN_5_2_ID = UUID.fromString("53061685-c1db-4df6-ad4e-8f384a200104"); + public final static UUID COLUMN_5_3_ID = UUID.fromString("643f9cda-8db1-47a4-bb08-c10e78e54c10"); + public final static UUID COLUMN_5_4_ID = UUID.fromString("efeacc15-3b31-4a9f-9dba-f07d62dcddd6"); + public final static UUID COLUMN_5_5_ID = UUID.fromString("0319db31-473a-47bc-bb9d-fa1edf82fcd5"); + public final static UUID COLUMN_5_6_ID = UUID.fromString("9ba789ca-59cf-4480-b9f6-3b957b1d7f5c"); + public final static UUID COLUMN_5_7_ID = UUID.fromString("81c42954-fd1a-4fef-adb1-bc4945469e26"); + public final static UUID COLUMN_5_8_ID = UUID.fromString("49a38905-52a2-4a9b-b7b9-5e1dcf799b2a"); + public final static UUID COLUMN_5_9_ID = UUID.fromString("1e1a9b6b-5aee-4773-b52d-ea56a5d1e2c8"); + public final static UUID COLUMN_5_10_ID = UUID.fromString("42ede62a-ae98-4a14-ba54-76b8ba1c580f"); + public final static UUID COLUMN_5_11_ID = UUID.fromString("0af0f84a-5a58-418a-8bbc-bde29ed0cda0"); + public final static UUID COLUMN_5_12_ID = UUID.fromString("d9cb30a2-1566-4bd1-899d-060a8ba47722"); + public final static UUID COLUMN_5_13_ID = UUID.fromString("e69f7f75-3731-4706-8193-0393aa0c08a7"); + public final static UUID COLUMN_5_14_ID = UUID.fromString("4441630e-7dfa-4046-8bc2-929860f1c66e"); + public final static UUID COLUMN_5_15_ID = UUID.fromString("f0a12be0-0b26-4686-bf7e-539cdc7e71b4"); + public final static UUID COLUMN_5_16_ID = UUID.fromString("b60abdcc-5786-40f8-a309-e4467f7d963c"); + public final static UUID COLUMN_5_17_ID = UUID.fromString("6d5877e2-daef-43d6-a1b6-1aff3ab1a9a2"); + public final static UUID COLUMN_5_18_ID = UUID.fromString("bb45455f-d449-496e-94f8-eac4d46ba9c0"); + public final static UUID COLUMN_5_19_ID = UUID.fromString("44c5484b-b57d-48a4-8f24-d2074de98e1a"); + public final static UUID COLUMN_5_20_ID = UUID.fromString("6475b937-71fc-4331-bc85-8ee71fa68d99"); + public final static UUID COLUMN_5_21_ID = UUID.fromString("92ff472f-e203-4c8e-b243-81640229ca19"); + + public final ColumnBriefDto TABLE_5_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_5_1_ID) .name("id") .internalName("id") .columnType(ColumnTypeDto.BIGINT) .build(); - public static final List<TableColumn> TABLE_5_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_5_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_5_1_ID) .ordinalPosition(0) .table(TABLE_5) @@ -4302,8 +4262,7 @@ public abstract class BaseTest { .columnType(TableColumnType.DECIMAL) .isNullAllowed(true) .build()); - - public static final List<ColumnDto> TABLE_5_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_5_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_5_1_ID) .ordinalPosition(0) .tableId(TABLE_5_ID) @@ -4493,17 +4452,17 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final List<CreateForeignKeyDto> TABLE_5_FOREIGN_KEYS_INVALID_CREATE = List.of(CreateForeignKeyDto.builder() + public final List<CreateForeignKeyDto> TABLE_5_FOREIGN_KEYS_INVALID_CREATE = List.of(CreateForeignKeyDto.builder() .columns(new LinkedList<>(List.of("somecolumn"))) .referencedTable("sometable") .referencedColumns(new LinkedList<>(List.of("someothercolumn"))) .build()); - public static final CreateTableConstraintsDto TABLE_5_CONSTRAINTS_INVALID_CREATE = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_5_CONSTRAINTS_INVALID_CREATE = CreateTableConstraintsDto.builder() .foreignKeys(TABLE_5_FOREIGN_KEYS_INVALID_CREATE) .build(); - public static final List<CreateTableColumnDto> TABLE_5_COLUMNS_CREATE = List.of(CreateTableColumnDto.builder() + public final List<CreateTableColumnDto> TABLE_5_COLUMNS_CREATE = List.of(CreateTableColumnDto.builder() .name("id") .type(ColumnTypeDto.BIGINT) .nullAllowed(false) @@ -4609,36 +4568,36 @@ public abstract class BaseTest { .nullAllowed(true) .build()); - public static final CreateTableConstraintsDto TABLE_5_CREATE_CONSTRAINTS_DTO = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_5_CREATE_CONSTRAINTS_DTO = CreateTableConstraintsDto.builder() .primaryKey(Set.of("id")) .uniques(new LinkedList<>(List.of(List.of("id")))) .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .build(); - public static final CreateTableDto TABLE_5_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_5_CREATE_DTO = CreateTableDto.builder() .name(TABLE_5_NAME) .description(TABLE_5_DESCRIPTION) .columns(TABLE_5_COLUMNS_CREATE) .constraints(TABLE_5_CREATE_CONSTRAINTS_DTO) .build(); - public static final CreateTableDto TABLE_5_INVALID_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_5_INVALID_CREATE_DTO = CreateTableDto.builder() .name(TABLE_5_NAME) .description(TABLE_5_DESCRIPTION) .columns(TABLE_5_COLUMNS_CREATE) .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 final static UUID QUERY_8_ID = UUID.fromString("1c466eee-d551-4ef9-a7e0-b5a2d1b15473"); + public final static String QUERY_8_STATEMENT = "SELECT `id`, `animal_name` FROM `zoo` WHERE `hair` = TRUE AND `feathers` = false;"; + public final static String QUERY_8_QUERY_HASH = "f0ee0d6dd45e092fca120c4f0eab089f91ed26ccf8dc34a03c6b9c6bb4141271"; + public final static Long QUERY_8_RESULT_NUMBER = 5L; + public final static String QUERY_8_RESULT_HASH = "b5f9cae916d32deff81c5f2e9f8ff43904034bc084b12320730953d120698bed"; + public final static Instant QUERY_8_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Boolean QUERY_8_PERSISTED = true; - public static final SubsetDto QUERY_8_SUBSET_DTO = SubsetDto.builder() + public 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() @@ -4658,19 +4617,14 @@ public abstract class BaseTest { .build()))) .build(); - public static final UUID COLUMN_6_1_ID = UUID.fromString("27b04a64-2849-4fae-b295-858c3e50361f"); + public final static UUID COLUMN_6_1_ID = UUID.fromString("27b04a64-2849-4fae-b295-858c3e50361f"); + public final static UUID COLUMN_6_2_ID = UUID.fromString("1ea62e32-5719-4152-94da-45d37eb88b6f"); + public final static UUID COLUMN_6_3_ID = UUID.fromString("f523f9f5-42f7-4695-841e-a5fd30fa6879"); + public final static UUID COLUMN_6_4_ID = UUID.fromString("f57ea880-f917-4127-bcbb-202a34831383"); + public final static UUID COLUMN_6_5_ID = UUID.fromString("38aaeb63-b94b-4d90-8eae-a626dfb1f092"); + public final static UUID COLUMN_6_6_ID = UUID.fromString("f788cf6f-66ed-4f28-8b24-d9d173c4d340"); - public static final UUID COLUMN_6_2_ID = UUID.fromString("1ea62e32-5719-4152-94da-45d37eb88b6f"); - - public static final UUID COLUMN_6_3_ID = UUID.fromString("f523f9f5-42f7-4695-841e-a5fd30fa6879"); - - public static final UUID COLUMN_6_4_ID = UUID.fromString("f57ea880-f917-4127-bcbb-202a34831383"); - - public static final UUID COLUMN_6_5_ID = UUID.fromString("38aaeb63-b94b-4d90-8eae-a626dfb1f092"); - - public static final UUID COLUMN_6_6_ID = UUID.fromString("f788cf6f-66ed-4f28-8b24-d9d173c4d340"); - - public static final List<TableColumn> TABLE_6_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_6_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_6_1_ID) .ordinalPosition(0) .table(TABLE_6) @@ -4725,14 +4679,14 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final ColumnBriefDto TABLE_6_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final ColumnBriefDto TABLE_6_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_6_1_ID) .name("id") .internalName("id") .columnType(ColumnTypeDto.BIGINT) .build(); - public static final List<ColumnDto> TABLE_6_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_6_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_6_1_ID) .ordinalPosition(0) .tableId(TABLE_6_ID) @@ -4787,25 +4741,23 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final List<List<String>> TABLE_6_UNIQUES_CREATE = List.of( + public final List<List<String>> TABLE_6_UNIQUES_CREATE = List.of( List.of("firstname", "lastname")); - public static final List<CreateForeignKeyDto> TABLE_6_FOREIGN_KEYS_CREATE = List.of(CreateForeignKeyDto.builder() + public final List<CreateForeignKeyDto> TABLE_6_FOREIGN_KEYS_CREATE = List.of(CreateForeignKeyDto.builder() .columns(new LinkedList<>(List.of("ref_id"))) .referencedTable("zoo") .referencedColumns(new LinkedList<>(List.of("id"))) .build()); - public static final Set<String> TABLE_6_CHECKS_CREATE = Set.of("firstname != lastname"); - - public static final CreateTableConstraintsDto TABLE_6_CONSTRAINTS_CREATE = CreateTableConstraintsDto.builder() + public final CreateTableConstraintsDto TABLE_6_CONSTRAINTS_CREATE = CreateTableConstraintsDto.builder() .uniques(TABLE_6_UNIQUES_CREATE) .foreignKeys(TABLE_6_FOREIGN_KEYS_CREATE) - .checks(TABLE_6_CHECKS_CREATE) + .checks(Set.of("firstname != lastname")) .primaryKey(Set.of("id")) .build(); - public static final List<CreateTableColumnDto> TABLE_6_COLUMNS_CREATE = List.of( + public final List<CreateTableColumnDto> TABLE_6_COLUMNS_CREATE = List.of( CreateTableColumnDto.builder() .name("name_id") .type(ColumnTypeDto.BIGINT) @@ -4818,32 +4770,31 @@ public abstract class BaseTest { .nullAllowed(false) .build()); - public static final CreateTableDto TABLE_6_CREATE_DTO = CreateTableDto.builder() + public final CreateTableDto TABLE_6_CREATE_DTO = CreateTableDto.builder() .name(TABLE_6_NAME) .description(TABLE_6_DESCRIPTION) .columns(TABLE_6_COLUMNS_CREATE) .constraints(TABLE_6_CONSTRAINTS_CREATE) .build(); - public static final UUID COLUMN_7_1_ID = UUID.fromString("395b44a4-0e31-41ea-94ad-c4f2d5e912c6"); - - public static final UUID COLUMN_7_2_ID = UUID.fromString("5713333b-872a-44c5-ab94-4d0ab62f5663"); + public final static UUID COLUMN_7_1_ID = UUID.fromString("395b44a4-0e31-41ea-94ad-c4f2d5e912c6"); + public final static UUID COLUMN_7_2_ID = UUID.fromString("5713333b-872a-44c5-ab94-4d0ab62f5663"); - public static final ColumnBriefDto TABLE_7_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() + public final ColumnBriefDto TABLE_7_COLUMNS_BRIEF_0_DTO = ColumnBriefDto.builder() .id(COLUMN_7_1_ID) .name("name_id") .internalName("name_id") .columnType(ColumnTypeDto.BIGINT) .build(); - public static final ColumnBriefDto TABLE_7_COLUMNS_BRIEF_1_DTO = ColumnBriefDto.builder() + public final ColumnBriefDto TABLE_7_COLUMNS_BRIEF_1_DTO = ColumnBriefDto.builder() .id(COLUMN_7_2_ID) .name("zoo_id") .internalName("zoo_id") .columnType(ColumnTypeDto.BIGINT) .build(); - public static final List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() + public final List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_7_1_ID) .ordinalPosition(0) .table(TABLE_7) @@ -4862,7 +4813,7 @@ public abstract class BaseTest { .isNullAllowed(false) .build()); - public static final List<ColumnDto> TABLE_7_COLUMNS_DTO = List.of(ColumnDto.builder() + public final List<ColumnDto> TABLE_7_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_7_1_ID) .ordinalPosition(0) .tableId(TABLE_7_ID) @@ -4881,27 +4832,24 @@ public abstract class BaseTest { .isNullAllowed(false) .build()); - public static final UUID VIEW_1_ID = UUID.fromString("7d712cf7-78c7-4a47-90b0-d6b9f7f19b70"); - public static final Boolean VIEW_1_INITIAL_VIEW = false; - public static final String VIEW_1_NAME = "JUnit"; - 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_HASH = "dc81a6877c7c51a6a6f406e1fc2a255e44a0d49a20548596e0d583c3eb849c23"; - - public static final UUID VIEW_COLUMN_1_1_ID = UUID.fromString("ebf2c5ce-4deb-4cc6-b6f6-61f5d3f6fc98"); - - public static final UUID VIEW_COLUMN_1_2_ID = UUID.fromString("d6ba3475-cefa-4771-aaa1-9274f16335ee"); - - 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() + public final static UUID VIEW_1_ID = UUID.fromString("7d712cf7-78c7-4a47-90b0-d6b9f7f19b70"); + public final static Boolean VIEW_1_INITIAL_VIEW = false; + public final static String VIEW_1_NAME = "JUnit"; + public final static String VIEW_1_INTERNAL_NAME = "junit"; + public final static Boolean VIEW_1_PUBLIC = false; + public final static Boolean VIEW_1_SCHEMA_PUBLIC = false; + public final static String VIEW_1_QUERY = "SELECT `location`, `lat`, `lng` FROM `weather_location`"; + public final static String VIEW_1_QUERY_HASH = "dc81a6877c7c51a6a6f406e1fc2a255e44a0d49a20548596e0d583c3eb849c23"; + public final static UUID VIEW_COLUMN_1_1_ID = UUID.fromString("ebf2c5ce-4deb-4cc6-b6f6-61f5d3f6fc98"); + public final static UUID VIEW_COLUMN_1_2_ID = UUID.fromString("d6ba3475-cefa-4771-aaa1-9274f16335ee"); + public final static UUID VIEW_COLUMN_1_3_ID = UUID.fromString("4f189a5f-c9ca-4518-9758-1a0730f6276b"); + + public 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( + public final List<ViewColumnDto> VIEW_1_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(VIEW_COLUMN_1_1_ID) .ordinalPosition(0) @@ -4933,10 +4881,9 @@ public abstract class BaseTest { .size(10L) .d(0L) .isNullAllowed(true) - .build() - ); + .build()); - public static final View VIEW_1 = View.builder() + public final View VIEW_1 = View.builder() .id(VIEW_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) @@ -4952,8 +4899,8 @@ public abstract class BaseTest { .database(null) /* DATABASE_1 */ .build(); - public static final Long VIEW_1_DATA_COUNT = 3L; - public static final List<Map<String, Object>> VIEW_1_DATA_DTO = new LinkedList<>(List.of( + public final static Long VIEW_1_DATA_COUNT = 3L; + public final List<Map<String, Object>> VIEW_1_DATA_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put("location", "Albury"); put("lat", -36.0653583); @@ -4971,7 +4918,7 @@ public abstract class BaseTest { }} )); - public static final List<ViewColumn> VIEW_1_COLUMNS = List.of( + public final List<ViewColumn> VIEW_1_COLUMNS = List.of( ViewColumn.builder() .id(VIEW_COLUMN_1_1_ID) .ordinalPosition(0) @@ -5003,10 +4950,9 @@ public abstract class BaseTest { .d(0L) .isNullAllowed(true) .view(VIEW_1) - .build() - ); + .build()); - public static final ViewDto VIEW_1_DTO = ViewDto.builder() + public final ViewDto VIEW_1_DTO = ViewDto.builder() .id(VIEW_1_ID) .databaseId(DATABASE_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) @@ -5021,7 +4967,7 @@ public abstract class BaseTest { .columns(VIEW_1_COLUMNS_DTO) .build(); - public static final ViewBriefDto VIEW_1_BRIEF_DTO = ViewBriefDto.builder() + public final ViewBriefDto VIEW_1_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) @@ -5034,30 +4980,26 @@ public abstract class BaseTest { .queryHash(VIEW_1_QUERY_HASH) .build(); - public static final CreateViewDto VIEW_1_CREATE_DTO = CreateViewDto.builder() + public final CreateViewDto VIEW_1_CREATE_DTO = CreateViewDto.builder() .isPublic(VIEW_1_PUBLIC) .name(VIEW_1_NAME) .query(VIEW_1_SUBSET_DTO) .build(); - public static final UUID VIEW_2_ID = UUID.fromString("1921a0a0-e4b0-4d12-a05f-be920af9b5ce"); - public static final Boolean VIEW_2_INITIAL_VIEW = false; - public static final String VIEW_2_NAME = "JUnit2"; - public static final String VIEW_2_INTERNAL_NAME = "junit2"; - public static final Boolean VIEW_2_PUBLIC = true; - public static final Boolean VIEW_2_SCHEMA_PUBLIC = true; - public static final String VIEW_2_QUERY = "select `date`, `location` as loc, `mintemp`, `rainfall` from `weather_aus` where `location` = 'Albury'"; - public static final String VIEW_2_QUERY_HASH = "987fc946772ffb6d85060262dcb5df419692a1f6772ea995e3dedb53c191e984"; - - public static final UUID VIEW_COLUMN_2_1_ID = UUID.fromString("8fb30bce-04a8-4e9a-9c6b-0776eda3aab8"); - - public static final UUID VIEW_COLUMN_2_2_ID = UUID.fromString("d43f9940-ae27-4d81-b17b-ccbaf578186c"); - - public static final UUID VIEW_COLUMN_2_3_ID = UUID.fromString("b47733bb-aeea-414d-811e-405c64463730"); - - public static final UUID VIEW_COLUMN_2_4_ID = UUID.fromString("2b467e3a-acef-4944-be19-b4b0680874c2"); - - public static final List<ViewColumnDto> VIEW_2_COLUMNS_DTO = List.of( + public final static UUID VIEW_2_ID = UUID.fromString("1921a0a0-e4b0-4d12-a05f-be920af9b5ce"); + public final static Boolean VIEW_2_INITIAL_VIEW = false; + public final static String VIEW_2_NAME = "JUnit2"; + public final static String VIEW_2_INTERNAL_NAME = "junit2"; + public final static Boolean VIEW_2_PUBLIC = true; + public final static Boolean VIEW_2_SCHEMA_PUBLIC = true; + public final static String VIEW_2_QUERY = "select `date`, `location` as loc, `mintemp`, `rainfall` from `weather_aus` where `location` = 'Albury'"; + public final static String VIEW_2_QUERY_HASH = "987fc946772ffb6d85060262dcb5df419692a1f6772ea995e3dedb53c191e984"; + public final static UUID VIEW_COLUMN_2_1_ID = UUID.fromString("8fb30bce-04a8-4e9a-9c6b-0776eda3aab8"); + public final static UUID VIEW_COLUMN_2_2_ID = UUID.fromString("d43f9940-ae27-4d81-b17b-ccbaf578186c"); + public final static UUID VIEW_COLUMN_2_3_ID = UUID.fromString("b47733bb-aeea-414d-811e-405c64463730"); + public final static UUID VIEW_COLUMN_2_4_ID = UUID.fromString("2b467e3a-acef-4944-be19-b4b0680874c2"); + + public final List<ViewColumnDto> VIEW_2_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(VIEW_COLUMN_2_1_ID) .databaseId(DATABASE_1_ID) @@ -5098,10 +5040,9 @@ public abstract class BaseTest { .size(10L) .d(0L) .isNullAllowed(true) - .build() - ); + .build()); - public static final View VIEW_2 = View.builder() + public final View VIEW_2 = View.builder() .id(VIEW_2_ID) .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) @@ -5116,7 +5057,7 @@ public abstract class BaseTest { .database(null) /* DATABASE_1 */ .build(); - public static final List<ViewColumn> VIEW_2_COLUMNS = List.of( + public final List<ViewColumn> VIEW_2_COLUMNS = List.of( ViewColumn.builder() .id(VIEW_COLUMN_2_1_ID) .ordinalPosition(0) @@ -5157,10 +5098,9 @@ public abstract class BaseTest { .d(0L) .isNullAllowed(true) .view(VIEW_2) - .build() - ); + .build()); - public static final ViewDto VIEW_2_DTO = ViewDto.builder() + public final ViewDto VIEW_2_DTO = ViewDto.builder() .id(VIEW_2_ID) .databaseId(DATABASE_1_ID) .isInitialView(VIEW_2_INITIAL_VIEW) @@ -5174,7 +5114,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final ViewBriefDto VIEW_2_BRIEF_DTO = ViewBriefDto.builder() + public final ViewBriefDto VIEW_2_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_2_ID) .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) @@ -5187,26 +5127,21 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final UUID VIEW_3_ID = UUID.fromString("88940939-d456-4aae-88a6-f2b6b343c614"); - public static final Boolean VIEW_3_INITIAL_VIEW = false; - public static final String VIEW_3_NAME = "JUnit3"; - public static final String VIEW_3_INTERNAL_NAME = "junit3"; - public static final Boolean VIEW_3_PUBLIC = true; - public static final Boolean VIEW_3_SCHEMA_PUBLIC = false; - public static final String VIEW_3_QUERY = "select w.`mintemp`, w.`rainfall`, w.`location`, m.`date` from `weather_aus` w join `junit2` m on m.`location` = w.`location` and m.`date` = w.`date`"; - public static final String VIEW_3_QUERY_HASH = "bbbaa56a5206b3dc3e6cf9301b0db9344eb6f19b100c7b88550ffb597a0bd255"; - - public static final Long VIEW_3_DATA_COUNT = 3L; - - public static final UUID VIEW_COLUMN_3_1_ID = UUID.fromString("129839cb-dbd7-492d-8fd0-ee44a8f51c4d"); - - public static final UUID VIEW_COLUMN_3_2_ID = UUID.fromString("e229d80a-c25c-4fbe-8f31-bbb2e1dff3d5"); - - public static final UUID VIEW_COLUMN_3_3_ID = UUID.fromString("12083a5d-fdd3-41db-9f92-d1298558e477"); - - public static final UUID VIEW_COLUMN_3_4_ID = UUID.fromString("668f8a87-1fa6-4be7-9761-1844aa8315a4"); - - public static final List<ViewColumnDto> VIEW_3_COLUMNS_DTO = List.of( + public final static UUID VIEW_3_ID = UUID.fromString("88940939-d456-4aae-88a6-f2b6b343c614"); + public final static Boolean VIEW_3_INITIAL_VIEW = false; + public final static String VIEW_3_NAME = "JUnit3"; + public final static String VIEW_3_INTERNAL_NAME = "junit3"; + public final static Boolean VIEW_3_PUBLIC = true; + public final static Boolean VIEW_3_SCHEMA_PUBLIC = false; + public final static String VIEW_3_QUERY = "select w.`mintemp`, w.`rainfall`, w.`location`, m.`date` from `weather_aus` w join `junit2` m on m.`location` = w.`location` and m.`date` = w.`date`"; + public final static String VIEW_3_QUERY_HASH = "bbbaa56a5206b3dc3e6cf9301b0db9344eb6f19b100c7b88550ffb597a0bd255"; + public final static Long VIEW_3_DATA_COUNT = 3L; + public final static UUID VIEW_COLUMN_3_1_ID = UUID.fromString("129839cb-dbd7-492d-8fd0-ee44a8f51c4d"); + public final static UUID VIEW_COLUMN_3_2_ID = UUID.fromString("e229d80a-c25c-4fbe-8f31-bbb2e1dff3d5"); + public final static UUID VIEW_COLUMN_3_3_ID = UUID.fromString("12083a5d-fdd3-41db-9f92-d1298558e477"); + public final static UUID VIEW_COLUMN_3_4_ID = UUID.fromString("668f8a87-1fa6-4be7-9761-1844aa8315a4"); + + public final List<ViewColumnDto> VIEW_3_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(VIEW_COLUMN_3_1_ID) .databaseId(DATABASE_1_ID) @@ -5247,10 +5182,9 @@ public abstract class BaseTest { .internalName("date") .columnType(ColumnTypeDto.DATE) .isNullAllowed(true) - .build() - ); + .build()); - public static final View VIEW_3 = View.builder() + public final View VIEW_3 = View.builder() .id(VIEW_3_ID) .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) @@ -5265,7 +5199,7 @@ public abstract class BaseTest { .database(null) /* DATABASE_1 */ .build(); - public static final List<ViewColumn> VIEW_3_COLUMNS = List.of( + public final List<ViewColumn> VIEW_3_COLUMNS = List.of( ViewColumn.builder() .id(VIEW_COLUMN_3_1_ID) .ordinalPosition(0) @@ -5306,10 +5240,9 @@ public abstract class BaseTest { .columnType(TableColumnType.DATE) .isNullAllowed(true) .view(VIEW_3) - .build() - ); + .build()); - public static final ViewDto VIEW_3_DTO = ViewDto.builder() + public final ViewDto VIEW_3_DTO = ViewDto.builder() .id(VIEW_3_ID) .databaseId(DATABASE_1_ID) .isInitialView(VIEW_3_INITIAL_VIEW) @@ -5323,7 +5256,7 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final ViewBriefDto VIEW_3_BRIEF_DTO = ViewBriefDto.builder() + public final ViewBriefDto VIEW_3_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_3_ID) .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) @@ -5336,17 +5269,16 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final UUID VIEW_4_ID = UUID.fromString("13b36fa0-a65a-4ccf-80b1-5b3a2444a41a"); - public static final Boolean VIEW_4_INITIAL_VIEW = false; - public static final String VIEW_4_NAME = "Mock View"; - public static final String VIEW_4_INTERNAL_NAME = "mock_view"; - public static final Table VIEW_4_TABLE = TABLE_5; - public static final Boolean VIEW_4_PUBLIC = true; - public static final Boolean VIEW_4_SCHEMA_PUBLIC = false; - public static final String VIEW_4_QUERY = "SELECT `animal_name`, `hair`, `feathers`, `eggs`, `milk`, `airborne`, `aquatic`, `predator`, `backbone`, `breathes`, `venomous`, `fins`, `legs`, `tail`, `domestic`, `catsize`, `class_type` FROM `zoo` WHERE `class_type` = 1"; - public static final String VIEW_4_QUERY_HASH = "3561cd0bb0b0e94d6f15ae602134252a5760d09d660a71a4fb015b6991c8ba0b"; - - public static final List<ViewColumnDto> VIEW_4_COLUMNS_DTO = List.of( + public final static UUID VIEW_4_ID = UUID.fromString("13b36fa0-a65a-4ccf-80b1-5b3a2444a41a"); + public final static Boolean VIEW_4_INITIAL_VIEW = false; + public final static String VIEW_4_NAME = "Mock View"; + public final static String VIEW_4_INTERNAL_NAME = "mock_view"; + public final Table VIEW_4_TABLE = TABLE_5; + public final static Boolean VIEW_4_PUBLIC = true; + public final static Boolean VIEW_4_SCHEMA_PUBLIC = false; + public final static String VIEW_4_QUERY = "SELECT `animal_name`, `hair`, `feathers`, `eggs`, `milk`, `airborne`, `aquatic`, `predator`, `backbone`, `breathes`, `venomous`, `fins`, `legs`, `tail`, `domestic`, `catsize`, `class_type` FROM `zoo` WHERE `class_type` = 1"; + public final static String VIEW_4_QUERY_HASH = "3561cd0bb0b0e94d6f15ae602134252a5760d09d660a71a4fb015b6991c8ba0b"; + public final List<ViewColumnDto> VIEW_4_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(COLUMN_5_1_ID) .databaseId(DATABASE_2_ID) @@ -5501,7 +5433,7 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final View VIEW_4 = View.builder() + public final View VIEW_4 = View.builder() .id(VIEW_4_ID) .isInitialView(VIEW_4_INITIAL_VIEW) .name(VIEW_4_NAME) @@ -5515,7 +5447,7 @@ public abstract class BaseTest { .columns(null) /* VIEW_4_COLUMNS */ .build(); - public static final ViewDto VIEW_4_DTO = ViewDto.builder() + public final ViewDto VIEW_4_DTO = ViewDto.builder() .id(VIEW_4_ID) .databaseId(DATABASE_2_ID) .isInitialView(VIEW_4_INITIAL_VIEW) @@ -5529,7 +5461,7 @@ public abstract class BaseTest { .columns(VIEW_4_COLUMNS_DTO) .build(); - public static final ViewBriefDto VIEW_4_BRIEF_DTO = ViewBriefDto.builder() + public final ViewBriefDto VIEW_4_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_4_ID) .isInitialView(VIEW_4_INITIAL_VIEW) .name(VIEW_4_NAME) @@ -5542,7 +5474,7 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final List<ViewColumn> VIEW_4_COLUMNS = List.of( + public final List<ViewColumn> VIEW_4_COLUMNS = List.of( ViewColumn.builder() .id(COLUMN_5_1_ID) .ordinalPosition(0) @@ -5697,16 +5629,16 @@ public abstract class BaseTest { .view(VIEW_4) .build()); - public static final UUID VIEW_5_ID = UUID.fromString("bc6b8507-51f1-4d05-bb0c-1f619a991dec"); - public static final Boolean VIEW_5_INITIAL_VIEW = false; - public static final String VIEW_5_NAME = "Mock View"; - public static final String VIEW_5_INTERNAL_NAME = "mock_view"; - public static final Boolean VIEW_5_PUBLIC = true; - public static final Boolean VIEW_5_SCHEMA_PUBLIC = true; - public static final String VIEW_5_QUERY = "SELECT `location`, `lat`, `lng` FROM `weather_location` WHERE `location` = 'Albury'"; - public static final String VIEW_5_QUERY_HASH = "120f32478aaff874c25ab32eceb9f00b64cc9d422831046f2f5d43953aca01e7"; + public final static UUID VIEW_5_ID = UUID.fromString("bc6b8507-51f1-4d05-bb0c-1f619a991dec"); + public final static Boolean VIEW_5_INITIAL_VIEW = false; + public final static String VIEW_5_NAME = "Mock View"; + public final static String VIEW_5_INTERNAL_NAME = "mock_view"; + public final static Boolean VIEW_5_PUBLIC = true; + public final static Boolean VIEW_5_SCHEMA_PUBLIC = true; + public final static String VIEW_5_QUERY = "SELECT `location`, `lat`, `lng` FROM `weather_location` WHERE `location` = 'Albury'"; + public final static String VIEW_5_QUERY_HASH = "120f32478aaff874c25ab32eceb9f00b64cc9d422831046f2f5d43953aca01e7"; - public static final View VIEW_5 = View.builder() + public final View VIEW_5 = View.builder() .id(VIEW_5_ID) .isInitialView(VIEW_5_INITIAL_VIEW) .name(VIEW_5_NAME) @@ -5720,7 +5652,7 @@ public abstract class BaseTest { .columns(null) .build(); - public static final ViewDto VIEW_5_DTO = ViewDto.builder() + public final ViewDto VIEW_5_DTO = ViewDto.builder() .id(VIEW_5_ID) .databaseId(DATABASE_3_ID) .isInitialView(VIEW_5_INITIAL_VIEW) @@ -5734,7 +5666,7 @@ public abstract class BaseTest { .columns(new LinkedList<>()) .build(); - public static final ViewBriefDto VIEW_5_BRIEF_DTO = ViewBriefDto.builder() + public final ViewBriefDto VIEW_5_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_5_ID) .isInitialView(VIEW_5_INITIAL_VIEW) .name(VIEW_5_NAME) @@ -5746,7 +5678,7 @@ public abstract class BaseTest { .queryHash(VIEW_5_QUERY_HASH) .build(); - public static final List<ViewColumn> VIEW_5_COLUMNS = List.of( + public final List<ViewColumn> VIEW_5_COLUMNS = List.of( ViewColumn.builder() .id(COLUMN_2_1_ID) .ordinalPosition(0) @@ -5780,7 +5712,7 @@ public abstract class BaseTest { .view(VIEW_5) .build()); - public static final List<ViewColumnDto> VIEW_5_COLUMNS_DTO = List.of( + public final List<ViewColumnDto> VIEW_5_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(COLUMN_2_1_ID) .databaseId(DATABASE_3_ID) @@ -5814,8 +5746,8 @@ public abstract class BaseTest { .isNullAllowed(true) .build()); - public static final Long QUERY_1_RESULT_ID = 1L; - public static final List<Map<String, Object>> QUERY_1_RESULT_DTO = new LinkedList<>(List.of( + public final static Long QUERY_1_RESULT_ID = 1L; + public final List<Map<String, Object>> QUERY_1_RESULT_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put("location", "Albury"); put("lat", -36.0653583); @@ -5826,33 +5758,30 @@ public abstract class BaseTest { put("lng", 150.6517942); }})); - public static final String LICENSE_1_IDENTIFIER = "MIT"; - public static final String LICENSE_1_URI = "https://opensource.org/license/mit/"; - - public static final License LICENSE_1 = License.builder() + public final static String LICENSE_1_IDENTIFIER = "MIT"; + public final static String LICENSE_1_URI = "https://opensource.org/license/mit/"; + public final License LICENSE_1 = License.builder() .identifier(LICENSE_1_IDENTIFIER) .uri(LICENSE_1_URI) .build(); - public static final LicenseDto LICENSE_1_DTO = LicenseDto.builder() + public final LicenseDto LICENSE_1_DTO = LicenseDto.builder() .identifier(LICENSE_1_IDENTIFIER) .uri(LICENSE_1_URI) .build(); - public static final UUID CREATOR_1_ID = UUID.fromString("a0417f34-80ff-419f-821d-ce179021484a"); - public static final String CREATOR_1_ORCID = "00000-00000-00000"; - public static final String CREATOR_1_AFFIL = "TU Graz"; - public static final String CREATOR_1_AFFIL_ROR = "https://ror.org/04wn28048"; - public static final String CREATOR_1_AFFIL_URI = "https://ror.org/"; - public static final AffiliationIdentifierSchemeType CREATOR_1_AFFIL_TYPE = AffiliationIdentifierSchemeType.ROR; - public static final AffiliationIdentifierSchemeTypeDto CREATOR_1_AFFIL_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; - public static final String CREATOR_1_FIRSTNAME = "Max"; - public static final String CREATOR_1_LASTNAME = "Mustermann"; - public static final String CREATOR_1_NAME = CREATOR_1_LASTNAME + ", " + CREATOR_1_FIRSTNAME; - public static final Instant CREATOR_1_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant CREATOR_1_MODIFIED = Instant.ofEpochSecond(1541588352L); - - public static final OrcidDto ORCID_1_DTO = OrcidDto.builder() + public final static UUID CREATOR_1_ID = UUID.fromString("a0417f34-80ff-419f-821d-ce179021484a"); + public final static String CREATOR_1_ORCID = "00000-00000-00000"; + public final static String CREATOR_1_AFFIL = "TU Graz"; + public final static String CREATOR_1_AFFIL_ROR = "https://ror.org/04wn28048"; + public final static String CREATOR_1_AFFIL_URI = "https://ror.org/"; + public final static AffiliationIdentifierSchemeType CREATOR_1_AFFIL_TYPE = AffiliationIdentifierSchemeType.ROR; + public final static AffiliationIdentifierSchemeTypeDto CREATOR_1_AFFIL_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; + public final static String CREATOR_1_FIRSTNAME = "Max"; + public final static String CREATOR_1_LASTNAME = "Mustermann"; + public final static String CREATOR_1_NAME = CREATOR_1_LASTNAME + ", " + CREATOR_1_FIRSTNAME; + + public final OrcidDto ORCID_1_DTO = OrcidDto.builder() .person(OrcidPersonDto.builder() .name(OrcidNameDto.builder() .givenNames(OrcidValueDto.builder() @@ -5882,190 +5811,184 @@ public abstract class BaseTest { .build()) .build(); - public static final UUID CREATOR_2_ID = UUID.fromString("56b70dae-17a7-4f76-9c1e-a493762ba760"); - public static final Long CREATOR_2_QUERY_ID = 1L; - public static final String CREATOR_2_ORCID = "00000-00000-00000"; - public static final String CREATOR_2_AFFIL = "TU Wien"; - public static final String CREATOR_2_FIRSTNAME = "Martina"; - public static final String CREATOR_2_LASTNAME = "Mustermann"; - public static final String CREATOR_2_NAME = CREATOR_2_LASTNAME + ", " + CREATOR_2_FIRSTNAME; - public static final Instant CREATOR_2_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant CREATOR_2_MODIFIED = Instant.ofEpochSecond(1541588352L); - - public static final UUID CREATOR_3_ID = UUID.fromString("a2dfea46-7d88-4069-9b93-2417e1fb578b"); - public static final Long CREATOR_3_QUERY_ID = 1L; - public static final String CREATOR_3_ORCID = "00000-00000-00000"; - public static final String CREATOR_3_AFFIL = "TU Graz"; - public static final String CREATOR_3_AFFIL_ROR = "https://ror.org/04wn28048"; - public static final AffiliationIdentifierSchemeType CREATOR_3_AFFIL_SCHEME_TYPE = AffiliationIdentifierSchemeType.ROR; - public static final AffiliationIdentifierSchemeTypeDto CREATOR_3_AFFIL_SCHEME_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; - public static final String CREATOR_3_AFFIL_URI = "https://ror.org/"; - public static final String CREATOR_3_FIRSTNAME = "Max"; - public static final String CREATOR_3_LASTNAME = "Mustermann"; - public static final String CREATOR_3_NAME = CREATOR_3_LASTNAME + ", " + CREATOR_3_FIRSTNAME; - public static final Instant CREATOR_3_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant CREATOR_3_MODIFIED = Instant.ofEpochSecond(1541588352L); - - public static final UUID CREATOR_4_ID = UUID.fromString("473489fa-ad02-4e48-856f-5a3f83ff541d"); - public static final Long CREATOR_4_QUERY_ID = 1L; - public static final String CREATOR_4_ORCID = "00000-00000-00000"; - public static final String CREATOR_4_AFFIL = "TU Wien"; - public static final String CREATOR_4_AFFIL_ROR = "https://ror.org/04d836q62"; - public static final String CREATOR_4_AFFIL_URI = "https://ror.org/"; - public static final AffiliationIdentifierSchemeType CREATOR_4_AFFIL_TYPE = AffiliationIdentifierSchemeType.ROR; - public static final AffiliationIdentifierSchemeTypeDto CREATOR_4_AFFIL_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; - public static final String CREATOR_4_FIRSTNAME = "Martina"; - public static final String CREATOR_4_LASTNAME = "Mustermann"; - public static final String CREATOR_4_NAME = CREATOR_4_LASTNAME + ", " + CREATOR_4_FIRSTNAME; - public static final Instant CREATOR_4_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant CREATOR_4_MODIFIED = Instant.ofEpochSecond(1541588352L); - - public static final UUID IDENTIFIER_1_ID = UUID.fromString("679a83f2-ef23-4b4b-98f7-ad77b9d68733"); - public static final String IDENTIFIER_1_DOI = "10.12345/183"; - public static final Instant IDENTIFIER_1_CREATED = Instant.ofEpochSecond(1641588352L) /* 2022-01-07 20:45:52 */; - public static final Instant IDENTIFIER_1_MODIFIED = Instant.ofEpochSecond(1541588352L) /* 2022-01-07 20:45:52 */; - public static final Instant IDENTIFIER_1_EXECUTION = Instant.ofEpochSecond(1541588352L) /* 2022-01-07 20:45:52 */; - public static final Integer IDENTIFIER_1_PUBLICATION_MONTH = 5; - public static final Integer IDENTIFIER_1_PUBLICATION_YEAR = 2022; - public static final Integer IDENTIFIER_1_PUBLICATION_DAY = null; - public static final String IDENTIFIER_1_PUBLISHER = "Austrian Government"; - public static final IdentifierType IDENTIFIER_1_TYPE = IdentifierType.DATABASE; - public static final IdentifierTypeDto IDENTIFIER_1_TYPE_DTO = IdentifierTypeDto.DATABASE; - public static final IdentifierStatusType IDENTIFIER_1_STATUS_TYPE = IdentifierStatusType.PUBLISHED; - public static final IdentifierStatusTypeDto IDENTIFIER_1_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; - - public static final UUID IDENTIFIER_1_TITLE_1_ID = UUID.fromString("3df6b286-9bd2-4ae3-b8f4-29c217544bef"); - public static final String IDENTIFIER_1_TITLE_1_TITLE = "Austrian weather data"; - public static final String IDENTIFIER_1_TITLE_1_TITLE_MODIFY = "Austrian weather some data"; - public static final TitleType IDENTIFIER_1_TITLE_1_TYPE = null; - public static final TitleTypeDto IDENTIFIER_1_TITLE_1_TYPE_DTO = null; - public static final LanguageType IDENTIFIER_1_TITLE_1_LANG = LanguageType.EN; - public static final LanguageTypeDto IDENTIFIER_1_TITLE_1_LANG_DTO = LanguageTypeDto.EN; - - public static final IdentifierTitle IDENTIFIER_1_TITLE_1 = IdentifierTitle.builder() + public final static UUID CREATOR_2_ID = UUID.fromString("56b70dae-17a7-4f76-9c1e-a493762ba760"); + public final static Long CREATOR_2_QUERY_ID = 1L; + public final static String CREATOR_2_ORCID = "00000-00000-00000"; + public final static String CREATOR_2_AFFIL = "TU Wien"; + public final static String CREATOR_2_FIRSTNAME = "Martina"; + public final static String CREATOR_2_LASTNAME = "Mustermann"; + public final static String CREATOR_2_NAME = CREATOR_2_LASTNAME + ", " + CREATOR_2_FIRSTNAME; + + public final static UUID CREATOR_3_ID = UUID.fromString("a2dfea46-7d88-4069-9b93-2417e1fb578b"); + public final static Long CREATOR_3_QUERY_ID = 1L; + public final static String CREATOR_3_ORCID = "00000-00000-00000"; + public final static String CREATOR_3_AFFIL = "TU Graz"; + public final static String CREATOR_3_AFFIL_ROR = "https://ror.org/04wn28048"; + public final static AffiliationIdentifierSchemeType CREATOR_3_AFFIL_SCHEME_TYPE = AffiliationIdentifierSchemeType.ROR; + public final static AffiliationIdentifierSchemeTypeDto CREATOR_3_AFFIL_SCHEME_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; + public final static String CREATOR_3_AFFIL_URI = "https://ror.org/"; + public final static String CREATOR_3_FIRSTNAME = "Max"; + public final static String CREATOR_3_LASTNAME = "Mustermann"; + public final static String CREATOR_3_NAME = CREATOR_3_LASTNAME + ", " + CREATOR_3_FIRSTNAME; + + public final static UUID CREATOR_4_ID = UUID.fromString("473489fa-ad02-4e48-856f-5a3f83ff541d"); + public final static Long CREATOR_4_QUERY_ID = 1L; + public final static String CREATOR_4_ORCID = "00000-00000-00000"; + public final static String CREATOR_4_AFFIL = "TU Wien"; + public final static String CREATOR_4_AFFIL_ROR = "https://ror.org/04d836q62"; + public final static String CREATOR_4_AFFIL_URI = "https://ror.org/"; + public final static AffiliationIdentifierSchemeType CREATOR_4_AFFIL_TYPE = AffiliationIdentifierSchemeType.ROR; + public final static AffiliationIdentifierSchemeTypeDto CREATOR_4_AFFIL_TYPE_DTO = AffiliationIdentifierSchemeTypeDto.ROR; + public final static String CREATOR_4_FIRSTNAME = "Martina"; + public final static String CREATOR_4_LASTNAME = "Mustermann"; + public final static String CREATOR_4_NAME = CREATOR_4_LASTNAME + ", " + CREATOR_4_FIRSTNAME; + + public final static UUID IDENTIFIER_1_ID = UUID.fromString("679a83f2-ef23-4b4b-98f7-ad77b9d68733"); + public final static String IDENTIFIER_1_DOI = "10.12345/183"; + public final static Instant IDENTIFIER_1_CREATED = Instant.ofEpochSecond(1641588352L) /* 2022-01-07 20:45:52 */; + public final static Instant IDENTIFIER_1_MODIFIED = Instant.ofEpochSecond(1541588352L) /* 2022-01-07 20:45:52 */; + public final static Instant IDENTIFIER_1_EXECUTION = Instant.ofEpochSecond(1541588352L) /* 2022-01-07 20:45:52 */; + public final static Integer IDENTIFIER_1_PUBLICATION_MONTH = 5; + public final static Integer IDENTIFIER_1_PUBLICATION_YEAR = 2022; + public final static Integer IDENTIFIER_1_PUBLICATION_DAY = null; + public final static String IDENTIFIER_1_PUBLISHER = "Austrian Government"; + public final static IdentifierType IDENTIFIER_1_TYPE = IdentifierType.DATABASE; + public final static IdentifierTypeDto IDENTIFIER_1_TYPE_DTO = IdentifierTypeDto.DATABASE; + public final static IdentifierStatusType IDENTIFIER_1_STATUS_TYPE = IdentifierStatusType.PUBLISHED; + public final static IdentifierStatusTypeDto IDENTIFIER_1_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; + + public final static UUID IDENTIFIER_1_TITLE_1_ID = UUID.fromString("3df6b286-9bd2-4ae3-b8f4-29c217544bef"); + public final static String IDENTIFIER_1_TITLE_1_TITLE = "Austrian weather data"; + public final static String IDENTIFIER_1_TITLE_1_TITLE_MODIFY = "Austrian weather some data"; + public final static TitleType IDENTIFIER_1_TITLE_1_TYPE = null; + public final static TitleTypeDto IDENTIFIER_1_TITLE_1_TYPE_DTO = null; + public final static LanguageType IDENTIFIER_1_TITLE_1_LANG = LanguageType.EN; + public final static LanguageTypeDto IDENTIFIER_1_TITLE_1_LANG_DTO = LanguageTypeDto.EN; + + public final IdentifierTitle IDENTIFIER_1_TITLE_1 = IdentifierTitle.builder() .id(IDENTIFIER_1_TITLE_1_ID) .title(IDENTIFIER_1_TITLE_1_TITLE) .titleType(IDENTIFIER_1_TITLE_1_TYPE) .language(IDENTIFIER_1_TITLE_1_LANG) .build(); - public static final IdentifierTitleDto IDENTIFIER_1_TITLE_1_DTO = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_1_TITLE_1_DTO = IdentifierTitleDto.builder() .id(IDENTIFIER_1_TITLE_1_ID) .title(IDENTIFIER_1_TITLE_1_TITLE) .titleType(IDENTIFIER_1_TITLE_1_TYPE_DTO) .language(IDENTIFIER_1_TITLE_1_LANG_DTO) .build(); - public static final IdentifierTitleDto IDENTIFIER_1_TITLE_1_DTO_MODIFY = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_1_TITLE_1_DTO_MODIFY = IdentifierTitleDto.builder() .id(IDENTIFIER_1_TITLE_1_ID) .title(IDENTIFIER_1_TITLE_1_TITLE_MODIFY) .titleType(IDENTIFIER_1_TITLE_1_TYPE_DTO) .language(IDENTIFIER_1_TITLE_1_LANG_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_1_TITLE_1_TITLE) .titleType(IDENTIFIER_1_TITLE_1_TYPE_DTO) .language(IDENTIFIER_1_TITLE_1_LANG_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_1_UPDATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_1_UPDATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_1_TITLE_1_TITLE_MODIFY) .titleType(IDENTIFIER_1_TITLE_1_TYPE_DTO) .language(IDENTIFIER_1_TITLE_1_LANG_DTO) .build(); - public static final UUID IDENTIFIER_1_TITLE_2_ID = UUID.fromString("903a7e5b-8014-4b8a-b8fd-44f477880905"); - public static final String IDENTIFIER_1_TITLE_2_TITLE = "Österreichische Wetterdaten"; - public static final String IDENTIFIER_1_TITLE_2_TITLE_MODIFY = "Österreichische Wetterdaten übersetzt"; - public static final TitleType IDENTIFIER_1_TITLE_2_TYPE = TitleType.TRANSLATED_TITLE; - public static final TitleTypeDto IDENTIFIER_1_TITLE_2_TYPE_DTO = TitleTypeDto.TRANSLATED_TITLE; - public static final LanguageType IDENTIFIER_1_TITLE_2_LANG = LanguageType.EN; - public static final LanguageTypeDto IDENTIFIER_1_TITLE_2_LANG_DTO = LanguageTypeDto.EN; + public final static UUID IDENTIFIER_1_TITLE_2_ID = UUID.fromString("903a7e5b-8014-4b8a-b8fd-44f477880905"); + public final static String IDENTIFIER_1_TITLE_2_TITLE = "Österreichische Wetterdaten"; + public final static String IDENTIFIER_1_TITLE_2_TITLE_MODIFY = "Österreichische Wetterdaten übersetzt"; + public final static TitleType IDENTIFIER_1_TITLE_2_TYPE = TitleType.TRANSLATED_TITLE; + public final static TitleTypeDto IDENTIFIER_1_TITLE_2_TYPE_DTO = TitleTypeDto.TRANSLATED_TITLE; + public final static LanguageType IDENTIFIER_1_TITLE_2_LANG = LanguageType.EN; + public final static LanguageTypeDto IDENTIFIER_1_TITLE_2_LANG_DTO = LanguageTypeDto.EN; - public static final IdentifierTitle IDENTIFIER_1_TITLE_2 = IdentifierTitle.builder() + public final IdentifierTitle IDENTIFIER_1_TITLE_2 = IdentifierTitle.builder() .id(IDENTIFIER_1_TITLE_2_ID) .title(IDENTIFIER_1_TITLE_2_TITLE) .titleType(IDENTIFIER_1_TITLE_2_TYPE) .language(IDENTIFIER_1_TITLE_2_LANG) .build(); - public static final IdentifierTitleDto IDENTIFIER_1_TITLE_2_DTO = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_1_TITLE_2_DTO = IdentifierTitleDto.builder() .id(IDENTIFIER_1_TITLE_2_ID) .title(IDENTIFIER_1_TITLE_2_TITLE) .titleType(IDENTIFIER_1_TITLE_2_TYPE_DTO) .language(IDENTIFIER_1_TITLE_2_LANG_DTO) .build(); - public static final IdentifierTitleDto IDENTIFIER_1_TITLE_2_DTO_MODIFY = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_1_TITLE_2_DTO_MODIFY = IdentifierTitleDto.builder() .id(IDENTIFIER_1_TITLE_2_ID) .title(IDENTIFIER_1_TITLE_2_TITLE_MODIFY) .titleType(IDENTIFIER_1_TITLE_2_TYPE_DTO) .language(IDENTIFIER_1_TITLE_2_LANG_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_2_CREATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_2_CREATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_1_TITLE_2_TITLE) .titleType(IDENTIFIER_1_TITLE_2_TYPE_DTO) .language(IDENTIFIER_1_TITLE_2_LANG_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_2_UPDATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_1_TITLE_2_UPDATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_1_TITLE_2_TITLE_MODIFY) .titleType(IDENTIFIER_1_TITLE_2_TYPE_DTO) .language(IDENTIFIER_1_TITLE_2_LANG_DTO) .build(); - public static final UUID IDENTIFIER_1_DESCRIPTION_1_ID = UUID.fromString("1c438756-93f0-4797-983c-175a17e18c2c"); - public static final String IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION = "Selecting all from the weather Austrian table"; - public static final String IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION_MODIFY = "Selecting some from the weather Austrian table"; - public static final DescriptionType IDENTIFIER_1_DESCRIPTION_1_TYPE = null; - public static final DescriptionTypeDto IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO = null; - public static final LanguageType IDENTIFIER_1_DESCRIPTION_1_LANG = LanguageType.EN; - public static final LanguageTypeDto IDENTIFIER_1_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.EN; + public final static UUID IDENTIFIER_1_DESCRIPTION_1_ID = UUID.fromString("1c438756-93f0-4797-983c-175a17e18c2c"); + public final static String IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION = "Selecting all from the weather Austrian table"; + public final static String IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION_MODIFY = "Selecting some from the weather Austrian table"; + public final static DescriptionType IDENTIFIER_1_DESCRIPTION_1_TYPE = null; + public final static DescriptionTypeDto IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO = null; + public final static LanguageType IDENTIFIER_1_DESCRIPTION_1_LANG = LanguageType.EN; + public final static LanguageTypeDto IDENTIFIER_1_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.EN; - public static final IdentifierDescription IDENTIFIER_1_DESCRIPTION_1 = IdentifierDescription.builder() + public final IdentifierDescription IDENTIFIER_1_DESCRIPTION_1 = IdentifierDescription.builder() .id(IDENTIFIER_1_DESCRIPTION_1_ID) .description(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION) .descriptionType(IDENTIFIER_1_DESCRIPTION_1_TYPE) .language(IDENTIFIER_1_DESCRIPTION_1_LANG) .build(); - public static final IdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() + public final IdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() .id(IDENTIFIER_1_DESCRIPTION_1_ID) .description(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION) .descriptionType(IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO) .language(IDENTIFIER_1_DESCRIPTION_1_LANG_DTO) .build(); - public static final IdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_DTO_MODIFY = IdentifierDescriptionDto.builder() + public final IdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_DTO_MODIFY = IdentifierDescriptionDto.builder() .id(IDENTIFIER_1_DESCRIPTION_1_ID) .description(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION_MODIFY) .descriptionType(IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO) .language(IDENTIFIER_1_DESCRIPTION_1_LANG_DTO) .build(); - public static final SaveIdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() + public final SaveIdentifierDescriptionDto IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() .id(null) .description(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION) .descriptionType(IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO) .language(IDENTIFIER_1_DESCRIPTION_1_LANG_DTO) .build(); - public static final UUID IDENTIFIER_1_CREATOR_1_ID = UUID.fromString("667cd1d6-4f94-4808-b5cb-12e5ec0788d8"); - public static final String IDENTIFIER_1_CREATOR_1_FIRSTNAME = CREATOR_1_FIRSTNAME; - public static final String IDENTIFIER_1_CREATOR_1_LASTNAME = CREATOR_1_LASTNAME; - public static final String IDENTIFIER_1_CREATOR_1_NAME = CREATOR_1_NAME; - public static final String IDENTIFIER_1_CREATOR_1_ORCID = CREATOR_1_ORCID; - public static final NameIdentifierSchemeType IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE = NameIdentifierSchemeType.ORCID; - public static final NameIdentifierSchemeTypeDto IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE_DTO = NameIdentifierSchemeTypeDto.ORCID; - public static final String IDENTIFIER_1_CREATOR_1_AFFILIATION = CREATOR_1_AFFIL; - public static final String IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER = CREATOR_1_AFFIL_ROR; - public static final AffiliationIdentifierSchemeType IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME = CREATOR_1_AFFIL_TYPE; - public static final AffiliationIdentifierSchemeTypeDto IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_DTO = CREATOR_1_AFFIL_TYPE_DTO; - public static final String IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI = CREATOR_1_AFFIL_URI; - - public static final Creator IDENTIFIER_1_CREATOR_1 = Creator.builder() + public final static UUID IDENTIFIER_1_CREATOR_1_ID = UUID.fromString("667cd1d6-4f94-4808-b5cb-12e5ec0788d8"); + public final static String IDENTIFIER_1_CREATOR_1_FIRSTNAME = CREATOR_1_FIRSTNAME; + public final static String IDENTIFIER_1_CREATOR_1_LASTNAME = CREATOR_1_LASTNAME; + public final static String IDENTIFIER_1_CREATOR_1_NAME = CREATOR_1_NAME; + public final static String IDENTIFIER_1_CREATOR_1_ORCID = CREATOR_1_ORCID; + public final NameIdentifierSchemeType IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE = NameIdentifierSchemeType.ORCID; + public final NameIdentifierSchemeTypeDto IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE_DTO = NameIdentifierSchemeTypeDto.ORCID; + public final static String IDENTIFIER_1_CREATOR_1_AFFILIATION = CREATOR_1_AFFIL; + public final static String IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER = CREATOR_1_AFFIL_ROR; + public final static AffiliationIdentifierSchemeType IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME = CREATOR_1_AFFIL_TYPE; + public final static AffiliationIdentifierSchemeTypeDto IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_DTO = CREATOR_1_AFFIL_TYPE_DTO; + public final static String IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI = CREATOR_1_AFFIL_URI; + + public final Creator IDENTIFIER_1_CREATOR_1 = Creator.builder() .id(IDENTIFIER_1_CREATOR_1_ID) .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) @@ -6079,7 +6002,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI) .build(); - public static final CreatorDto IDENTIFIER_1_CREATOR_1_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_1_CREATOR_1_DTO = CreatorDto.builder() .id(IDENTIFIER_1_CREATOR_1_ID) .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) @@ -6093,7 +6016,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_1_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_1_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() .id(null) .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) @@ -6106,15 +6029,15 @@ public abstract class BaseTest { .affiliationIdentifierScheme(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_DTO) .build(); - public static final UUID FUNDER_1_ID = UUID.fromString("8deb273d-6dd6-407d-970a-01534035ac01"); - public static final String FUNDER_1_NAME = "European Commission"; - public static final String FUNDER_1_IDENTIFIER = "https://doi.org/10.13039/501100000780"; - public static final String FUNDER_1_IDENTIFIER_ID_ONLY = "10.13039/501100000780"; - public static final IdentifierFunderType FUNDER_1_IDENTIFIER_TYPE = IdentifierFunderType.CROSSREF_FUNDER_ID; - public static final IdentifierFunderTypeDto FUNDER_1_IDENTIFIER_TYPE_DTO = IdentifierFunderTypeDto.CROSSREF_FUNDER_ID; - public static final String FUNDER_1_AWARD_TITLE = "Institutionalizing global genetic-resource commons. Global Strategies for accessing and using essential public knowledge assets in the life science"; + public final static UUID FUNDER_1_ID = UUID.fromString("8deb273d-6dd6-407d-970a-01534035ac01"); + public final static String FUNDER_1_NAME = "European Commission"; + public final static String FUNDER_1_IDENTIFIER = "https://doi.org/10.13039/501100000780"; + public final static String FUNDER_1_IDENTIFIER_ID_ONLY = "10.13039/501100000780"; + public final IdentifierFunderType FUNDER_1_IDENTIFIER_TYPE = IdentifierFunderType.CROSSREF_FUNDER_ID; + public final IdentifierFunderTypeDto FUNDER_1_IDENTIFIER_TYPE_DTO = IdentifierFunderTypeDto.CROSSREF_FUNDER_ID; + public final static String FUNDER_1_AWARD_TITLE = "Institutionalizing global genetic-resource commons. Global Strategies for accessing and using essential public knowledge assets in the life science"; - public static final IdentifierFunder IDENTIFIER_1_FUNDER_1 = IdentifierFunder.builder() + public final IdentifierFunder IDENTIFIER_1_FUNDER_1 = IdentifierFunder.builder() .id(FUNDER_1_ID) .funderName(FUNDER_1_NAME) .funderIdentifier(FUNDER_1_IDENTIFIER) @@ -6122,7 +6045,7 @@ public abstract class BaseTest { .awardTitle(FUNDER_1_AWARD_TITLE) .build(); - public static final IdentifierFunderDto IDENTIFIER_1_FUNDER_1_DTO = IdentifierFunderDto.builder() + public final IdentifierFunderDto IDENTIFIER_1_FUNDER_1_DTO = IdentifierFunderDto.builder() .id(FUNDER_1_ID) .funderName(FUNDER_1_NAME) .funderIdentifier(FUNDER_1_IDENTIFIER) @@ -6130,14 +6053,14 @@ public abstract class BaseTest { .awardTitle(FUNDER_1_AWARD_TITLE) .build(); - public static final SaveIdentifierFunderDto IDENTIFIER_1_FUNDER_1_CREATE_DTO = SaveIdentifierFunderDto.builder() + public final SaveIdentifierFunderDto IDENTIFIER_1_FUNDER_1_CREATE_DTO = SaveIdentifierFunderDto.builder() .funderName(FUNDER_1_NAME) .funderIdentifier(FUNDER_1_IDENTIFIER) .funderIdentifierType(FUNDER_1_IDENTIFIER_TYPE_DTO) .awardTitle(FUNDER_1_AWARD_TITLE) .build(); - public static final DataCiteBody<DataCiteDoi> IDENTIFIER_1_DATA_CITE = DataCiteBody.<DataCiteDoi>builder() + public final DataCiteBody<DataCiteDoi> IDENTIFIER_1_DATA_CITE = DataCiteBody.<DataCiteDoi>builder() .data(DataCiteData.<DataCiteDoi>builder() .type("dois") .attributes(DataCiteDoi.builder() @@ -6146,7 +6069,7 @@ public abstract class BaseTest { .build()) .build(); - public static final Identifier IDENTIFIER_1 = Identifier.builder() + public final Identifier IDENTIFIER_1 = Identifier.builder() .id(IDENTIFIER_1_ID) .queryId(QUERY_1_ID) .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1, IDENTIFIER_1_TITLE_2))) @@ -6173,32 +6096,7 @@ public abstract class BaseTest { .status(IDENTIFIER_1_STATUS_TYPE) .build(); - public static final Identifier IDENTIFIER_1_WITH_DOI = Identifier.builder() - .id(IDENTIFIER_1_ID) - .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1))) - .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1, IDENTIFIER_1_TITLE_2))) - .doi(IDENTIFIER_1_DOI) - .database(null /* for jpa */) - .created(IDENTIFIER_1_CREATED) - .lastModified(IDENTIFIER_1_MODIFIED) - .execution(IDENTIFIER_1_EXECUTION) - .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) - .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) - .queryHash(QUERY_1_QUERY_HASH) - .resultHash(QUERY_1_RESULT_HASH) - .query(QUERY_1_STATEMENT) - .queryNormalized(QUERY_1_STATEMENT) - .resultNumber(QUERY_1_RESULT_NUMBER) - .publisher(IDENTIFIER_1_PUBLISHER) - .type(IDENTIFIER_1_TYPE) - .owner(USER_1) - .licenses(new LinkedList<>(List.of(LICENSE_1))) - .creators(new LinkedList<>(List.of(IDENTIFIER_1_CREATOR_1))) - .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1))) - .status(IDENTIFIER_1_STATUS_TYPE) - .build(); - - public static final IdentifierDto IDENTIFIER_1_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_1_DTO = IdentifierDto.builder() .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .links(LinksDto.builder() @@ -6226,7 +6124,7 @@ public abstract class BaseTest { .status(IDENTIFIER_1_STATUS_TYPE_DTO) .build(); - public static final IdentifierBriefDto IDENTIFIER_1_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_1_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_DTO, IDENTIFIER_1_TITLE_2_DTO))) @@ -6237,7 +6135,7 @@ public abstract class BaseTest { .status(IDENTIFIER_1_STATUS_TYPE_DTO) .build(); - public static final CreateIdentifierDto IDENTIFIER_1_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_1_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_1_ID) .type(IDENTIFIER_1_TYPE_DTO) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) @@ -6254,7 +6152,7 @@ public abstract class BaseTest { .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO))) .build(); - public static final CreateIdentifierDto IDENTIFIER_1_CREATE_WITH_DOI_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_1_CREATE_WITH_DOI_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_1_ID) .type(IDENTIFIER_1_TYPE_DTO) .doi(IDENTIFIER_1_DOI) @@ -6271,7 +6169,7 @@ public abstract class BaseTest { .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO))) .build(); - public static final IdentifierSaveDto IDENTIFIER_1_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_1_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO))) @@ -6286,7 +6184,7 @@ public abstract class BaseTest { .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .build(); - public static final IdentifierSaveDto IDENTIFIER_1_SAVE_MODIFY_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_1_SAVE_MODIFY_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .descriptions(new LinkedList<>(List.of())) // <<< @@ -6301,84 +6199,83 @@ public abstract class BaseTest { .licenses(new LinkedList<>(List.of())) // <<< .build(); - public static final UUID IDENTIFIER_5_ID = UUID.fromString("e05bb4c9-ed26-48c9-bd91-5c48a93a04bd"); - public static final String IDENTIFIER_5_DOI = "10.12345/13/50BBFCFE08A12"; - public static final Instant IDENTIFIER_5_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant IDENTIFIER_5_MODIFIED = Instant.ofEpochSecond(1541588352L); - public static final Instant IDENTIFIER_5_EXECUTION = Instant.ofEpochSecond(1541588352L); - public static final Integer IDENTIFIER_5_PUBLICATION_DAY = 14; - public static final Integer IDENTIFIER_5_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_5_PUBLICATION_YEAR = 2022; - public static final String IDENTIFIER_5_QUERY_HASH = QUERY_2_QUERY_HASH; - public static final String IDENTIFIER_5_RESULT_HASH = QUERY_2_RESULT_HASH; - public static final String IDENTIFIER_5_QUERY = QUERY_2_STATEMENT; - public static final String IDENTIFIER_5_NORMALIZED = QUERY_2_STATEMENT; - public static final Long IDENTIFIER_5_RESULT_NUMBER = QUERY_2_RESULT_NUMBER; - public static final String IDENTIFIER_5_PUBLISHER = "Australian Government"; - public static final IdentifierType IDENTIFIER_5_TYPE = IdentifierType.SUBSET; - public static final IdentifierTypeDto IDENTIFIER_5_TYPE_DTO = IdentifierTypeDto.SUBSET; - public static final IdentifierStatusType IDENTIFIER_5_STATUS_TYPE = IdentifierStatusType.DRAFT; - public static final IdentifierStatusTypeDto IDENTIFIER_5_STATUS_TYPE_DTO = IdentifierStatusTypeDto.DRAFT; - public static final UUID IDENTIFIER_5_CREATED_BY = USER_2_ID; - - public static final UUID IDENTIFIER_5_TITLE_1_ID = UUID.fromString("1a0ae9c2-61c6-44f8-b886-26a4f4dabc52"); - public static final String IDENTIFIER_5_TITLE_1_TITLE = "Australische Wetterdaten"; - public static final LanguageType IDENTIFIER_5_TITLE_1_LANG = LanguageType.DE; - public static final LanguageTypeDto IDENTIFIER_5_TITLE_1_LANG_DTO = LanguageTypeDto.DE; - public static final TitleType IDENTIFIER_5_TITLE_1_TYPE = TitleType.SUBTITLE; - public static final TitleTypeDto IDENTIFIER_5_TITLE_1_TYPE_DTO = TitleTypeDto.SUBTITLE; - - public static final IdentifierTitle IDENTIFIER_5_TITLE_1 = IdentifierTitle.builder() + public final static UUID IDENTIFIER_5_ID = UUID.fromString("e05bb4c9-ed26-48c9-bd91-5c48a93a04bd"); + public final static String IDENTIFIER_5_DOI = "10.12345/13/50BBFCFE08A12"; + public final static Instant IDENTIFIER_5_CREATED = Instant.ofEpochSecond(1641588352L); + public final static Instant IDENTIFIER_5_MODIFIED = Instant.ofEpochSecond(1541588352L); + public final static Instant IDENTIFIER_5_EXECUTION = Instant.ofEpochSecond(1541588352L); + public final static Integer IDENTIFIER_5_PUBLICATION_DAY = 14; + public final static Integer IDENTIFIER_5_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_5_PUBLICATION_YEAR = 2022; + public final static String IDENTIFIER_5_QUERY_HASH = QUERY_2_QUERY_HASH; + public final static String IDENTIFIER_5_RESULT_HASH = QUERY_2_RESULT_HASH; + public final static String IDENTIFIER_5_QUERY = QUERY_2_STATEMENT; + public final static String IDENTIFIER_5_NORMALIZED = QUERY_2_STATEMENT; + public final static Long IDENTIFIER_5_RESULT_NUMBER = QUERY_2_RESULT_NUMBER; + public final static String IDENTIFIER_5_PUBLISHER = "Australian Government"; + public final static IdentifierType IDENTIFIER_5_TYPE = IdentifierType.SUBSET; + public final static IdentifierTypeDto IDENTIFIER_5_TYPE_DTO = IdentifierTypeDto.SUBSET; + public final static IdentifierStatusType IDENTIFIER_5_STATUS_TYPE = IdentifierStatusType.DRAFT; + public final static IdentifierStatusTypeDto IDENTIFIER_5_STATUS_TYPE_DTO = IdentifierStatusTypeDto.DRAFT; + + public final static UUID IDENTIFIER_5_TITLE_1_ID = UUID.fromString("1a0ae9c2-61c6-44f8-b886-26a4f4dabc52"); + public final static String IDENTIFIER_5_TITLE_1_TITLE = "Australische Wetterdaten"; + public final static LanguageType IDENTIFIER_5_TITLE_1_LANG = LanguageType.DE; + public final static LanguageTypeDto IDENTIFIER_5_TITLE_1_LANG_DTO = LanguageTypeDto.DE; + public final static TitleType IDENTIFIER_5_TITLE_1_TYPE = TitleType.SUBTITLE; + public final static TitleTypeDto IDENTIFIER_5_TITLE_1_TYPE_DTO = TitleTypeDto.SUBTITLE; + + public final IdentifierTitle IDENTIFIER_5_TITLE_1 = IdentifierTitle.builder() .id(IDENTIFIER_5_TITLE_1_ID) .title(IDENTIFIER_5_TITLE_1_TITLE) .language(IDENTIFIER_5_TITLE_1_LANG) .titleType(IDENTIFIER_5_TITLE_1_TYPE) .build(); - public static final IdentifierTitleDto IDENTIFIER_5_TITLE_1_DTO = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_5_TITLE_1_DTO = IdentifierTitleDto.builder() .id(IDENTIFIER_5_TITLE_1_ID) .title(IDENTIFIER_5_TITLE_1_TITLE) .language(IDENTIFIER_5_TITLE_1_LANG_DTO) .titleType(IDENTIFIER_5_TITLE_1_TYPE_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_5_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_5_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_5_TITLE_1_TITLE) .language(IDENTIFIER_5_TITLE_1_LANG_DTO) .titleType(IDENTIFIER_5_TITLE_1_TYPE_DTO) .build(); - public static final UUID IDENTIFIER_5_DESCRIPTION_1_ID = UUID.fromString("ab49bdca-f373-4823-9947-2a0cbfa88350"); - public static final String IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION = "Alle Wetterdaten in Australien"; - public static final LanguageType IDENTIFIER_5_DESCRIPTION_1_LANG = LanguageType.DE; - public static final LanguageTypeDto IDENTIFIER_5_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.DE; - public static final DescriptionType IDENTIFIER_5_DESCRIPTION_1_TYPE = DescriptionType.ABSTRACT; - public static final DescriptionTypeDto IDENTIFIER_5_DESCRIPTION_1_TYPE_DTO = DescriptionTypeDto.ABSTRACT; + public final static UUID IDENTIFIER_5_DESCRIPTION_1_ID = UUID.fromString("ab49bdca-f373-4823-9947-2a0cbfa88350"); + public final static String IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION = "Alle Wetterdaten in Australien"; + public final static LanguageType IDENTIFIER_5_DESCRIPTION_1_LANG = LanguageType.DE; + public final static LanguageTypeDto IDENTIFIER_5_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.DE; + public final static DescriptionType IDENTIFIER_5_DESCRIPTION_1_TYPE = DescriptionType.ABSTRACT; + public final static DescriptionTypeDto IDENTIFIER_5_DESCRIPTION_1_TYPE_DTO = DescriptionTypeDto.ABSTRACT; - public static final IdentifierDescription IDENTIFIER_5_DESCRIPTION_1 = IdentifierDescription.builder() + public final IdentifierDescription IDENTIFIER_5_DESCRIPTION_1 = IdentifierDescription.builder() .id(IDENTIFIER_5_DESCRIPTION_1_ID) .description(IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_5_DESCRIPTION_1_LANG) .descriptionType(IDENTIFIER_5_DESCRIPTION_1_TYPE) .build(); - public static final IdentifierDescriptionDto IDENTIFIER_5_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() + public final IdentifierDescriptionDto IDENTIFIER_5_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() .id(IDENTIFIER_5_DESCRIPTION_1_ID) .description(IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_5_DESCRIPTION_1_LANG_DTO) .descriptionType(IDENTIFIER_5_DESCRIPTION_1_TYPE_DTO) .build(); - public static final SaveIdentifierDescriptionDto IDENTIFIER_5_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() + public final SaveIdentifierDescriptionDto IDENTIFIER_5_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() .id(null) .description(IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_5_DESCRIPTION_1_LANG_DTO) .descriptionType(IDENTIFIER_5_DESCRIPTION_1_TYPE_DTO) .build(); - public static final UUID IDENTIFIER_5_CREATOR_1_ID = UUID.fromString("6844b684-93e4-47d2-a615-5939127fdafe"); + public final static UUID IDENTIFIER_5_CREATOR_1_ID = UUID.fromString("6844b684-93e4-47d2-a615-5939127fdafe"); - public static final Creator IDENTIFIER_5_CREATOR_1 = Creator.builder() + public final Creator IDENTIFIER_5_CREATOR_1 = Creator.builder() .id(IDENTIFIER_5_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6391,7 +6288,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final CreatorDto IDENTIFIER_5_CREATOR_1_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_5_CREATOR_1_DTO = CreatorDto.builder() .id(IDENTIFIER_5_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6404,7 +6301,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) .creatorName(CREATOR_1_NAME) @@ -6413,7 +6310,7 @@ public abstract class BaseTest { .affiliation(CREATOR_1_AFFIL) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_1_MODIFY_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_1_MODIFY_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) .creatorName(CREATOR_1_NAME) @@ -6422,9 +6319,9 @@ public abstract class BaseTest { .affiliation(CREATOR_1_AFFIL) .build(); - public static final UUID IDENTIFIER_5_CREATOR_2_ID = UUID.fromString("14943ad6-a935-49f5-b07e-f9eb789b8604"); + public final static UUID IDENTIFIER_5_CREATOR_2_ID = UUID.fromString("14943ad6-a935-49f5-b07e-f9eb789b8604"); - public static final Creator IDENTIFIER_5_CREATOR_2 = Creator.builder() + public final Creator IDENTIFIER_5_CREATOR_2 = Creator.builder() .id(IDENTIFIER_5_CREATOR_2_ID) .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) @@ -6434,7 +6331,7 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - public static final CreatorDto IDENTIFIER_5_CREATOR_2_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_5_CREATOR_2_DTO = CreatorDto.builder() .id(IDENTIFIER_5_CREATOR_2_ID) .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) @@ -6444,7 +6341,7 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_2_CREATE_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_2_CREATE_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) .creatorName(CREATOR_2_NAME) @@ -6453,7 +6350,7 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_2_MODIFY_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_5_CREATOR_2_MODIFY_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) .creatorName(CREATOR_2_NAME) @@ -6462,7 +6359,7 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - public static final Identifier IDENTIFIER_5 = Identifier.builder() + public final Identifier IDENTIFIER_5 = Identifier.builder() .id(IDENTIFIER_5_ID) .queryId(QUERY_2_ID) .database(null) /* DATABASE_2 */ @@ -6488,7 +6385,7 @@ public abstract class BaseTest { .status(IDENTIFIER_5_STATUS_TYPE) .build(); - public static final IdentifierDto IDENTIFIER_5_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_5_DTO = IdentifierDto.builder() .id(IDENTIFIER_5_ID) .databaseId(DATABASE_2_ID) .queryId(QUERY_2_ID) @@ -6496,6 +6393,7 @@ public abstract class BaseTest { .self("/api/identifier/" + IDENTIFIER_5_ID) .selfHtml("/pid/" + IDENTIFIER_5_ID) .data("/api/database/" + DATABASE_2_ID + "/subset/" + QUERY_2_ID + "/data") + .dashboardHtml("/d/" + DATABASE_2_DASHBOARD_UID) .build()) .descriptions(new LinkedList<>(List.of(IDENTIFIER_5_DESCRIPTION_1_DTO))) .titles(new LinkedList<>(List.of(IDENTIFIER_5_TITLE_1_DTO))) @@ -6516,7 +6414,7 @@ public abstract class BaseTest { .creators(new LinkedList<>(List.of(IDENTIFIER_5_CREATOR_1_DTO, IDENTIFIER_5_CREATOR_2_DTO))) .build(); - public static final IdentifierBriefDto IDENTIFIER_5_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_5_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_5_ID) .databaseId(DATABASE_2_ID) .queryId(QUERY_2_ID) @@ -6527,14 +6425,14 @@ public abstract class BaseTest { .type(IDENTIFIER_5_TYPE_DTO) .build(); - public static final UUID RELATED_IDENTIFIER_5_ID = UUID.fromString("26545877-574d-44fa-819d-d9d9a9750b38"); - public static final String RELATED_IDENTIFIER_5_VALUE = "10.5281/zenodo.6637333"; - public static final RelatedType RELATED_IDENTIFIER_5_TYPE = RelatedType.DOI; - public static final RelatedTypeDto RELATED_IDENTIFIER_5_TYPE_DTO = RelatedTypeDto.DOI; - public static final RelationType RELATED_IDENTIFIER_5_RELATION_TYPE = RelationType.CITES; - public static final RelationTypeDto RELATED_IDENTIFIER_5_RELATION_TYPE_DTO = RelationTypeDto.CITES; + public final static UUID RELATED_IDENTIFIER_5_ID = UUID.fromString("26545877-574d-44fa-819d-d9d9a9750b38"); + public final static String RELATED_IDENTIFIER_5_VALUE = "10.5281/zenodo.6637333"; + public final RelatedType RELATED_IDENTIFIER_5_TYPE = RelatedType.DOI; + public final RelatedTypeDto RELATED_IDENTIFIER_5_TYPE_DTO = RelatedTypeDto.DOI; + public final RelationType RELATED_IDENTIFIER_5_RELATION_TYPE = RelationType.CITES; + public final RelationTypeDto RELATED_IDENTIFIER_5_RELATION_TYPE_DTO = RelationTypeDto.CITES; - public static final RelatedIdentifier IDENTIFIER_1_RELATED_IDENTIFIER_1 = RelatedIdentifier.builder() + public final RelatedIdentifier IDENTIFIER_1_RELATED_IDENTIFIER_1 = RelatedIdentifier.builder() .id(RELATED_IDENTIFIER_5_ID) .identifier(IDENTIFIER_5) .type(RELATED_IDENTIFIER_5_TYPE) @@ -6542,19 +6440,19 @@ public abstract class BaseTest { .value(RELATED_IDENTIFIER_5_VALUE) .build(); - public static final SaveRelatedIdentifierDto IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO = SaveRelatedIdentifierDto.builder() + public final SaveRelatedIdentifierDto IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO = SaveRelatedIdentifierDto.builder() .value(RELATED_IDENTIFIER_5_VALUE) .type(RELATED_IDENTIFIER_5_TYPE_DTO) .relation(RELATED_IDENTIFIER_5_RELATION_TYPE_DTO) .build(); - public static final CreateIdentifierDto IDENTIFIER_5_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_5_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_2_ID) .publicationYear(IDENTIFIER_5_PUBLICATION_YEAR) .publisher(IDENTIFIER_5_PUBLISHER) .build(); - public static final IdentifierSaveDto IDENTIFIER_5_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_5_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_5_ID) .queryId(QUERY_2_ID) .databaseId(DATABASE_2_ID) @@ -6570,87 +6468,87 @@ public abstract class BaseTest { .type(IDENTIFIER_5_TYPE_DTO) .build(); - public static final UUID IDENTIFIER_6_ID = UUID.fromString("a244204d-9671-42a0-be07-9b14402238fd"); - public static final String IDENTIFIER_6_DOI = null; - public static final Instant IDENTIFIER_6_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant IDENTIFIER_6_MODIFIED = Instant.ofEpochSecond(1541588352L); - public static final Instant IDENTIFIER_6_EXECUTION = Instant.ofEpochSecond(1541588352L); - public static final Integer IDENTIFIER_6_PUBLICATION_DAY = 14; - public static final Integer IDENTIFIER_6_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_6_PUBLICATION_YEAR = 2022; - public static final String IDENTIFIER_6_QUERY_HASH = QUERY_3_QUERY_HASH; - public static final String IDENTIFIER_6_RESULT_HASH = QUERY_3_RESULT_HASH; - public static final String IDENTIFIER_6_QUERY = QUERY_3_STATEMENT; - public static final String IDENTIFIER_6_NORMALIZED = QUERY_3_STATEMENT; - public static final Long IDENTIFIER_6_RESULT_NUMBER = QUERY_3_RESULT_NUMBER; - public static final String IDENTIFIER_6_PUBLISHER = "Norwegian Government"; - public static final IdentifierType IDENTIFIER_6_TYPE = IdentifierType.SUBSET; - public static final IdentifierTypeDto IDENTIFIER_6_TYPE_DTO = IdentifierTypeDto.SUBSET; - public static final IdentifierStatusType IDENTIFIER_6_STATUS_TYPE = IdentifierStatusType.PUBLISHED; - public static final IdentifierStatusTypeDto IDENTIFIER_6_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; - - public static final UUID IDENTIFIER_6_TITLE_1_ID = UUID.fromString("0449011c-1490-4c8e-b46c-c1f862126aea"); - public static final String IDENTIFIER_6_TITLE_1_TITLE = "Norwegian weather data"; - public static final String IDENTIFIER_6_TITLE_1_TITLE_MODIFY = "Norwegian weather some data"; - public static final LanguageType IDENTIFIER_6_TITLE_1_LANG = LanguageType.EN; - public static final LanguageTypeDto IDENTIFIER_6_TITLE_1_LANG_DTO = LanguageTypeDto.EN; - - public static final IdentifierTitle IDENTIFIER_6_TITLE_1 = IdentifierTitle.builder() + public final static UUID IDENTIFIER_6_ID = UUID.fromString("a244204d-9671-42a0-be07-9b14402238fd"); + public final static String IDENTIFIER_6_DOI = null; + public final static Instant IDENTIFIER_6_CREATED = Instant.ofEpochSecond(1641588352L); + public final static Instant IDENTIFIER_6_MODIFIED = Instant.ofEpochSecond(1541588352L); + public final static Instant IDENTIFIER_6_EXECUTION = Instant.ofEpochSecond(1541588352L); + public final static Integer IDENTIFIER_6_PUBLICATION_DAY = 14; + public final static Integer IDENTIFIER_6_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_6_PUBLICATION_YEAR = 2022; + public final static String IDENTIFIER_6_QUERY_HASH = QUERY_3_QUERY_HASH; + public final static String IDENTIFIER_6_RESULT_HASH = QUERY_3_RESULT_HASH; + public final static String IDENTIFIER_6_QUERY = QUERY_3_STATEMENT; + public final static String IDENTIFIER_6_NORMALIZED = QUERY_3_STATEMENT; + public final static Long IDENTIFIER_6_RESULT_NUMBER = QUERY_3_RESULT_NUMBER; + public final static String IDENTIFIER_6_PUBLISHER = "Norwegian Government"; + public final static IdentifierType IDENTIFIER_6_TYPE = IdentifierType.SUBSET; + public final static IdentifierTypeDto IDENTIFIER_6_TYPE_DTO = IdentifierTypeDto.SUBSET; + public final static IdentifierStatusType IDENTIFIER_6_STATUS_TYPE = IdentifierStatusType.PUBLISHED; + public final static IdentifierStatusTypeDto IDENTIFIER_6_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; + + public final static UUID IDENTIFIER_6_TITLE_1_ID = UUID.fromString("0449011c-1490-4c8e-b46c-c1f862126aea"); + public final static String IDENTIFIER_6_TITLE_1_TITLE = "Norwegian weather data"; + public final static String IDENTIFIER_6_TITLE_1_TITLE_MODIFY = "Norwegian weather some data"; + public final static LanguageType IDENTIFIER_6_TITLE_1_LANG = LanguageType.EN; + public final static LanguageTypeDto IDENTIFIER_6_TITLE_1_LANG_DTO = LanguageTypeDto.EN; + + public final IdentifierTitle IDENTIFIER_6_TITLE_1 = IdentifierTitle.builder() .id(IDENTIFIER_6_TITLE_1_ID) .title(IDENTIFIER_6_TITLE_1_TITLE) .language(IDENTIFIER_6_TITLE_1_LANG) .build(); - public static final IdentifierTitleDto IDENTIFIER_6_TITLE_1_DTO = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_6_TITLE_1_DTO = IdentifierTitleDto.builder() .id(IDENTIFIER_6_TITLE_1_ID) .title(IDENTIFIER_6_TITLE_1_TITLE) .language(IDENTIFIER_6_TITLE_1_LANG_DTO) .build(); - public static final IdentifierTitleDto IDENTIFIER_6_TITLE_1_DTO_MODIFY = IdentifierTitleDto.builder() + public final IdentifierTitleDto IDENTIFIER_6_TITLE_1_DTO_MODIFY = IdentifierTitleDto.builder() .id(IDENTIFIER_6_TITLE_1_ID) .title(IDENTIFIER_6_TITLE_1_TITLE_MODIFY) .language(IDENTIFIER_6_TITLE_1_LANG_DTO) .build(); - public static final SaveIdentifierTitleDto IDENTIFIER_6_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() + public final SaveIdentifierTitleDto IDENTIFIER_6_TITLE_1_CREATE_DTO = SaveIdentifierTitleDto.builder() .title(IDENTIFIER_6_TITLE_1_TITLE_MODIFY) .language(IDENTIFIER_6_TITLE_1_LANG_DTO) .build(); - public static final UUID IDENTIFIER_6_DESCRIPTION_1_ID = UUID.fromString("aac03bbd-27e6-419d-8118-f996d594f00f"); - public static final String IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION = "Selecting all from the weather Norwegian table"; - public static final String IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION_MODIFY = "Selecting some from the weather Norwegian table"; - public static final LanguageType IDENTIFIER_6_DESCRIPTION_1_LANG = LanguageType.EN; - public static final LanguageTypeDto IDENTIFIER_6_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.EN; + public final static UUID IDENTIFIER_6_DESCRIPTION_1_ID = UUID.fromString("aac03bbd-27e6-419d-8118-f996d594f00f"); + public final static String IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION = "Selecting all from the weather Norwegian table"; + public final static String IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION_MODIFY = "Selecting some from the weather Norwegian table"; + public final static LanguageType IDENTIFIER_6_DESCRIPTION_1_LANG = LanguageType.EN; + public final static LanguageTypeDto IDENTIFIER_6_DESCRIPTION_1_LANG_DTO = LanguageTypeDto.EN; - public static final IdentifierDescription IDENTIFIER_6_DESCRIPTION_1 = IdentifierDescription.builder() + public final IdentifierDescription IDENTIFIER_6_DESCRIPTION_1 = IdentifierDescription.builder() .id(IDENTIFIER_6_DESCRIPTION_1_ID) .description(IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_6_DESCRIPTION_1_LANG) .build(); - public static final IdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() + public final IdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_DTO = IdentifierDescriptionDto.builder() .id(IDENTIFIER_6_DESCRIPTION_1_ID) .description(IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_6_DESCRIPTION_1_LANG_DTO) .build(); - public static final IdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_DTO_MODIFY = IdentifierDescriptionDto.builder() + public final IdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_DTO_MODIFY = IdentifierDescriptionDto.builder() .id(IDENTIFIER_6_DESCRIPTION_1_ID) .description(IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION_MODIFY) .language(IDENTIFIER_6_DESCRIPTION_1_LANG_DTO) .build(); - public static final SaveIdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() + public final SaveIdentifierDescriptionDto IDENTIFIER_6_DESCRIPTION_1_CREATE_DTO = SaveIdentifierDescriptionDto.builder() .id(null) .description(IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION_MODIFY) .language(IDENTIFIER_6_DESCRIPTION_1_LANG_DTO) .build(); - private final static UUID IDENTIFIER_6_CREATOR_1_ID = UUID.fromString("f8a52dca-8aec-46c1-b0e1-603dbe6a1a65"); + public final static UUID IDENTIFIER_6_CREATOR_1_ID = UUID.fromString("f8a52dca-8aec-46c1-b0e1-603dbe6a1a65"); - public static final Creator IDENTIFIER_6_CREATOR_1 = Creator.builder() + public final Creator IDENTIFIER_6_CREATOR_1 = Creator.builder() .id(IDENTIFIER_6_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6663,7 +6561,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final CreatorDto IDENTIFIER_6_CREATOR_1_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_6_CREATOR_1_DTO = CreatorDto.builder() .id(IDENTIFIER_6_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6676,7 +6574,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_6_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_6_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) .creatorName(CREATOR_1_NAME) @@ -6687,7 +6585,7 @@ public abstract class BaseTest { .affiliationIdentifierScheme(CREATOR_1_AFFIL_TYPE_DTO) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_6_CREATOR_1_MODIFY_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_6_CREATOR_1_MODIFY_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) .creatorName(CREATOR_1_NAME) @@ -6698,9 +6596,9 @@ public abstract class BaseTest { .affiliationIdentifierScheme(CREATOR_1_AFFIL_TYPE_DTO) .build(); - private final static UUID IDENTIFIER_6_CREATOR_2_ID = UUID.fromString("eeae78cb-75a1-42e2-b608-7082e5fbecc6"); + public final static UUID IDENTIFIER_6_CREATOR_2_ID = UUID.fromString("eeae78cb-75a1-42e2-b608-7082e5fbecc6"); - public static final Creator IDENTIFIER_6_CREATOR_2 = Creator.builder() + public final Creator IDENTIFIER_6_CREATOR_2 = Creator.builder() .id(IDENTIFIER_6_CREATOR_2_ID) .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) @@ -6710,7 +6608,7 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - public static final CreatorDto IDENTIFIER_6_CREATOR_2_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_6_CREATOR_2_DTO = CreatorDto.builder() .id(IDENTIFIER_6_CREATOR_2_ID) .firstname(CREATOR_2_FIRSTNAME) .lastname(CREATOR_2_LASTNAME) @@ -6720,9 +6618,9 @@ public abstract class BaseTest { .affiliation(CREATOR_2_AFFIL) .build(); - private final static UUID IDENTIFIER_6_CREATOR_3_ID = UUID.fromString("700058f1-6314-4cd1-9c0c-62e75c8f422b"); + public final static UUID IDENTIFIER_6_CREATOR_3_ID = UUID.fromString("700058f1-6314-4cd1-9c0c-62e75c8f422b"); - public static final Creator IDENTIFIER_6_CREATOR_3 = Creator.builder() + public final Creator IDENTIFIER_6_CREATOR_3 = Creator.builder() .id(IDENTIFIER_6_CREATOR_3_ID) .firstname(CREATOR_3_FIRSTNAME) .lastname(CREATOR_3_LASTNAME) @@ -6735,7 +6633,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_3_AFFIL_URI) .build(); - public static final CreatorDto IDENTIFIER_6_CREATOR_3_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_6_CREATOR_3_DTO = CreatorDto.builder() .id(IDENTIFIER_6_CREATOR_3_ID) .firstname(CREATOR_3_FIRSTNAME) .lastname(CREATOR_3_LASTNAME) @@ -6748,7 +6646,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_3_AFFIL_URI) .build(); - public static final Identifier IDENTIFIER_6 = Identifier.builder() + public final Identifier IDENTIFIER_6 = Identifier.builder() .id(IDENTIFIER_6_ID) .queryId(QUERY_3_ID) .descriptions(new LinkedList<>(List.of(IDENTIFIER_6_DESCRIPTION_1))) @@ -6774,7 +6672,7 @@ public abstract class BaseTest { .status(IDENTIFIER_6_STATUS_TYPE) .build(); - public static final IdentifierDto IDENTIFIER_6_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_6_DTO = IdentifierDto.builder() .id(IDENTIFIER_6_ID) .databaseId(DATABASE_3_ID) .queryId(QUERY_3_ID) @@ -6782,6 +6680,7 @@ public abstract class BaseTest { .self("/api/identifier/" + IDENTIFIER_6_ID) .selfHtml("/pid/" + IDENTIFIER_6_ID) .data("/api/database/" + DATABASE_3_ID + "/subset/" + QUERY_3_ID + "/data") + .dashboardHtml("/d/" + DATABASE_3_DASHBOARD_UID) .build()) .descriptions(new LinkedList<>(List.of(IDENTIFIER_6_DESCRIPTION_1_DTO))) .titles(new LinkedList<>(List.of(IDENTIFIER_6_TITLE_1_DTO))) @@ -6804,7 +6703,7 @@ public abstract class BaseTest { .build(); - public static final IdentifierBriefDto IDENTIFIER_6_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_6_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_6_ID) .databaseId(DATABASE_3_ID) .queryId(QUERY_3_ID) @@ -6816,13 +6715,13 @@ public abstract class BaseTest { .status(IDENTIFIER_6_STATUS_TYPE_DTO) .build(); - public static final CreateIdentifierDto IDENTIFIER_6_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_6_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_3_ID) .publicationYear(IDENTIFIER_6_PUBLICATION_YEAR) .publisher(IDENTIFIER_6_PUBLISHER) .build(); - public static final IdentifierSaveDto IDENTIFIER_6_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_6_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_6_ID) .databaseId(DATABASE_3_ID) .queryId(QUERY_3_ID) @@ -6837,22 +6736,22 @@ public abstract class BaseTest { .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .build(); - public static final UUID IDENTIFIER_7_ID = UUID.fromString("b216ae00-a31d-4ecb-95fb-37eb4da3946f"); - public static final String IDENTIFIER_7_DOI = null; - public static final Instant IDENTIFIER_7_CREATED = Instant.ofEpochSecond(1641588352L); - public static final Instant IDENTIFIER_7_MODIFIED = Instant.ofEpochSecond(1541588352L); - public static final Instant IDENTIFIER_7_EXECUTION = Instant.ofEpochSecond(1541588352L); - public static final Integer IDENTIFIER_7_PUBLICATION_DAY = 14; - public static final Integer IDENTIFIER_7_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_7_PUBLICATION_YEAR = 2022; - public static final Long IDENTIFIER_7_RESULT_NUMBER = 2L; - public static final String IDENTIFIER_7_PUBLISHER = "Swedish Government"; - public static final IdentifierType IDENTIFIER_7_TYPE = IdentifierType.DATABASE; - public static final IdentifierTypeDto IDENTIFIER_7_TYPE_DTO = IdentifierTypeDto.DATABASE; - public static final IdentifierStatusType IDENTIFIER_7_STATUS_TYPE = IdentifierStatusType.DRAFT; - public static final IdentifierStatusTypeDto IDENTIFIER_7_STATUS_TYPE_DTO = IdentifierStatusTypeDto.DRAFT; - - public static final DataCiteBody<DataCiteDoi> IDENTIFIER_7_DATA_CITE = DataCiteBody.<DataCiteDoi>builder() + public final static UUID IDENTIFIER_7_ID = UUID.fromString("b216ae00-a31d-4ecb-95fb-37eb4da3946f"); + public final static String IDENTIFIER_7_DOI = null; + public final static Instant IDENTIFIER_7_CREATED = Instant.ofEpochSecond(1641588352L); + public final static Instant IDENTIFIER_7_MODIFIED = Instant.ofEpochSecond(1541588352L); + public final static Instant IDENTIFIER_7_EXECUTION = Instant.ofEpochSecond(1541588352L); + public final static Integer IDENTIFIER_7_PUBLICATION_DAY = 14; + public final static Integer IDENTIFIER_7_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_7_PUBLICATION_YEAR = 2022; + public final static Long IDENTIFIER_7_RESULT_NUMBER = 2L; + public final static String IDENTIFIER_7_PUBLISHER = "Swedish Government"; + public final static IdentifierType IDENTIFIER_7_TYPE = IdentifierType.DATABASE; + public final static IdentifierTypeDto IDENTIFIER_7_TYPE_DTO = IdentifierTypeDto.DATABASE; + public final static IdentifierStatusType IDENTIFIER_7_STATUS_TYPE = IdentifierStatusType.DRAFT; + public final static IdentifierStatusTypeDto IDENTIFIER_7_STATUS_TYPE_DTO = IdentifierStatusTypeDto.DRAFT; + + public final DataCiteBody<DataCiteDoi> IDENTIFIER_7_DATA_CITE = DataCiteBody.<DataCiteDoi>builder() .data(DataCiteData.<DataCiteDoi>builder() .type("dois") .attributes(DataCiteDoi.builder() @@ -6861,9 +6760,9 @@ public abstract class BaseTest { .build()) .build(); - private final static UUID IDENTIFIER_7_CREATOR_1_ID = UUID.fromString("b899c367-06c7-4f47-8aea-5f15061ee3ee"); + public final static UUID IDENTIFIER_7_CREATOR_1_ID = UUID.fromString("b899c367-06c7-4f47-8aea-5f15061ee3ee"); - public static final Creator IDENTIFIER_7_CREATOR_1 = Creator.builder() + public final Creator IDENTIFIER_7_CREATOR_1 = Creator.builder() .id(IDENTIFIER_7_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6876,7 +6775,7 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final CreatorDto IDENTIFIER_7_CREATOR_1_DTO = CreatorDto.builder() + public final CreatorDto IDENTIFIER_7_CREATOR_1_DTO = CreatorDto.builder() .id(IDENTIFIER_7_CREATOR_1_ID) .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) @@ -6889,12 +6788,13 @@ public abstract class BaseTest { .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); - public static final IdentifierDto IDENTIFIER_7_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_7_DTO = IdentifierDto.builder() .id(IDENTIFIER_7_ID) .databaseId(DATABASE_4_ID) .links(LinksDto.builder() .self("/api/identifier/" + IDENTIFIER_7_ID) .selfHtml("/pid/" + IDENTIFIER_7_ID) + .dashboardHtml("/d/" + DATABASE_4_DASHBOARD_UID) .build()) .descriptions(new LinkedList<>()) .titles(new LinkedList<>()) @@ -6914,7 +6814,7 @@ public abstract class BaseTest { .status(IDENTIFIER_7_STATUS_TYPE_DTO) .build(); - public static final SaveIdentifierCreatorDto IDENTIFIER_7_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() + public final SaveIdentifierCreatorDto IDENTIFIER_7_CREATOR_1_CREATE_DTO = SaveIdentifierCreatorDto.builder() .firstname(CREATOR_1_FIRSTNAME) .lastname(CREATOR_1_LASTNAME) .creatorName(CREATOR_1_NAME) @@ -6924,13 +6824,13 @@ public abstract class BaseTest { .affiliationIdentifier(CREATOR_1_AFFIL_ROR) .build(); - public static final CreateIdentifierDto IDENTIFIER_7_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_7_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_4_ID) .publicationYear(IDENTIFIER_7_PUBLICATION_YEAR) .publisher(IDENTIFIER_7_PUBLISHER) .build(); - public static final IdentifierSaveDto IDENTIFIER_7_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_7_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_7_ID) .databaseId(DATABASE_4_ID) .descriptions(new LinkedList<>()) @@ -6945,27 +6845,26 @@ public abstract class BaseTest { .type(IDENTIFIER_7_TYPE_DTO) .build(); - public static final UUID IDENTIFIER_2_ID = UUID.fromString("fdb95f60-48e7-4e74-8122-d3c8d079c889"); - public static final String IDENTIFIER_2_DOI = null; - public static final Instant IDENTIFIER_2_CREATED = Instant.ofEpochSecond(1651588352L); - public static final Instant IDENTIFIER_2_MODIFIED = Instant.ofEpochSecond(1551588352L); - public static final Instant IDENTIFIER_2_EXECUTION = Instant.ofEpochSecond(1551588352L); - public static final Integer IDENTIFIER_2_PUBLICATION_DAY = 10; - public static final Integer IDENTIFIER_2_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_2_PUBLICATION_YEAR = 2023; - public static final String IDENTIFIER_2_QUERY_HASH = QUERY_1_QUERY_HASH; - public static final String IDENTIFIER_2_RESULT_HASH = QUERY_1_RESULT_HASH; - public static final String IDENTIFIER_2_QUERY = QUERY_1_STATEMENT; - public static final String IDENTIFIER_2_NORMALIZED = QUERY_1_STATEMENT; - public static final Long IDENTIFIER_2_RESULT_NUMBER = QUERY_1_RESULT_NUMBER; - public static final String IDENTIFIER_2_PUBLISHER = "Swedish Government"; - public static final IdentifierType IDENTIFIER_2_TYPE = IdentifierType.SUBSET; - public static final IdentifierTypeDto IDENTIFIER_2_TYPE_DTO = IdentifierTypeDto.SUBSET; - public static final IdentifierStatusType IDENTIFIER_2_STATUS_TYPE = IdentifierStatusType.PUBLISHED; - public static final IdentifierStatusTypeDto IDENTIFIER_2_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; - public static final UUID IDENTIFIER_2_CREATED_BY = USER_1_ID; - - public static final CreateIdentifierDto IDENTIFIER_2_CREATE_DTO = CreateIdentifierDto.builder() + public final static UUID IDENTIFIER_2_ID = UUID.fromString("fdb95f60-48e7-4e74-8122-d3c8d079c889"); + public final static String IDENTIFIER_2_DOI = null; + public final static Instant IDENTIFIER_2_CREATED = Instant.ofEpochSecond(1651588352L); + public final static Instant IDENTIFIER_2_MODIFIED = Instant.ofEpochSecond(1551588352L); + public final static Instant IDENTIFIER_2_EXECUTION = Instant.ofEpochSecond(1551588352L); + public final static Integer IDENTIFIER_2_PUBLICATION_DAY = 10; + public final static Integer IDENTIFIER_2_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_2_PUBLICATION_YEAR = 2023; + public final static String IDENTIFIER_2_QUERY_HASH = QUERY_1_QUERY_HASH; + public final static String IDENTIFIER_2_RESULT_HASH = QUERY_1_RESULT_HASH; + public final static String IDENTIFIER_2_QUERY = QUERY_1_STATEMENT; + public final static String IDENTIFIER_2_NORMALIZED = QUERY_1_STATEMENT; + public final static Long IDENTIFIER_2_RESULT_NUMBER = QUERY_1_RESULT_NUMBER; + public final static String IDENTIFIER_2_PUBLISHER = "Swedish Government"; + public final static IdentifierType IDENTIFIER_2_TYPE = IdentifierType.SUBSET; + public final static IdentifierTypeDto IDENTIFIER_2_TYPE_DTO = IdentifierTypeDto.SUBSET; + public final static IdentifierStatusType IDENTIFIER_2_STATUS_TYPE = IdentifierStatusType.PUBLISHED; + public final static IdentifierStatusTypeDto IDENTIFIER_2_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; + + public final CreateIdentifierDto IDENTIFIER_2_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_1_ID) .queryId(QUERY_1_ID) .type(IDENTIFIER_2_TYPE_DTO) @@ -6973,7 +6872,7 @@ public abstract class BaseTest { .publisher(IDENTIFIER_2_PUBLISHER) .build(); - public static final Identifier IDENTIFIER_2 = Identifier.builder() + public final Identifier IDENTIFIER_2 = Identifier.builder() .id(IDENTIFIER_2_ID) .queryId(QUERY_1_ID) .descriptions(new LinkedList<>()) @@ -7000,7 +6899,7 @@ public abstract class BaseTest { .status(IDENTIFIER_2_STATUS_TYPE) .build(); - public static final IdentifierDto IDENTIFIER_2_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_2_DTO = IdentifierDto.builder() .id(IDENTIFIER_2_ID) .queryId(QUERY_1_ID) .databaseId(DATABASE_1_ID) @@ -7029,7 +6928,7 @@ public abstract class BaseTest { .status(IDENTIFIER_2_STATUS_TYPE_DTO) .build(); - public static final IdentifierBriefDto IDENTIFIER_2_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_2_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_2_ID) .queryId(QUERY_1_ID) .databaseId(DATABASE_1_ID) @@ -7041,7 +6940,7 @@ public abstract class BaseTest { .status(IDENTIFIER_2_STATUS_TYPE_DTO) .build(); - public static final IdentifierSaveDto IDENTIFIER_2_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_2_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_2_ID) .databaseId(DATABASE_1_ID) .queryId(QUERY_1_ID) @@ -7057,27 +6956,26 @@ public abstract class BaseTest { .queryId(QUERY_1_ID) .build(); - public static final UUID IDENTIFIER_3_ID = UUID.fromString("e2d831c2-3694-4fdc-8c48-7a7e94b73c43"); - public static final String IDENTIFIER_3_DOI = null; - public static final Instant IDENTIFIER_3_CREATED = Instant.ofEpochSecond(1651588352L); - public static final Instant IDENTIFIER_3_MODIFIED = Instant.ofEpochSecond(1551588352L); - public static final Instant IDENTIFIER_3_EXECUTION = Instant.ofEpochSecond(1551588352L); - public static final Integer IDENTIFIER_3_PUBLICATION_DAY = 10; - public static final Integer IDENTIFIER_3_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_3_PUBLICATION_YEAR = 2023; - public static final String IDENTIFIER_3_QUERY_HASH = VIEW_1_QUERY_HASH; - public static final String IDENTIFIER_3_RESULT_HASH = null; - public static final String IDENTIFIER_3_QUERY = VIEW_1_QUERY; - public static final String IDENTIFIER_3_NORMALIZED = VIEW_1_QUERY; - public static final Long IDENTIFIER_3_RESULT_NUMBER = null; - public static final String IDENTIFIER_3_PUBLISHER = "Polish Government"; - public static final IdentifierType IDENTIFIER_3_TYPE = IdentifierType.VIEW; - public static final IdentifierTypeDto IDENTIFIER_3_TYPE_DTO = IdentifierTypeDto.VIEW; - public static final IdentifierStatusType IDENTIFIER_3_STATUS_TYPE = IdentifierStatusType.PUBLISHED; - public static final IdentifierStatusTypeDto IDENTIFIER_3_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; - public static final UUID IDENTIFIER_3_CREATED_BY = USER_1_ID; - - public static final Identifier IDENTIFIER_3 = Identifier.builder() + public final static UUID IDENTIFIER_3_ID = UUID.fromString("e2d831c2-3694-4fdc-8c48-7a7e94b73c43"); + public final static String IDENTIFIER_3_DOI = null; + public final static Instant IDENTIFIER_3_CREATED = Instant.ofEpochSecond(1651588352L); + public final static Instant IDENTIFIER_3_MODIFIED = Instant.ofEpochSecond(1551588352L); + public final static Instant IDENTIFIER_3_EXECUTION = Instant.ofEpochSecond(1551588352L); + public final static Integer IDENTIFIER_3_PUBLICATION_DAY = 10; + public final static Integer IDENTIFIER_3_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_3_PUBLICATION_YEAR = 2023; + public final static String IDENTIFIER_3_QUERY_HASH = VIEW_1_QUERY_HASH; + public final static String IDENTIFIER_3_RESULT_HASH = null; + public final static String IDENTIFIER_3_QUERY = VIEW_1_QUERY; + public final static String IDENTIFIER_3_NORMALIZED = VIEW_1_QUERY; + public final static Long IDENTIFIER_3_RESULT_NUMBER = null; + public final static String IDENTIFIER_3_PUBLISHER = "Polish Government"; + public final static IdentifierType IDENTIFIER_3_TYPE = IdentifierType.VIEW; + public final static IdentifierTypeDto IDENTIFIER_3_TYPE_DTO = IdentifierTypeDto.VIEW; + public final static IdentifierStatusType IDENTIFIER_3_STATUS_TYPE = IdentifierStatusType.PUBLISHED; + public final static IdentifierStatusTypeDto IDENTIFIER_3_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; + + public final Identifier IDENTIFIER_3 = Identifier.builder() .id(IDENTIFIER_3_ID) .viewId(VIEW_1_ID) .descriptions(new LinkedList<>()) @@ -7104,7 +7002,7 @@ public abstract class BaseTest { .status(IDENTIFIER_3_STATUS_TYPE) .build(); - public static final IdentifierDto IDENTIFIER_3_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_3_DTO = IdentifierDto.builder() .id(IDENTIFIER_3_ID) .databaseId(DATABASE_1_ID) .viewId(VIEW_1_ID) @@ -7133,7 +7031,7 @@ public abstract class BaseTest { .status(IDENTIFIER_3_STATUS_TYPE_DTO) .build(); - public static final IdentifierBriefDto IDENTIFIER_3_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_3_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_3_ID) .databaseId(DATABASE_1_ID) .viewId(VIEW_1_ID) @@ -7145,7 +7043,7 @@ public abstract class BaseTest { .status(IDENTIFIER_3_STATUS_TYPE_DTO) .build(); - public static final CreateIdentifierDto IDENTIFIER_3_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_3_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_1_ID) .viewId(VIEW_1_ID) .type(IDENTIFIER_3_TYPE_DTO) @@ -7153,7 +7051,7 @@ public abstract class BaseTest { .publisher(IDENTIFIER_3_PUBLISHER) .build(); - public static final IdentifierSaveDto IDENTIFIER_3_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_3_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_3_ID) .databaseId(DATABASE_1_ID) .viewId(VIEW_1_ID) @@ -7168,24 +7066,23 @@ public abstract class BaseTest { .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .build(); - public static final UUID IDENTIFIER_4_ID = UUID.fromString("3bd69bb8-f7e3-48e4-9717-823787e7ba23"); - public static final String IDENTIFIER_4_DOI = null; - public static final Instant IDENTIFIER_4_CREATED = Instant.ofEpochSecond(1751588352L); - public static final Instant IDENTIFIER_4_MODIFIED = Instant.ofEpochSecond(1551588352L); - public static final Instant IDENTIFIER_4_EXECUTION = Instant.ofEpochSecond(1551588352L); - public static final Integer IDENTIFIER_4_PUBLICATION_DAY = 10; - public static final Integer IDENTIFIER_4_PUBLICATION_MONTH = 7; - public static final Integer IDENTIFIER_4_PUBLICATION_YEAR = 2023; - public static final String IDENTIFIER_4_RESULT_HASH = null; - public static final Long IDENTIFIER_4_RESULT_NUMBER = null; - public static final String IDENTIFIER_4_PUBLISHER = "Example Publisher"; - public static final IdentifierType IDENTIFIER_4_TYPE = IdentifierType.TABLE; - public static final IdentifierTypeDto IDENTIFIER_4_TYPE_DTO = IdentifierTypeDto.TABLE; - public static final IdentifierStatusType IDENTIFIER_4_STATUS_TYPE = IdentifierStatusType.PUBLISHED; - public static final IdentifierStatusTypeDto IDENTIFIER_4_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; - public static final UUID IDENTIFIER_4_CREATED_BY = USER_1_ID; - - public static final Identifier IDENTIFIER_4 = Identifier.builder() + public final static UUID IDENTIFIER_4_ID = UUID.fromString("3bd69bb8-f7e3-48e4-9717-823787e7ba23"); + public final static String IDENTIFIER_4_DOI = null; + public final static Instant IDENTIFIER_4_CREATED = Instant.ofEpochSecond(1751588352L); + public final static Instant IDENTIFIER_4_MODIFIED = Instant.ofEpochSecond(1551588352L); + public final static Instant IDENTIFIER_4_EXECUTION = Instant.ofEpochSecond(1551588352L); + public final static Integer IDENTIFIER_4_PUBLICATION_DAY = 10; + public final static Integer IDENTIFIER_4_PUBLICATION_MONTH = 7; + public final static Integer IDENTIFIER_4_PUBLICATION_YEAR = 2023; + public final static String IDENTIFIER_4_RESULT_HASH = null; + public final static Long IDENTIFIER_4_RESULT_NUMBER = null; + public final static String IDENTIFIER_4_PUBLISHER = "Example Publisher"; + public final static IdentifierType IDENTIFIER_4_TYPE = IdentifierType.TABLE; + public final static IdentifierTypeDto IDENTIFIER_4_TYPE_DTO = IdentifierTypeDto.TABLE; + public final static IdentifierStatusType IDENTIFIER_4_STATUS_TYPE = IdentifierStatusType.PUBLISHED; + public final static IdentifierStatusTypeDto IDENTIFIER_4_STATUS_TYPE_DTO = IdentifierStatusTypeDto.PUBLISHED; + + public final Identifier IDENTIFIER_4 = Identifier.builder() .id(IDENTIFIER_4_ID) .tableId(TABLE_1_ID) .descriptions(new LinkedList<>()) @@ -7209,7 +7106,7 @@ public abstract class BaseTest { .status(IDENTIFIER_4_STATUS_TYPE) .build(); - public static final IdentifierDto IDENTIFIER_4_DTO = IdentifierDto.builder() + public final IdentifierDto IDENTIFIER_4_DTO = IdentifierDto.builder() .id(IDENTIFIER_4_ID) .databaseId(DATABASE_1_ID) .tableId(TABLE_1_ID) @@ -7235,7 +7132,7 @@ public abstract class BaseTest { .status(IDENTIFIER_4_STATUS_TYPE_DTO) .build(); - public static final IdentifierBriefDto IDENTIFIER_4_BRIEF_DTO = IdentifierBriefDto.builder() + public final IdentifierBriefDto IDENTIFIER_4_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_4_ID) .databaseId(DATABASE_1_ID) .tableId(TABLE_1_ID) @@ -7247,13 +7144,13 @@ public abstract class BaseTest { .status(IDENTIFIER_4_STATUS_TYPE_DTO) .build(); - public static final CreateIdentifierDto IDENTIFIER_4_CREATE_DTO = CreateIdentifierDto.builder() + public final CreateIdentifierDto IDENTIFIER_4_CREATE_DTO = CreateIdentifierDto.builder() .databaseId(DATABASE_1_ID) .publicationYear(IDENTIFIER_4_PUBLICATION_YEAR) .publisher(IDENTIFIER_4_PUBLISHER) .build(); - public static final IdentifierSaveDto IDENTIFIER_4_SAVE_DTO = IdentifierSaveDto.builder() + public final IdentifierSaveDto IDENTIFIER_4_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_4_ID) .databaseId(DATABASE_1_ID) .tableId(TABLE_1_ID) @@ -7268,36 +7165,36 @@ public abstract class BaseTest { .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .build(); - public static final String VIRTUAL_HOST_NAME = "fda"; - public static final String VIRTUAL_HOST_DESCRIPTION = "FAIR Data Austria"; - public static final String VIRTUAL_HOST_TAGS = ""; + public final static String VIRTUAL_HOST_NAME = "fda"; + public final static String VIRTUAL_HOST_DESCRIPTION = "FAIR Data Austria"; + public final static String VIRTUAL_HOST_TAGS = ""; - public static final CreateVirtualHostDto VIRTUAL_HOST_CREATE_DTO = CreateVirtualHostDto.builder() + public final CreateVirtualHostDto VIRTUAL_HOST_CREATE_DTO = CreateVirtualHostDto.builder() .name(VIRTUAL_HOST_NAME) .description(VIRTUAL_HOST_DESCRIPTION) .tags(VIRTUAL_HOST_TAGS) .build(); - public static final ExchangeUpdatePermissionsDto VIRTUAL_HOST_EXCHANGE_UPDATE_DTO = ExchangeUpdatePermissionsDto.builder() + public final ExchangeUpdatePermissionsDto VIRTUAL_HOST_EXCHANGE_UPDATE_DTO = ExchangeUpdatePermissionsDto.builder() .exchange(DATABASE_1_EXCHANGE) .read(".*") .write(".*") .build(); - public static final GrantVirtualHostPermissionsDto VIRTUAL_HOST_GRANT_DTO = GrantVirtualHostPermissionsDto.builder() + public final GrantVirtualHostPermissionsDto VIRTUAL_HOST_GRANT_DTO = GrantVirtualHostPermissionsDto.builder() .read(".*") .write(".*") .configure(".*") .build(); - public static final UUID BANNER_MESSAGE_1_ID = UUID.fromString("81cf09b7-0d86-44ad-be8e-a407e7d114e1"); - public static final String BANNER_MESSAGE_1_MESSAGE = "Next maintenance in 7 days!"; - public static final BannerMessageType BANNER_MESSAGE_1_TYPE = BannerMessageType.INFO; - public static final BannerMessageTypeDto BANNER_MESSAGE_1_TYPE_DTO = BannerMessageTypeDto.INFO; - public static final Instant BANNER_MESSAGE_1_START = Instant.ofEpochSecond(1684577786L) /* 2022-12-23 22:00:00 (UTC) */; - public static final Instant BANNER_MESSAGE_1_END = null; + public final static UUID BANNER_MESSAGE_1_ID = UUID.fromString("81cf09b7-0d86-44ad-be8e-a407e7d114e1"); + public final static String BANNER_MESSAGE_1_MESSAGE = "Next maintenance in 7 days!"; + public final static BannerMessageType BANNER_MESSAGE_1_TYPE = BannerMessageType.INFO; + public final static BannerMessageTypeDto BANNER_MESSAGE_1_TYPE_DTO = BannerMessageTypeDto.INFO; + public final static Instant BANNER_MESSAGE_1_START = Instant.ofEpochSecond(1684577786L) /* 2022-12-23 22:00:00 (UTC) */; + public final static Instant BANNER_MESSAGE_1_END = null; - public static final BannerMessage BANNER_MESSAGE_1 = BannerMessage.builder() + public final BannerMessage BANNER_MESSAGE_1 = BannerMessage.builder() .id(BANNER_MESSAGE_1_ID) .message(BANNER_MESSAGE_1_MESSAGE) .type(BANNER_MESSAGE_1_TYPE) @@ -7305,7 +7202,7 @@ public abstract class BaseTest { .displayEnd(BANNER_MESSAGE_1_END) .build(); - public static final BannerMessageDto BANNER_MESSAGE_1_DTO = BannerMessageDto.builder() + public final BannerMessageDto BANNER_MESSAGE_1_DTO = BannerMessageDto.builder() .id(BANNER_MESSAGE_1_ID) .message(BANNER_MESSAGE_1_MESSAGE) .type(BANNER_MESSAGE_1_TYPE_DTO) @@ -7313,28 +7210,28 @@ public abstract class BaseTest { .displayEnd(BANNER_MESSAGE_1_END) .build(); - public static final BannerMessageCreateDto BANNER_MESSAGE_1_CREATE_DTO = BannerMessageCreateDto.builder() + public final BannerMessageCreateDto BANNER_MESSAGE_1_CREATE_DTO = BannerMessageCreateDto.builder() .message(BANNER_MESSAGE_1_MESSAGE) .type(BANNER_MESSAGE_1_TYPE_DTO) .displayStart(BANNER_MESSAGE_1_START) .displayEnd(BANNER_MESSAGE_1_END) .build(); - public static final BannerMessageUpdateDto BANNER_MESSAGE_1_UPDATE_DTO = BannerMessageUpdateDto.builder() + public final BannerMessageUpdateDto BANNER_MESSAGE_1_UPDATE_DTO = BannerMessageUpdateDto.builder() .message(BANNER_MESSAGE_1_MESSAGE) .type(BannerMessageTypeDto.WARNING) .displayStart(BANNER_MESSAGE_1_START) .displayEnd(BANNER_MESSAGE_1_END) .build(); - public static final UUID BANNER_MESSAGE_2_ID = UUID.fromString("1e7e2c03-e2c6-46b8-9fdc-6668ef055d99"); - public static final String BANNER_MESSAGE_2_MESSAGE = "No operation on Christmas 2022!"; - public static final BannerMessageType BANNER_MESSAGE_2_TYPE = BannerMessageType.ERROR; - public static final BannerMessageTypeDto BANNER_MESSAGE_2_TYPE_DTO = BannerMessageTypeDto.ERROR; - public static final Instant BANNER_MESSAGE_2_START = Instant.ofEpochSecond(1671836400L) /* 2022-12-23 22:00:00 (UTC) */; - public static final Instant BANNER_MESSAGE_2_END = Instant.ofEpochSecond(1672009200L) /* 2022-12-25 22:00:00 (UTC) */; + public final static UUID BANNER_MESSAGE_2_ID = UUID.fromString("1e7e2c03-e2c6-46b8-9fdc-6668ef055d99"); + public final static String BANNER_MESSAGE_2_MESSAGE = "No operation on Christmas 2022!"; + public final static BannerMessageType BANNER_MESSAGE_2_TYPE = BannerMessageType.ERROR; + public final static BannerMessageTypeDto BANNER_MESSAGE_2_TYPE_DTO = BannerMessageTypeDto.ERROR; + public final static Instant BANNER_MESSAGE_2_START = Instant.ofEpochSecond(1671836400L) /* 2022-12-23 22:00:00 (UTC) */; + public final static Instant BANNER_MESSAGE_2_END = Instant.ofEpochSecond(1672009200L) /* 2022-12-25 22:00:00 (UTC) */; - public static final BannerMessage BANNER_MESSAGE_2 = BannerMessage.builder() + public final BannerMessage BANNER_MESSAGE_2 = BannerMessage.builder() .id(BANNER_MESSAGE_2_ID) .message(BANNER_MESSAGE_2_MESSAGE) .type(BANNER_MESSAGE_2_TYPE) @@ -7342,29 +7239,31 @@ public abstract class BaseTest { .displayEnd(BANNER_MESSAGE_2_END) .build(); - public static final BannerMessageCreateDto BANNER_MESSAGE_2_CREATE_DTO = BannerMessageCreateDto.builder() + public final BannerMessageCreateDto BANNER_MESSAGE_2_CREATE_DTO = BannerMessageCreateDto.builder() .message(BANNER_MESSAGE_2_MESSAGE) .type(BANNER_MESSAGE_2_TYPE_DTO) .displayStart(BANNER_MESSAGE_2_START) .displayEnd(BANNER_MESSAGE_2_END) .build(); - public static final Database DATABASE_1 = Database.builder() + public final Database DATABASE_1 = Database.builder() .id(DATABASE_1_ID) .created(Instant.now().minus(1, HOURS)) .lastModified(Instant.now()) .isPublic(DATABASE_1_PUBLIC) .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_1_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_1_DASHBOARD_UID) .name(DATABASE_1_NAME) .description(DATABASE_1_DESCRIPTION) .identifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))) .cid(CONTAINER_1_ID) .container(CONTAINER_1) - .internalName(DATABASE_1_INTERNALNAME) + .internalName(DATABASE_1_INTERNAL_NAME) .exchangeName(DATABASE_1_EXCHANGE) .created(DATABASE_1_CREATED) .lastModified(DATABASE_1_LAST_MODIFIED) - .ownedBy(DATABASE_1_CREATED_BY) + .ownedBy(USER_1_ID) .owner(USER_1) .ownedBy(USER_1_ID) .owner(USER_1) @@ -7378,13 +7277,15 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) .build(); - public static final DatabaseDto DATABASE_1_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_1_DTO = DatabaseDto.builder() .id(DATABASE_1_ID) .isPublic(DATABASE_1_PUBLIC) .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_1_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_1_DASHBOARD_UID) .name(DATABASE_1_NAME) .container(CONTAINER_1_DTO) - .internalName(DATABASE_1_INTERNALNAME) + .internalName(DATABASE_1_INTERNAL_NAME) .exchangeName(DATABASE_1_EXCHANGE) .identifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))) .tables(new LinkedList<>(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO))) @@ -7392,13 +7293,13 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final DatabaseDto DATABASE_1_PRIVILEGED_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_1_PRIVILEGED_DTO = DatabaseDto.builder() .id(DATABASE_1_ID) .isPublic(DATABASE_1_PUBLIC) .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) .name(DATABASE_1_NAME) .container(CONTAINER_1_PRIVILEGED_DTO) - .internalName(DATABASE_1_INTERNALNAME) + .internalName(DATABASE_1_INTERNAL_NAME) .exchangeName(DATABASE_1_EXCHANGE) .accesses(new LinkedList<>(List.of())) /* DATABASE_1_USER_1_READ_ACCESS_DTO */ .identifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))) @@ -7408,16 +7309,16 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); - public static final DatabaseBriefDto DATABASE_1_BRIEF_DTO = DatabaseBriefDto.builder() + public final DatabaseBriefDto DATABASE_1_BRIEF_DTO = DatabaseBriefDto.builder() .id(DATABASE_1_ID) .isPublic(DATABASE_1_PUBLIC) .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) .name(DATABASE_1_NAME) - .internalName(DATABASE_1_INTERNALNAME) + .internalName(DATABASE_1_INTERNAL_NAME) .identifiers(new LinkedList<>(List.of(IDENTIFIER_1_BRIEF_DTO, IDENTIFIER_2_BRIEF_DTO, IDENTIFIER_3_BRIEF_DTO, IDENTIFIER_4_BRIEF_DTO))) .build(); - public static final DatabaseAccess DATABASE_1_USER_1_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_1_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7425,14 +7326,14 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_1_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_1_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_1_ID) .huserid(USER_1_ID) .user(USER_1_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_1_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7440,7 +7341,7 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccess DATABASE_1_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7448,7 +7349,7 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccess DATABASE_1_USER_2_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_2_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7456,14 +7357,14 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_2_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_2_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_1_ID) .huserid(USER_2_ID) .user(USER_2_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_1_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7471,14 +7372,14 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_OWN) .hdbid(DATABASE_1_ID) .huserid(USER_2_ID) .user(USER_2_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_1_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7486,14 +7387,14 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_2_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_2_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .hdbid(DATABASE_1_ID) .huserid(USER_2_ID) .user(USER_2_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_1_USER_3_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_3_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7501,7 +7402,7 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccess DATABASE_1_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7509,7 +7410,7 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccess DATABASE_1_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7517,14 +7418,14 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .hdbid(DATABASE_1_ID) .huserid(USER_3_ID) .user(USER_3_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_1_USER_4_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_1_USER_4_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_1_ID) .database(DATABASE_1) @@ -7532,28 +7433,43 @@ public abstract class BaseTest { .user(USER_4) .build(); - public static final DatabaseAccessDto DATABASE_1_USER_4_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_1_USER_4_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_1_ID) .huserid(USER_4_ID) .user(USER_4_BRIEF_DTO) .build(); - public static final Database DATABASE_2 = Database.builder() + public final CreateDashboardResponseDto DATABASE_1_CREATE_DASHBOARD_RESPONSE_DTO = + CreateDashboardResponseDto.builder() + .id(1L) + .uid(DATABASE_1_DASHBOARD_UID) + .build(); + + public final CreateDashboardDto DATABASE_1_CREATE_DASHBOARD_DTO = CreateDashboardDto.builder() + .databaseName(DATABASE_1_INTERNAL_NAME) + .isPublic(DATABASE_1_PUBLIC) + .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) + .ownerUsername(USER_1_USERNAME) + .build(); + + public final Database DATABASE_2 = Database.builder() .id(DATABASE_2_ID) .created(DATABASE_2_CREATED) .lastModified(Instant.now()) .isPublic(DATABASE_2_PUBLIC) .isSchemaPublic(DATABASE_2_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_2_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_2_DASHBOARD_UID) .name(DATABASE_2_NAME) .description(DATABASE_2_DESCRIPTION) .cid(CONTAINER_1_ID) .container(CONTAINER_1) - .internalName(DATABASE_2_INTERNALNAME) + .internalName(DATABASE_2_INTERNAL_NAME) .exchangeName(DATABASE_2_EXCHANGE) .created(DATABASE_2_CREATED) .lastModified(DATABASE_2_LAST_MODIFIED) - .ownedBy(DATABASE_2_OWNER) + .ownedBy(USER_2_ID) .owner(USER_2) .contactPerson(USER_2_ID) .contact(USER_2) @@ -7563,13 +7479,13 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) .build(); - public static final DatabaseDto DATABASE_2_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_2_DTO = DatabaseDto.builder() .id(DATABASE_2_ID) .isPublic(DATABASE_2_PUBLIC) .isSchemaPublic(DATABASE_2_SCHEMA_PUBLIC) .name(DATABASE_2_NAME) .container(CONTAINER_1_DTO) - .internalName(DATABASE_2_INTERNALNAME) + .internalName(DATABASE_2_INTERNAL_NAME) .exchangeName(DATABASE_2_EXCHANGE) .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_DTO))) .tables(new LinkedList<>(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO))) @@ -7578,13 +7494,13 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); - public static final DatabaseDto DATABASE_2_PRIVILEGED_DTO = DatabaseDto.builder() + public final DatabaseDto DATABASE_2_PRIVILEGED_DTO = DatabaseDto.builder() .id(DATABASE_2_ID) .isPublic(DATABASE_2_PUBLIC) .isSchemaPublic(DATABASE_2_SCHEMA_PUBLIC) .name(DATABASE_2_NAME) .container(CONTAINER_1_PRIVILEGED_DTO) - .internalName(DATABASE_2_INTERNALNAME) + .internalName(DATABASE_2_INTERNAL_NAME) .exchangeName(DATABASE_2_EXCHANGE) .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_DTO))) .tables(new LinkedList<>(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO))) @@ -7593,27 +7509,27 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); - public static final DatabaseBriefDto DATABASE_2_PRIVILEGED_BRIEF_DTO = DatabaseBriefDto.builder() + public 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) + .internalName(DATABASE_2_INTERNAL_NAME) .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_BRIEF_DTO))) .ownerId(USER_2_ID) .build(); - public static final DatabaseBriefDto DATABASE_2_BRIEF_DTO = DatabaseBriefDto.builder() + public final DatabaseBriefDto DATABASE_2_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) + .internalName(DATABASE_2_INTERNAL_NAME) .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_BRIEF_DTO))) .ownerId(USER_2_ID) .build(); - public static final DatabaseAccess DATABASE_2_USER_1_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_1_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7621,7 +7537,7 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccess DATABASE_2_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7629,7 +7545,7 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccess DATABASE_2_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7637,7 +7553,7 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccess DATABASE_2_USER_2_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_2_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7645,13 +7561,13 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccessDto DATABASE_2_USER_2_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_2_USER_2_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_2_ID) .huserid(USER_2_ID) .build(); - public static final DatabaseAccess DATABASE_2_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7659,7 +7575,7 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccess DATABASE_2_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7667,14 +7583,14 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccessDto DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .hdbid(DATABASE_2_ID) .huserid(USER_2_ID) .user(USER_2_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_2_USER_3_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_3_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7682,14 +7598,14 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccessDto DATABASE_2_USER_3_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_2_USER_3_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_2_ID) .huserid(USER_3_ID) .user(USER_3_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_2_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7697,7 +7613,7 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccess DATABASE_2_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_2_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_2_ID) .database(DATABASE_2) @@ -7705,21 +7621,36 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final Database DATABASE_3 = Database.builder() + public final CreateDashboardResponseDto DATABASE_2_CREATE_DASHBOARD_RESPONSE_DTO = + CreateDashboardResponseDto.builder() + .id(2L) + .uid(DATABASE_2_DASHBOARD_UID) + .build(); + + public final CreateDashboardDto DATABASE_2_CREATE_DASHBOARD_DTO = CreateDashboardDto.builder() + .databaseName(DATABASE_2_INTERNAL_NAME) + .isPublic(DATABASE_2_PUBLIC) + .isSchemaPublic(DATABASE_2_SCHEMA_PUBLIC) + .ownerUsername(USER_2_USERNAME) + .build(); + + public final Database DATABASE_3 = Database.builder() .id(DATABASE_3_ID) .created(Instant.now().minus(1, HOURS)) .lastModified(Instant.now()) .isPublic(DATABASE_3_PUBLIC) .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_3_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_3_DASHBOARD_UID) .name(DATABASE_3_NAME) .description(DATABASE_3_DESCRIPTION) .cid(CONTAINER_1_ID) .container(CONTAINER_1) - .internalName(DATABASE_3_INTERNALNAME) + .internalName(DATABASE_3_INTERNAL_NAME) .exchangeName(DATABASE_3_EXCHANGE) .created(DATABASE_3_CREATED) .lastModified(DATABASE_3_LAST_MODIFIED) - .ownedBy(DATABASE_3_OWNER) + .ownedBy(USER_3_ID) .owner(USER_3) .contactPerson(USER_3_ID) .contact(USER_3) @@ -7729,7 +7660,7 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) /* IDENTIFIER_6 */ .build(); - public static final DatabaseAccess DATABASE_3_USER_1_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_1_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7737,14 +7668,14 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_1_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_1_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_3_ID) .huserid(USER_1_ID) .user(USER_1_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_3_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7752,14 +7683,14 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_OWN) .hdbid(DATABASE_3_ID) .huserid(USER_1_ID) .user(USER_1_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_3_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7767,14 +7698,14 @@ public abstract class BaseTest { .user(USER_1) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_1_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_1_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .hdbid(DATABASE_3_ID) .huserid(USER_1_ID) .user(USER_1_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_3_USER_2_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_2_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7782,7 +7713,7 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccess DATABASE_3_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7790,7 +7721,7 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccess DATABASE_3_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7798,7 +7729,7 @@ public abstract class BaseTest { .user(USER_2) .build(); - public static final DatabaseAccess DATABASE_3_USER_3_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_3_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7806,14 +7737,14 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_3_READ_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_3_READ_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.READ) .hdbid(DATABASE_3_ID) .huserid(USER_3_ID) .user(USER_3_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_3_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7821,14 +7752,14 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_OWN) .hdbid(DATABASE_3_ID) .huserid(USER_3_ID) .user(USER_3_BRIEF_DTO) .build(); - public static final DatabaseAccess DATABASE_3_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_3_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_3_ID) .database(DATABASE_3) @@ -7836,14 +7767,27 @@ public abstract class BaseTest { .user(USER_3) .build(); - public static final DatabaseAccessDto DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() + public final DatabaseAccessDto DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO = DatabaseAccessDto.builder() .type(AccessTypeDto.WRITE_ALL) .hdbid(DATABASE_3_ID) .huserid(USER_3_ID) .user(USER_3_BRIEF_DTO) .build(); - public static final Identifier IDENTIFIER_7 = Identifier.builder() + public final CreateDashboardResponseDto DATABASE_3_CREATE_DASHBOARD_RESPONSE_DTO = + CreateDashboardResponseDto.builder() + .id(3L) + .uid(DATABASE_3_DASHBOARD_UID) + .build(); + + public final CreateDashboardDto DATABASE_3_CREATE_DASHBOARD_DTO = CreateDashboardDto.builder() + .databaseName(DATABASE_3_INTERNAL_NAME) + .isPublic(DATABASE_3_PUBLIC) + .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) + .ownerUsername(USER_3_USERNAME) + .build(); + + public final Identifier IDENTIFIER_7 = Identifier.builder() .id(IDENTIFIER_7_ID) .descriptions(new LinkedList<>()) .titles(new LinkedList<>()) @@ -7866,21 +7810,23 @@ public abstract class BaseTest { .status(IDENTIFIER_7_STATUS_TYPE) .build(); - public static final Database DATABASE_4 = Database.builder() + public final Database DATABASE_4 = Database.builder() .id(DATABASE_4_ID) .created(Instant.now().minus(4, HOURS)) .lastModified(Instant.now()) .isPublic(DATABASE_4_PUBLIC) .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) + .isDashboardEnabled(DATABASE_4_DASHBOARD_ENABLED) + .dashboardUid(DATABASE_4_DASHBOARD_UID) .name(DATABASE_4_NAME) .description(DATABASE_4_DESCRIPTION) .cid(CONTAINER_4_ID) .container(CONTAINER_4) - .internalName(DATABASE_4_INTERNALNAME) + .internalName(DATABASE_4_INTERNAL_NAME) .exchangeName(DATABASE_4_EXCHANGE) .created(DATABASE_4_CREATED) .lastModified(DATABASE_4_LAST_MODIFIED) - .ownedBy(DATABASE_4_OWNER) + .ownedBy(USER_4_ID) .owner(USER_4) .contactPerson(USER_4_ID) .contact(USER_4) @@ -7889,72 +7835,85 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) .build(); - public static final DatabaseAccess DATABASE_4_USER_1_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_1_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_1_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_1_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_1_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_1_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_1_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_2_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_2_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_2_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_2_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_2_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_2_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_2_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_3_READ_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_3_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_3_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_3_WRITE_OWN_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_OWN) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_3_ID) .build(); - public static final DatabaseAccess DATABASE_4_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() + public final DatabaseAccess DATABASE_4_USER_3_WRITE_ALL_ACCESS = DatabaseAccess.builder() .type(AccessType.WRITE_ALL) .hdbid(DATABASE_4_ID) .database(DATABASE_4) .huserid(USER_3_ID) .build(); - public static final List<IdentifierDto> VIEW_1_DTO_IDENTIFIERS = List.of(IDENTIFIER_3_DTO); + public final CreateDashboardResponseDto DATABASE_4_CREATE_DASHBOARD_RESPONSE_DTO = + CreateDashboardResponseDto.builder() + .id(4L) + .uid(DATABASE_4_DASHBOARD_UID) + .build(); + + public final CreateDashboardDto DATABASE_4_CREATE_DASHBOARD_DTO = CreateDashboardDto.builder() + .databaseName(DATABASE_4_INTERNAL_NAME) + .isPublic(DATABASE_4_PUBLIC) + .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) + .ownerUsername(USER_4_USERNAME) + .build(); + + public final List<IdentifierDto> VIEW_1_DTO_IDENTIFIERS = List.of(IDENTIFIER_3_DTO); - public static final Constraints TABLE_1_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_1_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -7965,7 +7924,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_1_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_1_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -7976,7 +7935,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_2_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_2_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) .foreignKeys(new LinkedList<>(List.of(ForeignKey.builder() .id(UUID.fromString("d79f0fb1-05d6-4f3e-a5e2-8559982b8516")) @@ -8005,36 +7964,36 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_2_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_2_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() - .id(UUID.fromString("ca833111-1e9a-48a3-bb16-ad6f90196f96")) + .id(UUID.fromString("d79f0fb1-05d6-4f3e-a5e2-8559982b8516")) .name("fk_location") .onDelete(ReferenceTypeDto.NO_ACTION) .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() - .id(UUID.fromString("8552f282-0403-424d-b2ba-4ed0f760197c")) - .column(TABLE_2_COLUMNS_BRIEF_2_DTO) + .id(UUID.fromString("a4da8f2f-2999-4621-8066-801a2fb73c8d")) + .column(TABLE_2_COLUMNS_BRIEF_DTO.get(2)) .referencedColumn(TABLE_1_COLUMNS_BRIEF_0_DTO) .foreignKey(null) // set later .build()))) - .table(TABLE_1_BRIEF_DTO) - .referencedTable(TABLE_2_BRIEF_DTO) + .table(TABLE_2_BRIEF_DTO) + .referencedTable(TABLE_1_BRIEF_DTO) .onUpdate(ReferenceTypeDto.NO_ACTION) .build()))) .uniques(new LinkedList<>(List.of(UniqueDto.builder() - .id(UUID.fromString("b9aba807-dd9c-43a3-9614-2493cb4b26bd")) + .id(UUID.fromString("408e398f-d157-49a1-8b45-87a070f3b4de")) .table(TABLE_2_BRIEF_DTO) .name("uk_1") .columns(new LinkedList<>(List.of(TABLE_2_COLUMNS_BRIEF_DTO.get(1)))) .build()))) - .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .primaryKey(new LinkedHashSet<>(List.of(PrimaryKeyDto.builder() .table(TABLE_2_BRIEF_DTO) - .column(TABLE_2_COLUMNS_BRIEF_0_DTO) + .column(TABLE_2_COLUMNS_BRIEF_DTO.get(0)) .id(COLUMN_2_1_ID) .build()))) .build(); - public static final Constraints TABLE_3_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_3_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8045,7 +8004,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_3_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_3_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8056,7 +8015,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_4_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_4_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8067,7 +8026,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_4_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_4_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8078,7 +8037,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_5_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_5_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8089,7 +8048,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_5_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_5_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8100,7 +8059,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_6_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_6_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>(List.of())) .uniques(new LinkedList<>()) @@ -8111,7 +8070,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_6_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_6_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8122,7 +8081,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_7_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_7_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>(List.of(ForeignKey.builder() .id(UUID.fromString("421c3dd8-ae09-4c72-a6ca-09de009e755f")) @@ -8160,7 +8119,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_0_DTO = ForeignKeyDto.builder() + public final ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_0_DTO = ForeignKeyDto.builder() .id(UUID.fromString("561b4933-54e5-4dad-a536-39836da87fe3")) .name("fk_name_id") .onDelete(ReferenceTypeDto.NO_ACTION) @@ -8175,11 +8134,11 @@ public abstract class BaseTest { .onUpdate(ReferenceTypeDto.NO_ACTION) .build(); - public static final ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO = ForeignKeyBriefDto.builder() + public final ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO = ForeignKeyBriefDto.builder() .id(UUID.fromString("a92f09c5-9bce-4f77-8f7b-a9afc1d30ec2")) .build(); - public static final ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_1_DTO = ForeignKeyDto.builder() + public final ForeignKeyDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_1_DTO = ForeignKeyDto.builder() .id(UUID.fromString("f2e82566-ddc3-4b76-8d27-adc3c51780a9")) .name("fk_zoo_id") .onDelete(ReferenceTypeDto.NO_ACTION) @@ -8194,11 +8153,11 @@ public abstract class BaseTest { .onUpdate(ReferenceTypeDto.NO_ACTION) .build(); - public static final ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO = ForeignKeyBriefDto.builder() + public final ForeignKeyBriefDto TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO = ForeignKeyBriefDto.builder() .id(UUID.fromString("6ce1f707-0bdf-4930-be77-157801d2735a")) .build(); - public static final ConstraintsDto TABLE_7_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_7_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>(List.of(TABLE_7_CONSTRAINTS_FOREIGN_KEY_0_DTO, TABLE_7_CONSTRAINTS_FOREIGN_KEY_1_DTO))) @@ -8210,7 +8169,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final Constraints TABLE_8_CONSTRAINTS = Constraints.builder() + public final Constraints TABLE_8_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8221,7 +8180,7 @@ public abstract class BaseTest { .build()))) .build(); - public static final ConstraintsDto TABLE_8_CONSTRAINTS_DTO = ConstraintsDto.builder() + public final ConstraintsDto TABLE_8_CONSTRAINTS_DTO = ConstraintsDto.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .uniques(new LinkedList<>()) @@ -8232,12 +8191,12 @@ public abstract class BaseTest { .build()))) .build(); - public static final ExportResourceDto EXPORT_RESOURCE_DTO = ExportResourceDto.builder() + public final ExportResourceDto EXPORT_RESOURCE_DTO = ExportResourceDto.builder() .filename("68b329da9893e34099c7d8ad5cb9c940") .resource(new InputStreamResource(InputStream.nullInputStream())) .build(); - public static final QueryDto QUERY_1_DTO = QueryDto.builder() + public final QueryDto QUERY_1_DTO = QueryDto.builder() .id(QUERY_1_ID) .databaseId(DATABASE_1_ID) .query(QUERY_1_STATEMENT) @@ -8249,7 +8208,7 @@ public abstract class BaseTest { .resultNumber(3L) .build(); - public static final QueryDto QUERY_2_DTO = QueryDto.builder() + public final QueryDto QUERY_2_DTO = QueryDto.builder() .id(QUERY_2_ID) .databaseId(DATABASE_1_ID) .query(QUERY_2_STATEMENT) @@ -8263,7 +8222,7 @@ public abstract class BaseTest { .resultNumber(3L) .build(); - public static final QueryDto QUERY_3_DTO = QueryDto.builder() + public final QueryDto QUERY_3_DTO = QueryDto.builder() .id(QUERY_3_ID) .databaseId(DATABASE_1_ID) .query(QUERY_3_STATEMENT) @@ -8277,7 +8236,7 @@ public abstract class BaseTest { .resultNumber(2L) .build(); - public static final QueryDto QUERY_7_DTO = QueryDto.builder() + public final QueryDto QUERY_7_DTO = QueryDto.builder() .id(QUERY_7_ID) .databaseId(DATABASE_4_ID) .query(QUERY_7_STATEMENT) @@ -8291,7 +8250,7 @@ public abstract class BaseTest { .resultNumber(2L) .build(); - public static final QueryDto QUERY_6_DTO = QueryDto.builder() + public final QueryDto QUERY_6_DTO = QueryDto.builder() .id(QUERY_6_ID) .databaseId(DATABASE_1_ID) .query(QUERY_6_STATEMENT) @@ -8304,7 +8263,7 @@ public abstract class BaseTest { .isPersisted(QUERY_6_PERSISTED) .build(); - public static final QueryDto QUERY_8_DTO = QueryDto.builder() + public final QueryDto QUERY_8_DTO = QueryDto.builder() .id(QUERY_8_ID) .databaseId(DATABASE_2_ID) .query(QUERY_8_STATEMENT) @@ -8318,4 +8277,131 @@ public abstract class BaseTest { .resultNumber(3L) .build(); -} + public BaseTest() { + IMAGE_1_DTO.setOperators(IMAGE_1_OPERATORS_DTO); + CONTAINER_1_DTO.setImage(IMAGE_1_DTO); + IMAGE_1.setOperators(new LinkedList<>(IMAGE_1_OPERATORS)); + CONTAINER_1.setDatabases(new LinkedList<>(List.of(DATABASE_1, DATABASE_2, DATABASE_3))); + CONTAINER_4.setDatabases(new LinkedList<>(List.of(DATABASE_4))); + /* DATABASE 1 */ + DATABASE_1.setOwner(USER_1); + DATABASE_1.setSubsets(new LinkedList<>()); + DATABASE_1.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS, DATABASE_1_USER_2_WRITE_OWN_ACCESS, DATABASE_1_USER_3_WRITE_ALL_ACCESS))); + DATABASE_1_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS_DTO, DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO, DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO))); + DATABASE_1_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS_DTO, DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO, DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO))); + TABLE_1.setDatabase(DATABASE_1); + TABLE_1.setColumns(new LinkedList<>(TABLE_1_COLUMNS)); + TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); + VIEW_1_DTO.setIdentifiers(VIEW_1_DTO_IDENTIFIERS); + 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); + IDENTIFIER_3.setDatabase(DATABASE_1); + IDENTIFIER_4.setDatabase(DATABASE_1); + DATABASE_1.setTables(new LinkedList<>(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_4))); + DATABASE_1.setViews(new LinkedList<>(List.of(VIEW_1, VIEW_2, VIEW_3))); + DATABASE_1_DTO.setContainer(CONTAINER_1_DTO); + DATABASE_1_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))); + DATABASE_1_DTO.setTables(new LinkedList<>(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO))); + 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_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_3.setDatabase(DATABASE_1); + TABLE_3.setColumns(new LinkedList<>(TABLE_3_COLUMNS)); + TABLE_3.setConstraints(TABLE_3_CONSTRAINTS); + TABLE_3_DTO.setColumns(new LinkedList<>(TABLE_3_COLUMNS_DTO)); + TABLE_3_DTO.setConstraints(TABLE_3_CONSTRAINTS_DTO); + TABLE_4.setDatabase(DATABASE_1); + TABLE_4.setColumns(new LinkedList<>(TABLE_4_COLUMNS)); + TABLE_4.setConstraints(TABLE_4_CONSTRAINTS); + TABLE_4_DTO.setColumns(TABLE_4_COLUMNS_DTO); + TABLE_4_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_2.setDatabase(DATABASE_1); + VIEW_2.setColumns(new LinkedList<>(VIEW_2_COLUMNS)); + VIEW_3.setDatabase(DATABASE_1); + VIEW_3.setColumns(new LinkedList<>(VIEW_3_COLUMNS)); + IDENTIFIER_1.setDatabase(DATABASE_1); + IDENTIFIER_2.setDatabase(DATABASE_1); + IDENTIFIER_3.setDatabase(DATABASE_1); + IDENTIFIER_4.setDatabase(DATABASE_1); + /* DATABASE 2 */ + 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)); + 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); + TABLE_5_DTO.setColumns(new LinkedList<>(TABLE_5_COLUMNS_DTO)); + TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); + TABLE_6.setDatabase(DATABASE_2); + TABLE_6.setColumns(new LinkedList<>(TABLE_6_COLUMNS)); + TABLE_6.setConstraints(TABLE_6_CONSTRAINTS); + TABLE_7.setDatabase(DATABASE_2); + TABLE_7.setColumns(new LinkedList<>(TABLE_7_COLUMNS)); + TABLE_7.setConstraints(TABLE_7_CONSTRAINTS); + TABLE_7_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(0)); + TABLE_7_CONSTRAINTS.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(1)); + TABLE_7_DTO.setColumns(TABLE_7_COLUMNS_DTO); + TABLE_7_DTO.setConstraints(TABLE_7_CONSTRAINTS_DTO); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_0_DTO); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_FOREIGN_KEY_BRIEF_1_DTO); + VIEW_4.setDatabase(DATABASE_2); + IDENTIFIER_5.setDatabase(DATABASE_2); + /* DATABASE 3 */ + DATABASE_3.setTables(new LinkedList<>(List.of(TABLE_8))); + DATABASE_3.setViews(new LinkedList<>(List.of(VIEW_5))); + DATABASE_3.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_6))); + DATABASE_3.setAccesses(new LinkedList<>(List.of(DATABASE_3_USER_1_WRITE_ALL_ACCESS))); + DATABASE_3_DTO.setTables(new LinkedList<>(List.of(TABLE_8_DTO))); + DATABASE_3_DTO.setViews(new LinkedList<>(List.of(VIEW_5_DTO))); + 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); + TABLE_8_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); + TABLE_8_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); + VIEW_5.setDatabase(DATABASE_3); + VIEW_5.setColumns(VIEW_5_COLUMNS); + VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO); + IDENTIFIER_6.setDatabase(DATABASE_3); + /* DATABASE 4 */ + 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))); + 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); + TABLE_9_DTO.setColumns(TABLE_9_COLUMNS_DTO); + TABLE_9_DTO.setConstraints(TABLE_9_CONSTRAINTS_DTO); + IDENTIFIER_7.setStatus(IdentifierStatusType.DRAFT); + IDENTIFIER_7.setDatabase(DATABASE_4); + } + +} \ No newline at end of file diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/dto/LocaleDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/dto/LocaleDto.java similarity index 86% rename from dbrepo-metadata-service/test/src/main/java/at/tuwien/test/dto/LocaleDto.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/dto/LocaleDto.java index d14ad880d9..bec6d7ea05 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/dto/LocaleDto.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/dto/LocaleDto.java @@ -1,4 +1,4 @@ -package at.tuwien.test.dto; +package at.ac.tuwien.ifs.dbrepo.core.test.dto; import lombok.*; diff --git a/dbrepo-metadata-service/test/pom.xml b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/pom.xml similarity index 94% rename from dbrepo-metadata-service/test/pom.xml rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/pom.xml index b6bf12dfa4..a7995dec69 100644 --- a/dbrepo-metadata-service/test/pom.xml +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.7.3</version> + <version>1.8.0</version> </parent> <artifactId>dbrepo-metadata-service-test</artifactId> <name>dbrepo-metadata-service-test</name> - <version>1.7.3</version> + <version>1.8.0</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/ArrayUtils.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/ArrayUtils.java similarity index 87% rename from dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/ArrayUtils.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/ArrayUtils.java index 50dff12d85..c30116295f 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/ArrayUtils.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/ArrayUtils.java @@ -1,4 +1,4 @@ -package at.tuwien.test.utils; +package at.ac.tuwien.ifs.dbrepo.core.test.utils; import java.util.Arrays; import java.util.LinkedList; diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/EndpointUtils.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/EndpointUtils.java similarity index 94% rename from dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/EndpointUtils.java rename to lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/EndpointUtils.java index a2101bf3ab..56adf110c9 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/utils/EndpointUtils.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/utils/EndpointUtils.java @@ -1,6 +1,6 @@ -package at.tuwien.test.utils; +package at.ac.tuwien.ifs.dbrepo.core.test.utils; -import at.tuwien.test.dto.LocaleDto; +import at.ac.tuwien.ifs.dbrepo.core.test.dto.LocaleDto; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.config.BeanDefinition; diff --git a/lib/python/Makefile b/lib/python/Makefile deleted file mode 100644 index afebb199ac..0000000000 --- a/lib/python/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -all: build - -clean: - rm -rf ./python/dist/* ./docs/build/* ./dist/* - -docs: clean - sphinx-apidoc -o ./docs/source ./dbrepo - sphinx-build -M html ./docs/ ./docs/build/ - -check: - python3 ./python/setup.py develop - -build: clean - python3 -m build --sdist . - python3 -m build --wheel . - -deploy: build - python3 -m twine upload --config-file ~/.pypirc --verbose --repository pypi ./dist/dbrepo-* - -deploy-test: build - python3 -m twine upload --config-file ~/.pypirc --verbose --repository testpypi ./dist/dbrepo-* - -FORCE: ; \ No newline at end of file diff --git a/lib/python/Pipfile b/lib/python/Pipfile index b7ebe44f3a..e9fb9d2177 100644 --- a/lib/python/Pipfile +++ b/lib/python/Pipfile @@ -10,6 +10,9 @@ paho-mqtt = "*" pydantic = "*" tuspy = "*" pandas = "*" +jwt = "~=1.3" +grafana-client = "*" +opensearch-py = "~=2.2" [dev-packages] build = "*" @@ -22,6 +25,8 @@ requests-mock = "*" furo = "*" pytest-ordering = "*" httpx = "*" +testcontainers-minio = "*" +testcontainers-opensearch = "*" [requires] python_version = "3.11" diff --git a/lib/python/Pipfile.lock b/lib/python/Pipfile.lock index d4c90209c0..a0cbd664ae 100644 --- a/lib/python/Pipfile.lock +++ b/lib/python/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "049bd8a6ac52e886dce11e7d7de630464e073e360471f35125a2eccf7c30a7a7" + "sha256": "b4e4c9e239afef86e7bfbe56d0f92336cacdc3fa9e4f85c0f51c8551771396ae" }, "pipfile-spec": 6, "requires": { @@ -18,98 +18,98 @@ "default": { "aiohappyeyeballs": { "hashes": [ - "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1", - "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0" + "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", + "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" ], "markers": "python_version >= '3.9'", - "version": "==2.4.6" + "version": "==2.6.1" }, "aiohttp": { "hashes": [ - "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef", - "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae", - "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462", - "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a", - "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5", - "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0", - "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6", - "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb", - "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb", - "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1", - "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce", - "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a", - "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42", - "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58", - "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204", - "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed", - "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9", - "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c", - "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3", - "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7", - "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1", - "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff", - "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802", - "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957", - "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73", - "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78", - "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef", - "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e", - "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798", - "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0", - "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804", - "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b", - "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e", - "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5", - "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5", - "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854", - "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420", - "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb", - "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55", - "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65", - "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6", - "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1", - "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df", - "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460", - "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6", - "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933", - "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b", - "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7", - "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259", - "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5", - "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0", - "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9", - "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9", - "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484", - "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f", - "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8", - "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb", - "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9", - "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d", - "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94", - "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72", - "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259", - "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f", - "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9", - "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df", - "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f", - "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788", - "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0", - "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c", - "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16", - "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d", - "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250", - "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a", - "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2", - "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1", - "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf", - "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd", - "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e", - "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00", - "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4", - "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287" + "sha256:04eb541ce1e03edc1e3be1917a0f45ac703e913c21a940111df73a2c2db11d73", + "sha256:05582cb2d156ac7506e68b5eac83179faedad74522ed88f88e5861b78740dc0e", + "sha256:0a29be28e60e5610d2437b5b2fed61d6f3dcde898b57fb048aa5079271e7f6f3", + "sha256:0b2501f1b981e70932b4a552fc9b3c942991c7ae429ea117e8fba57718cdeed0", + "sha256:0df3788187559c262922846087e36228b75987f3ae31dd0a1e5ee1034090d42f", + "sha256:12c5869e7ddf6b4b1f2109702b3cd7515667b437da90a5a4a50ba1354fe41881", + "sha256:14fc03508359334edc76d35b2821832f092c8f092e4b356e74e38419dfe7b6de", + "sha256:1a7169ded15505f55a87f8f0812c94c9412623c744227b9e51083a72a48b68a5", + "sha256:1c68e41c4d576cd6aa6c6d2eddfb32b2acfb07ebfbb4f9da991da26633a3db1a", + "sha256:20412c7cc3720e47a47e63c0005f78c0c2370020f9f4770d7fc0075f397a9fb0", + "sha256:22a8107896877212130c58f74e64b77f7007cb03cea8698be317272643602d45", + "sha256:28a3d083819741592685762d51d789e6155411277050d08066537c5edc4066e6", + "sha256:2b86efe23684b58a88e530c4ab5b20145f102916bbb2d82942cafec7bd36a647", + "sha256:2d0b46abee5b5737cb479cc9139b29f010a37b1875ee56d142aefc10686a390b", + "sha256:321238a42ed463848f06e291c4bbfb3d15ba5a79221a82c502da3e23d7525d06", + "sha256:3a8a0d127c10b8d89e69bbd3430da0f73946d839e65fec00ae48ca7916a31948", + "sha256:3a8b0321e40a833e381d127be993b7349d1564b756910b28b5f6588a159afef3", + "sha256:3b420d076a46f41ea48e5fcccb996f517af0d406267e31e6716f480a3d50d65c", + "sha256:3b512f1de1c688f88dbe1b8bb1283f7fbeb7a2b2b26e743bb2193cbadfa6f307", + "sha256:413fe39fd929329f697f41ad67936f379cba06fcd4c462b62e5b0f8061ee4a77", + "sha256:41cf0cefd9e7b5c646c2ef529c8335e7eafd326f444cc1cdb0c47b6bc836f9be", + "sha256:4848ae31ad44330b30f16c71e4f586cd5402a846b11264c412de99fa768f00f3", + "sha256:4b0a200e85da5c966277a402736a96457b882360aa15416bf104ca81e6f5807b", + "sha256:4e2e8ef37d4bc110917d038807ee3af82700a93ab2ba5687afae5271b8bc50ff", + "sha256:4edcbe34e6dba0136e4cabf7568f5a434d89cc9de5d5155371acda275353d228", + "sha256:51ba80d473eb780a329d73ac8afa44aa71dfb521693ccea1dea8b9b5c4df45ce", + "sha256:5409a59d5057f2386bb8b8f8bbcfb6e15505cedd8b2445db510563b5d7ea1186", + "sha256:572def4aad0a4775af66d5a2b5923c7de0820ecaeeb7987dcbccda2a735a993f", + "sha256:599b66582f7276ebefbaa38adf37585e636b6a7a73382eb412f7bc0fc55fb73d", + "sha256:59a05cdc636431f7ce843c7c2f04772437dd816a5289f16440b19441be6511f1", + "sha256:602d4db80daf4497de93cb1ce00b8fc79969c0a7cf5b67bec96fa939268d806a", + "sha256:65c75b14ee74e8eeff2886321e76188cbe938d18c85cff349d948430179ad02c", + "sha256:69bb252bfdca385ccabfd55f4cd740d421dd8c8ad438ded9637d81c228d0da49", + "sha256:6d3986112e34eaa36e280dc8286b9dd4cc1a5bcf328a7f147453e188f6fe148f", + "sha256:6dd9766da617855f7e85f27d2bf9a565ace04ba7c387323cd3e651ac4329db91", + "sha256:70ab0f61c1a73d3e0342cedd9a7321425c27a7067bebeeacd509f96695b875fc", + "sha256:749f1eb10e51dbbcdba9df2ef457ec060554842eea4d23874a3e26495f9e87b1", + "sha256:781c8bd423dcc4641298c8c5a2a125c8b1c31e11f828e8d35c1d3a722af4c15a", + "sha256:7e7abe865504f41b10777ac162c727af14e9f4db9262e3ed8254179053f63e6d", + "sha256:7f2dadece8b85596ac3ab1ec04b00694bdd62abc31e5618f524648d18d9dd7fa", + "sha256:86135c32d06927339c8c5e64f96e4eee8825d928374b9b71a3c42379d7437058", + "sha256:8778620396e554b758b59773ab29c03b55047841d8894c5e335f12bfc45ebd28", + "sha256:87f0e003fb4dd5810c7fbf47a1239eaa34cd929ef160e0a54c570883125c4831", + "sha256:8aa5c68e1e68fff7cd3142288101deb4316b51f03d50c92de6ea5ce646e6c71f", + "sha256:8d14e274828561db91e4178f0057a915f3af1757b94c2ca283cb34cbb6e00b50", + "sha256:8d1dd75aa4d855c7debaf1ef830ff2dfcc33f893c7db0af2423ee761ebffd22b", + "sha256:92007c89a8cb7be35befa2732b0b32bf3a394c1b22ef2dff0ef12537d98a7bda", + "sha256:92868f6512714efd4a6d6cb2bfc4903b997b36b97baea85f744229f18d12755e", + "sha256:948abc8952aff63de7b2c83bfe3f211c727da3a33c3a5866a0e2cf1ee1aa950f", + "sha256:95d7787f2bcbf7cb46823036a8d64ccfbc2ffc7d52016b4044d901abceeba3db", + "sha256:997b57e38aa7dc6caab843c5e042ab557bc83a2f91b7bd302e3c3aebbb9042a1", + "sha256:99b8bbfc8111826aa8363442c0fc1f5751456b008737ff053570f06a151650b3", + "sha256:9e73fa341d8b308bb799cf0ab6f55fc0461d27a9fa3e4582755a3d81a6af8c09", + "sha256:a0d2c04a623ab83963576548ce098baf711a18e2c32c542b62322a0b4584b990", + "sha256:a40087b82f83bd671cbeb5f582c233d196e9653220404a798798bfc0ee189fff", + "sha256:ad1f2fb9fe9b585ea4b436d6e998e71b50d2b087b694ab277b30e060c434e5db", + "sha256:b05774864c87210c531b48dfeb2f7659407c2dda8643104fb4ae5e2c311d12d9", + "sha256:b41693b7388324b80f9acfabd479bd1c84f0bc7e8f17bab4ecd9675e9ff9c734", + "sha256:b42dbd097abb44b3f1156b4bf978ec5853840802d6eee2784857be11ee82c6a0", + "sha256:b4e7c7ec4146a94a307ca4f112802a8e26d969018fabed526efc340d21d3e7d0", + "sha256:b59d096b5537ec7c85954cb97d821aae35cfccce3357a2cafe85660cc6295628", + "sha256:b9c60d1de973ca94af02053d9b5111c4fbf97158e139b14f1be68337be267be6", + "sha256:bccd2cb7aa5a3bfada72681bdb91637094d81639e116eac368f8b3874620a654", + "sha256:c32593ead1a8c6aabd58f9d7ee706e48beac796bb0cb71d6b60f2c1056f0a65f", + "sha256:c7571f99525c76a6280f5fe8e194eeb8cb4da55586c3c61c59c33a33f10cfce7", + "sha256:c8b2df9feac55043759aa89f722a967d977d80f8b5865a4153fc41c93b957efc", + "sha256:ca9f835cdfedcb3f5947304e85b8ca3ace31eef6346d8027a97f4de5fb687534", + "sha256:cc9253069158d57e27d47a8453d8a2c5a370dc461374111b5184cf2f147a3cc3", + "sha256:ced66c5c6ad5bcaf9be54560398654779ec1c3695f1a9cf0ae5e3606694a000a", + "sha256:d173c0ac508a2175f7c9a115a50db5fd3e35190d96fdd1a17f9cb10a6ab09aa1", + "sha256:d6edc538c7480fa0a3b2bdd705f8010062d74700198da55d16498e1b49549b9c", + "sha256:daf20d9c3b12ae0fdf15ed92235e190f8284945563c4b8ad95b2d7a31f331cd3", + "sha256:dc311634f6f28661a76cbc1c28ecf3b3a70a8edd67b69288ab7ca91058eb5a33", + "sha256:e2bc827c01f75803de77b134afdbf74fa74b62970eafdf190f3244931d7a5c0d", + "sha256:e365034c5cf6cf74f57420b57682ea79e19eb29033399dd3f40de4d0171998fa", + "sha256:e906da0f2bcbf9b26cc2b144929e88cb3bf943dd1942b4e5af066056875c7618", + "sha256:e9faafa74dbb906b2b6f3eb9942352e9e9db8d583ffed4be618a89bd71a4e914", + "sha256:ec6cd1954ca2bbf0970f531a628da1b1338f594bf5da7e361e19ba163ecc4f3b", + "sha256:f296d637a50bb15fb6a229fbb0eb053080e703b53dbfe55b1e4bb1c5ed25d325", + "sha256:f30fc72daf85486cdcdfc3f5e0aea9255493ef499e31582b34abadbfaafb0965", + "sha256:fe846f0a98aa9913c2852b630cd39b4098f296e0907dd05f6c7b30d911afa4c3" ], "markers": "python_version >= '3.9'", - "version": "==3.11.12" + "version": "==3.11.14" }, "aiosignal": { "hashes": [ @@ -129,11 +129,11 @@ }, "attrs": { "hashes": [ - "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", - "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a" + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" ], "markers": "python_version >= '3.8'", - "version": "==25.1.0" + "version": "==25.3.0" }, "certifi": { "hashes": [ @@ -143,6 +143,79 @@ "markers": "python_version >= '3.6'", "version": "==2025.1.31" }, + "cffi": { + "hashes": [ + "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", + "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", + "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", + "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", + "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", + "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", + "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", + "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", + "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", + "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", + "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", + "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", + "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", + "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", + "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", + "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", + "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", + "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", + "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", + "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", + "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", + "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", + "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", + "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", + "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", + "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", + "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", + "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", + "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", + "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", + "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", + "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", + "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", + "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", + "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", + "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", + "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", + "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", + "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", + "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", + "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", + "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", + "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", + "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", + "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", + "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", + "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", + "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", + "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", + "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", + "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", + "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", + "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", + "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", + "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", + "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", + "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", + "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", + "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", + "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", + "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==1.17.1" + }, "charset-normalizer": { "hashes": [ "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", @@ -241,6 +314,53 @@ "markers": "python_version >= '3.7'", "version": "==3.4.1" }, + "cryptography": { + "hashes": [ + "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.2" + }, + "events": { + "hashes": [ + "sha256:a7286af378ba3e46640ac9825156c93bdba7502174dd696090fdfcd4d80a1abd" + ], + "version": "==0.5" + }, "frozenlist": { "hashes": [ "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", @@ -339,6 +459,22 @@ "markers": "python_version >= '3.8'", "version": "==1.5.0" }, + "grafana-client": { + "hashes": [ + "sha256:2477a47b923fd0637947e620b0b777c641af18a3025464fa4505783dbf05dfcc", + "sha256:8cb61bb2a87ec07bca10974df276b9a1a95bfdb63f3a696f065692ffc9b8c389" + ], + "index": "pypi", + "version": "==4.3.2" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, "idna": { "hashes": [ "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", @@ -347,164 +483,289 @@ "markers": "python_version >= '3.6'", "version": "==3.10" }, + "jh2": { + "hashes": [ + "sha256:038091480cd1544e9389b0adbb1b1645a797689dcb68ceae7e45eec96ed24497", + "sha256:0c8e336df8ed1687590695f4469f480eeb4159bf13bb6193791c6530fe114b49", + "sha256:0c9bf2d5e4ef45c1686c6f76935e7ca263f5eae4de92bf5d1873a0e737e4eb7d", + "sha256:0faf6e96f74d27b8ca816b40217904891f91b664ed1c0388737949ceb50ac15d", + "sha256:10ea7f497e6226372e1d4fdbf42c8381f4887819a643ab930bff4072ad298d84", + "sha256:11650f7ed77ee1df30f25d6b3b74b2fa1c94124e074fd455abafea3cbc913d53", + "sha256:12ead3ee3e9c7caa00356b528a5cc7fe210fbe2060628af6e19ed76b8416572e", + "sha256:136b3c5b08883681fcb58f12393a5bbfa422d6e2d5ba887e263e776874276bc6", + "sha256:17d6e1691154ea9f726e43dcb717df48e56c66b5a01c90ad675c6494c36e5be1", + "sha256:19cb987915cc0d321746a12f2a693d087ffb721c37ac9a153cc088c57d4d90eb", + "sha256:1cdf15de698c4026e64fd914fead3180e52bf2a7bcbe44a3392404582dbf2d22", + "sha256:1e81e1c64e33506b8508ba5e3c7c139b2577e78b079c2c16a8e7a02a161f1080", + "sha256:2226c76e4ff2149c5d9f94bed22bf9c4f3411d38cc53d4a7ddfbe0899c8b558c", + "sha256:2837412fb7b684c6ce7392c8bc57440c6dbadaf1bde7a53144381f7df7083c1c", + "sha256:293f0f3da3c391e997e0d55fdb85540e98a8b0406622bb4ba57fb7617697f31e", + "sha256:2b9cc6c0239215a349d28c192fa4c4e7a7348eee7980531525c01bffe39eea80", + "sha256:2f3ad679f84ff236a0d7b71ddc4b3c09fe467abee2f1a86671f0cd417be5352b", + "sha256:358cad2f328c52c15756cf32b0ad17afb0d617e7cdfe93d59aa2616966d825b7", + "sha256:3663712305b509f79c002c8c0ca9994f716cadba576f5a59632dda1aec1ca8c6", + "sha256:41794820ccca039ca2ead6245f30b34601dd1456eee5b5dde620672bb989e79d", + "sha256:44b7e64aff542471c474c24f771eae5efd9152da02a12556f7cb7607020e1420", + "sha256:45770eb0990166026538d3c2fd7d92f17cfde13ca6567570c4baec3ce9162936", + "sha256:498060078a4d1b458e9381fefb027d85329397b50d65287712b3d48233e20836", + "sha256:4c2f18f337c2393f84e45e5011c8b02697b81638b1cec49da60a01b9ed067695", + "sha256:5162d6e475d2762035fb8ea25982bcbec6c58715e33bd0951499f743cd90b110", + "sha256:51e8c890bb59008c95b3a552cefd8bd9ce50a7466a6c920a78cf586e885d7449", + "sha256:56ad3839ac6ac5fd3d023cf59d4b04264b74bb4cb44c0780faf51d6b5ff38fbc", + "sha256:5821638ef0d7c973071810a6786f59b305172197f7e7e469a2ce169e7f4978e3", + "sha256:5ac1b2d379f4d40c13dcce537e69704452943cddbe991fd54a84fdb2da9026d5", + "sha256:5b465d4311b0429fe6fa85df8e2cfcb038c9fface95396dd14e838ecabaaadf2", + "sha256:5d8656b98057329bd03d968aac8d5198389cf51517511295cfc4cb827a507e39", + "sha256:5dcfb3e823ef4b91b70b92848570d1d8cfd584304bd2bd54272dc100c9494def", + "sha256:5e40d23ea43f683f3a7c032dde391104f609b05c21b6d284101120b51dbd50c1", + "sha256:63a01522bde161c713f7fa5ee5d850fee6386fc386073490ebcd438f14579cf2", + "sha256:6b2a3d7756035dde13571f4ad232629b78b7f35c2cd5fda7b464079fc697db3a", + "sha256:6b3be1a6bf6c965aea3b4e3a40df9d2c134c516d89c76cf2b6c81f67e6c5c6ed", + "sha256:6c7bea3357f2dc653756e6da55f66cd21c73d3875c8f3dc4e8d196a876252de0", + "sha256:6e6c8e229507cf29333a2f491cbaa7dff5b8a4a3e613af8090ccce9ce3e4f7a0", + "sha256:6fad27f2a63884ee45d491aebec4b1f38752cd6aaccc625038c21e7f43c02c49", + "sha256:71bfef52547c2b8b145897fa8d1b5142bc52313cfa38c0742e0ef755f0d09c60", + "sha256:72370d312323282b1bf74426e53fae861a310d7ae519b419da46673c38e7d147", + "sha256:76c7d36043a9c478b0c846fcec7da5cb095983722473e503e0122ccd170182b5", + "sha256:78d8a81ef51edb9a2f278a6fb278789b49e304b12bb21bccf2fe7e344f71a9fb", + "sha256:798a6b159ce32181a5e7ab7611c17d1080e74a5541fec47f961b728dab25a76f", + "sha256:7e370567f66a57e2c0e3ae2afcc6f126e1d6babd36831cfd0caad279b05c1c88", + "sha256:8004b845f606b95a8b17efa112aa10b327e46e95dcda604a257b4633d4ed45c8", + "sha256:80b20bf9ea4e709b3b9ae364ac298dfa872b084c186e5c1d60b0b79c79a7ee7e", + "sha256:87303f4bb1b493997f911a4f126123ccd2827d3a2e7dd2390cc6143fbc75805b", + "sha256:8d423f4631395b92dceda39f481a463498131ac02a58581124a44495491f715b", + "sha256:94ee262192db50fb9c069a0be7bb1a426fb1b43af26ce12bf4c6c30e13f46b56", + "sha256:960e4be2e7de340300ab4bcc2b45bed46be1d62330575b8265e6602dbcb9a14c", + "sha256:99397d5e1da6b345cec3e6125e2902b0e6864eb8eaa4be43a2013f059c502c93", + "sha256:9abbb8c1bad08817bad62ae1ea76c01bdbd0ee8c827d05f3ba038c9f6d6f14bb", + "sha256:9c0b8fadf80bc70d341032f92702bda1b0ed78c01e9c495f0df701938c99bcf5", + "sha256:9f977da9abae170eebdcf02bda33727c342fad5dcdbc08498bfdfb6cc6c65489", + "sha256:a6be712ca39d5e9c89b705bc9800be36739436fefb8d0b52b2d332f7d6d22a01", + "sha256:aa434418d6ee44b0ba3a5a407bc9e1543cf496328f43f149e9b58f74a63d5c21", + "sha256:ac4f778e32f7de0ba63346893a4af87c2280ffc1783f594a117be51d908a10da", + "sha256:ac85d65ee369c09b2904b55078ad589961e2e2e03c810963d35a26e6a3931425", + "sha256:ad5d78c664d39960435d4162db31117c8945ba74fb0c414e79ba85a8bdeafdec", + "sha256:ad91f57c3485d87a8edee558dafab0f08c716857d748731c0998dcefe9d3fd5f", + "sha256:afd255d42b340036883ca95bded553b29065b064e2fe5db64ad5988517db9694", + "sha256:b1c2c74f100a0c2110a8e30445554ae331860d32f145c60a2a1e1c27702022a2", + "sha256:b49a8c71378d40d43c6a56eaa536d7823baa43c27c93e082aeb60a9717be0c10", + "sha256:b5f52611323e8e35705e6750a760f32165b41c052d22da154ae343871e7cd50d", + "sha256:b6bf99ae529ac359263269710356d3ddb173c15d8f8dc8849ae794ab811e5cd0", + "sha256:ba361bf87c4701f11241be92c99ef5cf916865dd225955cccb2376bf76717b3c", + "sha256:bc351aa2158575e68943d8e1d5531719ad86bf6607776627ed5a1a60657664af", + "sha256:bd6eb7b1e12e4dd0b75cab1b023272f1333494add5ad61deedac738af1ffeede", + "sha256:bf8852595f5e2d2b072e24c29394b5aca7fba96ecc8656d56660535f9e9872c9", + "sha256:c1dd66541569a2bdbe92589cc96a89f470b20d168f2238fd463e1b59ee3e2d49", + "sha256:c36a7a004cba4e370d0675826eeefe4e42a256638b6b1432263ddb4af317bc02", + "sha256:c886cda61da4d39010be84802bed11bc75f03e8a6094cc18016957a2c80254d4", + "sha256:cc7aa83946f80c66a5d2dea7e165f15aa3eb21e7b74b24d8f850afc0d44bb00e", + "sha256:cea9c4bef70d1358bafec6019164abce362f4de15d79d1ecd64ae31c1749d77a", + "sha256:cfe1951e80869695857986be104a40a1e7fa8ec7de05f86bcbd7bd20854be764", + "sha256:d36cf6f139da3279644794fcfda18af425c8bb122ef9c2e7c762a937bbf7b0f4", + "sha256:d81308faaa9393b7e6ed20718d465c4c2b73c24d5e4826024961acf4b87b1524", + "sha256:db51ea1f9c5ac790848bc271fcdf4108ad1b77a77c6949a96320477962cf7ba5", + "sha256:dd05c18c920a15e00d7a52df37bffd3930fe2c004c690f9422b20e12077e6dbd", + "sha256:df05918a11e1db0198d00486e36673b4b4a89390e4458ff9479b4908dde357ac", + "sha256:e4c31dccf6be131709e545d0258eb5b75c5fac304857ad3976331c6740e8b9d6", + "sha256:e60954d673040430802b29fe5bba698e262182b5ba5f302ff4458e39f8101881", + "sha256:e60e2d2c88a0552e61c37172fe377f6a8abf479130a445314886de4a360ba940", + "sha256:e786f773ddc153846b2ebdb854011cfd1f7c874b8ee79cced3706801341c9f5d", + "sha256:e7cd91548fb95b69edd376f5204e27115ac7d093ec7d80066123a5bdb31c71d9", + "sha256:eaef2ea4f5602aefaaf3d6e8235f3b9ffde35aff15aac1c16cc802f6bbf0a3b5", + "sha256:ec8c5ea93a03775fbadd08462200cf34ce617ec75a032abfa44fd6d3a00e5424", + "sha256:eddeb8574bc9d9abb8491d4a46b60e553c2cea235b80373756acb06568101175", + "sha256:eeb300b0e4b428aab2f70d785cad4306529262af6de8c8c5fe6a4b41a674a434", + "sha256:f39d71ece8e97cf069e4154868eaac1256b133fe23e0459829432e4bb6406472", + "sha256:f4840ddad2b9d53710e92361391944da89e3576641a290066a1719520059247c", + "sha256:f70723a00bcbce0f9a216853139955be45da35741335eb3afead304e77662560", + "sha256:f829cf2ba5b553e6529d6238928c07096f1feb47f4ad536b7f06bca6cc77173f", + "sha256:f96386910467725895f7972939a6faabd6e96b1de0cc2c092e4bd2c40e956e25", + "sha256:fe259a9d6f555bc79aed9bb4b9a7fff73db443b4c483e4a81a428c8a2860428b" + ], + "markers": "python_version >= '3.7'", + "version": "==5.0.8" + }, + "jwt": { + "hashes": [ + "sha256:61c9170f92e736b530655e75374681d4fcca9cfa8763ab42be57353b2b203494" + ], + "index": "pypi", + "version": "==1.3.1" + }, "multidict": { "hashes": [ - "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", - "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056", - "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", - "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", - "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", - "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", - "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748", - "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", - "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f", - "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", - "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6", - "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada", - "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", - "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2", - "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d", - "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", - "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef", - "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", - "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", - "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60", - "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6", - "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", - "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478", - "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", - "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7", - "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56", - "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", - "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", - "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30", - "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", - "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", - "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0", - "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", - "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c", - "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", - "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", - "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", - "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", - "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", - "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2", - "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", - "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", - "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", - "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", - "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657", - "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581", - "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492", - "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43", - "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", - "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", - "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", - "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057", - "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc", - "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", - "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255", - "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1", - "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972", - "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53", - "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1", - "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", - "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a", - "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160", - "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c", - "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd", - "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", - "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5", - "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", - "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", - "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", - "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", - "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4", - "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", - "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", - "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28", - "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d", - "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a", - "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", - "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", - "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429", - "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", - "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", - "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", - "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392", - "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167", - "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c", - "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", - "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", - "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76", - "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875", - "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd", - "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", - "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db" + "sha256:0085b0afb2446e57050140240a8595846ed64d1cbd26cef936bfab3192c673b8", + "sha256:042028348dc5a1f2be6c666437042a98a5d24cee50380f4c0902215e5ec41844", + "sha256:05fefbc3cddc4e36da209a5e49f1094bbece9a581faa7f3589201fd95df40e5d", + "sha256:063be88bd684782a0715641de853e1e58a2f25b76388538bd62d974777ce9bc2", + "sha256:07bfa8bc649783e703263f783f73e27fef8cd37baaad4389816cf6a133141331", + "sha256:08549895e6a799bd551cf276f6e59820aa084f0f90665c0f03dd3a50db5d3c48", + "sha256:095a2eabe8c43041d3e6c2cb8287a257b5f1801c2d6ebd1dd877424f1e89cf29", + "sha256:0b183a959fb88ad1be201de2c4bdf52fa8e46e6c185d76201286a97b6f5ee65c", + "sha256:0c383d28857f66f5aebe3e91d6cf498da73af75fbd51cedbe1adfb85e90c0460", + "sha256:0d57a01a2a9fa00234aace434d8c131f0ac6e0ac6ef131eda5962d7e79edfb5b", + "sha256:0dc25a3293c50744796e87048de5e68996104d86d940bb24bc3ec31df281b191", + "sha256:0e5a644e50ef9fb87878d4d57907f03a12410d2aa3b93b3acdf90a741df52c49", + "sha256:0f249badb360b0b4d694307ad40f811f83df4da8cef7b68e429e4eea939e49dd", + "sha256:0f74f2fc51555f4b037ef278efc29a870d327053aba5cb7d86ae572426c7cccc", + "sha256:125dd82b40f8c06d08d87b3510beaccb88afac94e9ed4a6f6c71362dc7dbb04b", + "sha256:13551d0e2d7201f0959725a6a769b6f7b9019a168ed96006479c9ac33fe4096b", + "sha256:14ed9ed1bfedd72a877807c71113deac292bf485159a29025dfdc524c326f3e1", + "sha256:163f4604e76639f728d127293d24c3e208b445b463168af3d031b92b0998bb90", + "sha256:19e2819b0b468174de25c0ceed766606a07cedeab132383f1e83b9a4e96ccb4f", + "sha256:1e2a2193d3aa5cbf5758f6d5680a52aa848e0cf611da324f71e5e48a9695cc86", + "sha256:1f3c099d3899b14e1ce52262eb82a5f5cb92157bb5106bf627b618c090a0eadc", + "sha256:214207dcc7a6221d9942f23797fe89144128a71c03632bf713d918db99bd36de", + "sha256:2325105e16d434749e1be8022f942876a936f9bece4ec41ae244e3d7fae42aaf", + "sha256:2529ddbdaa424b2c6c2eb668ea684dd6b75b839d0ad4b21aad60c168269478d7", + "sha256:256d431fe4583c5f1e0f2e9c4d9c22f3a04ae96009b8cfa096da3a8723db0a16", + "sha256:25bb96338512e2f46f615a2bb7c6012fe92a4a5ebd353e5020836a7e33120349", + "sha256:2e87f1926e91855ae61769ba3e3f7315120788c099677e0842e697b0bfb659f2", + "sha256:2fc6af8e39f7496047c7876314f4317736eac82bf85b54c7c76cf1a6f8e35d98", + "sha256:3157126b028c074951839233647bd0e30df77ef1fedd801b48bdcad242a60f4e", + "sha256:32c9b4878f48be3e75808ea7e499d6223b1eea6d54c487a66bc10a1871e3dc6a", + "sha256:32ed748ff9ac682eae7859790d3044b50e3076c7d80e17a44239683769ff485e", + "sha256:3501621d5e86f1a88521ea65d5cad0a0834c77b26f193747615b7c911e5422d2", + "sha256:437c33561edb6eb504b5a30203daf81d4a9b727e167e78b0854d9a4e18e8950b", + "sha256:48d39b1824b8d6ea7de878ef6226efbe0773f9c64333e1125e0efcfdd18a24c7", + "sha256:4ac3fcf9a2d369bd075b2c2965544036a27ccd277fc3c04f708338cc57533081", + "sha256:4ccfd74957ef53fa7380aaa1c961f523d582cd5e85a620880ffabd407f8202c0", + "sha256:52b05e21ff05729fbea9bc20b3a791c3c11da61649ff64cce8257c82a020466d", + "sha256:5389445f0173c197f4a3613713b5fb3f3879df1ded2a1a2e4bc4b5b9c5441b7e", + "sha256:5c5e7d2e300d5cb3b2693b6d60d3e8c8e7dd4ebe27cd17c9cb57020cac0acb80", + "sha256:5d26547423e5e71dcc562c4acdc134b900640a39abd9066d7326a7cc2324c530", + "sha256:5dd7106d064d05896ce28c97da3f46caa442fe5a43bc26dfb258e90853b39b44", + "sha256:5f8cb1329f42fadfb40d6211e5ff568d71ab49be36e759345f91c69d1033d633", + "sha256:61d5541f27533f803a941d3a3f8a3d10ed48c12cf918f557efcbf3cd04ef265c", + "sha256:639556758c36093b35e2e368ca485dada6afc2bd6a1b1207d85ea6dfc3deab27", + "sha256:641cf2e3447c9ecff2f7aa6e9eee9eaa286ea65d57b014543a4911ff2799d08a", + "sha256:6aed763b6a1b28c46c055692836879328f0b334a6d61572ee4113a5d0c859872", + "sha256:6e2a2d6749e1ff2c9c76a72c6530d5baa601205b14e441e6d98011000f47a7ac", + "sha256:7243c5a6523c5cfeca76e063efa5f6a656d1d74c8b1fc64b2cd1e84e507f7e2a", + "sha256:76b34c12b013d813e6cb325e6bd4f9c984db27758b16085926bbe7ceeaace626", + "sha256:781b5dd1db18c9e9eacc419027b0acb5073bdec9de1675c0be25ceb10e2ad133", + "sha256:7c611345bbe7cb44aabb877cb94b63e86f2d0db03e382667dbd037866d44b4f8", + "sha256:83b78c680d4b15d33042d330c2fa31813ca3974197bddb3836a5c635a5fd013f", + "sha256:84e87a7d75fa36839a3a432286d719975362d230c70ebfa0948549cc38bd5b46", + "sha256:89b3857652183b8206a891168af47bac10b970d275bba1f6ee46565a758c078d", + "sha256:8cd1a0644ccaf27e9d2f6d9c9474faabee21f0578fe85225cc5af9a61e1653df", + "sha256:8de4d42dffd5ced9117af2ce66ba8722402541a3aa98ffdf78dde92badb68932", + "sha256:94a7bb972178a8bfc4055db80c51efd24baefaced5e51c59b0d598a004e8305d", + "sha256:98aa8325c7f47183b45588af9c434533196e241be0a4e4ae2190b06d17675c02", + "sha256:9e658d1373c424457ddf6d55ec1db93c280b8579276bebd1f72f113072df8a5d", + "sha256:9f49585f4abadd2283034fc605961f40c638635bc60f5162276fec075f2e37a4", + "sha256:9f6cad071960ba1914fa231677d21b1b4a3acdcce463cee41ea30bc82e6040cf", + "sha256:a0cc398350ef31167e03f3ca7c19313d4e40a662adcb98a88755e4e861170bdd", + "sha256:a1133414b771619aa3c3000701c11b2e4624a7f492f12f256aedde97c28331a2", + "sha256:a33273a541f1e1a8219b2a4ed2de355848ecc0254264915b9290c8d2de1c74e1", + "sha256:a3c0ff89fe40a152e77b191b83282c9664357dce3004032d42e68c514ceff27e", + "sha256:a49994481b99cd7dedde07f2e7e93b1d86c01c0fca1c32aded18f10695ae17eb", + "sha256:abf5b17bc0cf626a8a497d89ac691308dbd825d2ac372aa990b1ca114e470151", + "sha256:ac380cacdd3b183338ba63a144a34e9044520a6fb30c58aa14077157a033c13e", + "sha256:ad81012b24b88aad4c70b2cbc2dad84018783221b7f923e926f4690ff8569da3", + "sha256:b2c00ad31fbc2cbac85d7d0fcf90853b2ca2e69d825a2d3f3edb842ef1544a2c", + "sha256:b4c153863dd6569f6511845922c53e39c8d61f6e81f228ad5443e690fca403de", + "sha256:b4f3d66dd0354b79761481fc15bdafaba0b9d9076f1f42cc9ce10d7fcbda205a", + "sha256:b99aac6bb2c37db336fa03a39b40ed4ef2818bf2dfb9441458165ebe88b793af", + "sha256:b9f6392d98c0bd70676ae41474e2eecf4c7150cb419237a41f8f96043fcb81d1", + "sha256:c537da54ce4ff7c15e78ab1292e5799d0d43a2108e006578a57f531866f64025", + "sha256:ca23db5fb195b5ef4fd1f77ce26cadefdf13dba71dab14dadd29b34d457d7c44", + "sha256:cc826b9a8176e686b67aa60fd6c6a7047b0461cae5591ea1dc73d28f72332a8a", + "sha256:cca83a629f77402cfadd58352e394d79a61c8015f1694b83ab72237ec3941f88", + "sha256:cf8d370b2fea27fb300825ec3984334f7dd54a581bde6456799ba3776915a656", + "sha256:d1175b0e0d6037fab207f05774a176d71210ebd40b1c51f480a04b65ec5c786d", + "sha256:d1996ee1330e245cd3aeda0887b4409e3930524c27642b046e4fae88ffa66c5e", + "sha256:d5a36953389f35f0a4e88dc796048829a2f467c9197265504593f0e420571547", + "sha256:da51d8928ad8b4244926fe862ba1795f0b6e68ed8c42cd2f822d435db9c2a8f4", + "sha256:e16e7297f29a544f49340012d6fc08cf14de0ab361c9eb7529f6a57a30cbfda1", + "sha256:e25b11a0417475f093d0f0809a149aff3943c2c56da50fdf2c3c88d57fe3dfbd", + "sha256:e4371591e621579cb6da8401e4ea405b33ff25a755874a3567c4075ca63d56e2", + "sha256:e653d36b1bf48fa78c7fcebb5fa679342e025121ace8c87ab05c1cefd33b34fc", + "sha256:e7d91a230c7f8af86c904a5a992b8c064b66330544693fd6759c3d6162382ecf", + "sha256:e851e6363d0dbe515d8de81fd544a2c956fdec6f8a049739562286727d4a00c3", + "sha256:ef7d48207926edbf8b16b336f779c557dd8f5a33035a85db9c4b0febb0706817", + "sha256:f7716f7e7138252d88607228ce40be22660d6608d20fd365d596e7ca0738e019", + "sha256:facaf11f21f3a4c51b62931feb13310e6fe3475f85e20d9c9fdce0d2ea561b87" ], - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.0" + }, + "niquests": { + "hashes": [ + "sha256:68e0a7e9f338466b3606945fffd11f75e3c90af7498aa9336ef03812323b7e36", + "sha256:86e484c2c60444aa96069c15f6295af6e25a8bad50781e1326df1b5c7ab48339" + ], + "markers": "python_version >= '3.7'", + "version": "==3.14.0" }, "numpy": { "hashes": [ - "sha256:0391ea3622f5c51a2e29708877d56e3d276827ac5447d7f45e9bc4ade8923c52", - "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d", - "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693", - "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d", - "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8", - "sha256:1ad78ce7f18ce4e7df1b2ea4019b5817a2f6a8a16e34ff2775f646adce0a5027", - "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304", - "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5", - "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5", - "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50", - "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a", - "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94", - "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021", - "sha256:39261798d208c3095ae4f7bc8eaeb3481ea8c6e03dc48028057d3cbdbdb8937e", - "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe", - "sha256:3c2ec8a0f51d60f1e9c0c5ab116b7fc104b165ada3f6c58abf881cb2eb16044d", - "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890", - "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8", - "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe", - "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1", - "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e", - "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b", - "sha256:596140185c7fa113563c67c2e894eabe0daea18cf8e33851738c19f70ce86aeb", - "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b", - "sha256:5ebeb7ef54a7be11044c33a17b2624abe4307a75893c001a4800857956b41094", - "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea", - "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c", - "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636", - "sha256:783145835458e60fa97afac25d511d00a1eca94d4a8f3ace9fe2043003c678e4", - "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba", - "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a", - "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d", - "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95", - "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2", - "sha256:95172a21038c9b423e68be78fd0be6e1b97674cde269b76fe269a5dfa6fadf0b", - "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f", - "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1", - "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532", - "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082", - "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2", - "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0", - "sha256:cbc6472e01952d3d1b2772b720428f8b90e2deea8344e854df22b0618e9cce71", - "sha256:cdfe0c22692a30cd830c0755746473ae66c4a8f2e7bd508b35fb3b6a0813d787", - "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef", - "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d", - "sha256:d5b47c440210c5d1d67e1cf434124e0b5c395eee1f5806fdd89b553ed1acd0a3", - "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b", - "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf", - "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020", - "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76", - "sha256:e37242f5324ffd9f7ba5acf96d774f9276aa62a966c0bad8dae692deebec7716", - "sha256:ed2cf9ed4e8ebc3b754d398cba12f24359f018b416c380f577bbae112ca52fc9", - "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb", - "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610", - "sha256:f6b3dfc7661f8842babd8ea07e9897fe3d9b69a1d7e5fbb743e4160f9387833b" + "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", + "sha256:0d54974f9cf14acf49c60f0f7f4084b6579d24d439453d5fc5805d46a165b542", + "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f", + "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", + "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0", + "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7", + "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", + "sha256:218f061d2faa73621fa23d6359442b0fc658d5b9a70801373625d958259eaca3", + "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146", + "sha256:2fa8fa7697ad1646b5c93de1719965844e004fcad23c91228aca1cf0800044a1", + "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", + "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc", + "sha256:4ba5054787e89c59c593a4169830ab362ac2bee8a969249dc56e5d7d20ff8df9", + "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592", + "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00", + "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", + "sha256:7051ee569db5fbac144335e0f3b9c2337e0c8d5c9fee015f259a5bd70772b7e8", + "sha256:7716e4a9b7af82c06a2543c53ca476fa0b57e4d760481273e09da04b74ee6ee2", + "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392", + "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb", + "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8", + "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", + "sha256:8146f3550d627252269ac42ae660281d673eb6f8b32f113538e0cc2a9aed42b9", + "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0", + "sha256:892c10d6a73e0f14935c31229e03325a7b3093fafd6ce0af704be7f894d95687", + "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", + "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", + "sha256:9eeea959168ea555e556b8188da5fa7831e21d91ce031e95ce23747b7609f8a4", + "sha256:a0258ad1f44f138b791327961caedffbf9612bfa504ab9597157806faa95194a", + "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39", + "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4", + "sha256:a84eda42bd12edc36eb5b53bbcc9b406820d3353f1994b6cfe453a33ff101775", + "sha256:ab2939cd5bec30a7430cbdb2287b63151b77cf9624de0532d629c9a1c59b1d5c", + "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd", + "sha256:adf8c1d66f432ce577d0197dceaac2ac00c0759f573f28516246351c58a85020", + "sha256:b4adfbbc64014976d2f91084915ca4e626fbf2057fb81af209c1a6d776d23e3d", + "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24", + "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", + "sha256:bd3ad3b0a40e713fc68f99ecfd07124195333f1e689387c180813f0e94309d6f", + "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba", + "sha256:cf28633d64294969c019c6df4ff37f5698e8326db68cc2b66576a51fad634880", + "sha256:d0f35b19894a9e08639fd60a1ec1978cb7f5f7f1eace62f38dd36be8aecdef4d", + "sha256:db1f1c22173ac1c58db249ae48aa7ead29f534b9a948bc56828337aa84a32ed6", + "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854", + "sha256:df2f57871a96bbc1b69733cd4c51dc33bea66146b8c63cacbfed73eec0883017", + "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", + "sha256:e642d86b8f956098b564a45e6f6ce68a22c2c97a04f5acd3f221f57b8cb850ae", + "sha256:e9e0a277bb2eb5d8a7407e14688b85fd8ad628ee4e0c7930415687b6564207a4", + "sha256:ea2bb7e2ae9e37d96835b3576a4fa4b3a97592fbea8ef7c3587078b0068b8f09", + "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", + "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", + "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee", + "sha256:f4162988a360a29af158aeb4a2f4f09ffed6a969c9776f8f3bdee9b06a8ab7e5", + "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", + "sha256:f7de08cbe5551911886d1ab60de58448c6df0f67d9feb7d1fb21e9875ef95e91" ], "markers": "python_version == '3.11'", - "version": "==2.2.3" + "version": "==2.2.4" + }, + "opensearch-py": { + "hashes": [ + "sha256:52c60fdb5d4dcf6cce3ee746c13b194529b0161e0f41268b98ab8f1624abe2fa", + "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda" + ], + "index": "pypi", + "version": "==2.8.0" }, "paho-mqtt": { "hashes": [ @@ -572,205 +833,228 @@ }, "propcache": { "hashes": [ - "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4", - "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4", - "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", - "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f", - "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9", - "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", - "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e", - "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6", - "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf", - "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034", - "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d", - "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16", - "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30", - "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba", - "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95", - "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d", - "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae", - "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348", - "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2", - "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", - "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce", - "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54", - "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629", - "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54", - "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1", - "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b", - "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf", - "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b", - "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587", - "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097", - "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea", - "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24", - "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7", - "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541", - "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6", - "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634", - "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3", - "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d", - "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034", - "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465", - "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2", - "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf", - "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1", - "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04", - "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5", - "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583", - "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb", - "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b", - "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c", - "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958", - "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc", - "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4", - "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82", - "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e", - "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce", - "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9", - "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518", - "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536", - "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505", - "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052", - "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff", - "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1", - "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f", - "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681", - "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347", - "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af", - "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246", - "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787", - "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", - "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f", - "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439", - "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3", - "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6", - "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca", - "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec", - "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d", - "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3", - "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16", - "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717", - "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6", - "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd", - "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212" + "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e", + "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b", + "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf", + "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b", + "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5", + "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c", + "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c", + "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a", + "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf", + "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8", + "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5", + "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42", + "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035", + "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0", + "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e", + "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46", + "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d", + "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24", + "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d", + "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de", + "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf", + "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7", + "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371", + "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833", + "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259", + "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136", + "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25", + "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005", + "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef", + "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7", + "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f", + "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53", + "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0", + "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb", + "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566", + "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a", + "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908", + "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf", + "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458", + "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64", + "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9", + "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71", + "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b", + "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5", + "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037", + "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5", + "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894", + "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe", + "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757", + "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3", + "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976", + "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6", + "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641", + "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7", + "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649", + "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120", + "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd", + "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", + "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e", + "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229", + "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c", + "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7", + "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111", + "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654", + "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f", + "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294", + "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da", + "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f", + "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7", + "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0", + "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073", + "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7", + "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11", + "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f", + "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27", + "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70", + "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7", + "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519", + "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5", + "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180", + "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f", + "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee", + "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18", + "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815", + "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e", + "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a", + "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7", + "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6", + "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c", + "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc", + "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8", + "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98", + "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256", + "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5", + "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744", + "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723", + "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277", + "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5" ], "markers": "python_version >= '3.9'", - "version": "==0.2.1" + "version": "==0.3.1" + }, + "pycparser": { + "hashes": [ + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + ], + "markers": "python_version >= '3.8'", + "version": "==2.22" }, "pydantic": { "hashes": [ - "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", - "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236" + "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", + "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8" ], "index": "pypi", - "version": "==2.10.6" + "version": "==2.11.1" }, "pydantic-core": { "hashes": [ - "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278", - "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", - "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", - "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f", - "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", - "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", - "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54", - "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630", - "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", - "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", - "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", - "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", - "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", - "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", - "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", - "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", - "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", - "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd", - "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", - "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", - "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", - "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", - "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", - "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", - "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", - "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", - "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", - "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", - "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", - "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", - "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", - "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf", - "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", - "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", - "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76", - "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362", - "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", - "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", - "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320", - "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118", - "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96", - "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", - "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046", - "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", - "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", - "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", - "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", - "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67", - "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", - "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", - "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35", - "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", - "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", - "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b", - "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", - "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", - "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", - "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145", - "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", - "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", - "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", - "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", - "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", - "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", - "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5", - "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", - "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", - "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", - "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", - "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da", - "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", - "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", - "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993", - "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656", - "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4", - "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", - "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb", - "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d", - "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", - "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e", - "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", - "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc", - "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a", - "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9", - "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506", - "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b", - "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1", - "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", - "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", - "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", - "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", - "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", - "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", - "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", - "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308", - "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2", - "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228", - "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b", - "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", - "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad" + "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", + "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", + "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", + "sha256:085d8985b1c1e48ef271e98a658f562f29d89bda98bf120502283efbc87313eb", + "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", + "sha256:0bcf0bab28995d483f6c8d7db25e0d05c3efa5cebfd7f56474359e7137f39856", + "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", + "sha256:14229c1504287533dbf6b1fc56f752ce2b4e9694022ae7509631ce346158de11", + "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", + "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", + "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", + "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", + "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", + "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", + "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", + "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", + "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", + "sha256:26bc7367c0961dec292244ef2549afa396e72e28cc24706210bd44d947582c59", + "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", + "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", + "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", + "sha256:31860fbda80d8f6828e84b4a4d129fd9c4535996b8249cfb8c720dc2a1a00bb8", + "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", + "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", + "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", + "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", + "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", + "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", + "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", + "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", + "sha256:4f1ab031feb8676f6bd7c85abec86e2935850bf19b84432c64e3e239bffeb1ec", + "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", + "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", + "sha256:58c1151827eef98b83d49b6ca6065575876a02d2211f259fb1a6b7757bd24dd8", + "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", + "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", + "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", + "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", + "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", + "sha256:5f72914cfd1d0176e58ddc05c7a47674ef4222c8253bf70322923e73e14a4ac3", + "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", + "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", + "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", + "sha256:64672fa888595a959cfeff957a654e947e65bbe1d7d82f550417cbd6898a1d6b", + "sha256:68504959253303d3ae9406b634997a2123a0b0c1da86459abbd0ffc921695eac", + "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", + "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", + "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", + "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", + "sha256:7419241e17c7fbe5074ba79143d5523270e04f86f1b3a0dff8df490f84c8273a", + "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", + "sha256:7a25493320203005d2a4dac76d1b7d953cb49bce6d459d9ae38e30dd9f29bc9c", + "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", + "sha256:7c9c84749f5787781c1c45bb99f433402e484e515b40675a5d121ea14711cf61", + "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", + "sha256:82a4eba92b7ca8af1b7d5ef5f3d9647eee94d1f74d21ca7c21e3a2b92e008358", + "sha256:89670d7a0045acb52be0566df5bc8b114ac967c662c06cf5e0c606e4aadc964b", + "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", + "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", + "sha256:91301a0980a1d4530d4ba7e6a739ca1a6b31341252cb709948e0aca0860ce0ae", + "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", + "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", + "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", + "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", + "sha256:a66d931ea2c1464b738ace44b7334ab32a2fd50be023d863935eb00f42be1778", + "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", + "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", + "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", + "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", + "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", + "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", + "sha256:b716294e721d8060908dbebe32639b01bfe61b15f9f57bcc18ca9a0e00d9520b", + "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", + "sha256:ba95691cf25f63df53c1d342413b41bd7762d9acb425df8858d7efa616c0870e", + "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", + "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", + "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", + "sha256:ce72d46eb201ca43994303025bd54d8a35a3fc2a3495fac653d6eb7205ce04f4", + "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", + "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", + "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", + "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", + "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", + "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", + "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", + "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", + "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", + "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", + "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", + "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", + "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", + "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", + "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", + "sha256:f200b2f20856b5a6c3a35f0d4e344019f805e363416e609e9b47c552d35fd5ea", + "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", + "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", + "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", + "sha256:fc53e05c16697ff0c1c7c2b98e45e131d4bfb78068fffff92a82d169cbb4c7b7", + "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365" ], - "markers": "python_version >= '3.8'", - "version": "==2.27.2" + "markers": "python_version >= '3.9'", + "version": "==2.33.0" }, "python-dateutil": { "hashes": [ @@ -782,10 +1066,111 @@ }, "pytz": { "hashes": [ - "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", - "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e" - ], - "version": "==2025.1" + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" + ], + "version": "==2025.2" + }, + "qh3": { + "hashes": [ + "sha256:0107f576a0524421e1b0f9e0437d2881a1835b1b6105eadd7ea0c1c9bf2da917", + "sha256:06159707895c606a321ccb5630347a2d2a44ee584f22945e5b22b0ad34f21ec8", + "sha256:06255835f99ea1af9e5d358056011686fcccbafaba893454027daa62ab6f701f", + "sha256:09b2305a954e61a9ed8b46a7a45f54e8d95ef870a47d5fd1836e14c7600d3b92", + "sha256:0a51dcffae03a89ddbab1884860569e0d1dbbf95deee47457c1fd29b4ac8d220", + "sha256:0a5d1cd881b7d43481ad60262cf3390a555e0e51751bc2af70ba4a612487e797", + "sha256:0e1c273660f9b8511c22d0b082137556e46d6a7eccf132bd82f95d29f90488b2", + "sha256:0e540cc7e7da65da30381bdb73a789a8635c6aaef98688d904eee3bc587654a5", + "sha256:10ed818f47dc522350a12641e8f2bea19ff824f8ce373c23a8e594b3481fd7a4", + "sha256:195b4ad58cf5a8da218e2368d34f47628c14581f3cc9863fc0406b32e137f3a6", + "sha256:1a80d07249c7ccbaa57bb9015b5ead0ead7ac1940cd5483548dfe56db99ce7a4", + "sha256:1cf0b18823801078d2294a0356abc2be34b4a224bea863a87029c1c97d6c34e0", + "sha256:1fac2ab4b8a2e50894b54a19416cd363defe0fb33f52754686ea58999f98dfc5", + "sha256:205cdaea9da8881b31b76eb6da5b88c9558ba96bc16a3ecf11333098ac7f3859", + "sha256:2294e78bcc40728a3a772df0f8ecf8b8756616d06dd001029016876aa4e5c9de", + "sha256:235236ab195d34e7cd18d186e46b7a4f8aceafe246bf36b42913f72627ded414", + "sha256:25eef1f2be50d79d23e01a567c719e46e4892518a5ccc96685fcb4746357320b", + "sha256:2ae147b756c3adf59699756feb9e07d4a69674f57b4e13d6c25f9d1dc3c8707c", + "sha256:2c9cdd7ea49c79b671e7de35dad61d2aa91920e2498d0c6dfa932d5e05070a5e", + "sha256:2dc9f269d7316b0a44e61ae7a11ffd8daa800b3f5ba773de2e9d8c4ee636a896", + "sha256:2f94d69edb0070ef4ec414deabfc2369aa2100b11bf4a4f2f393f2c28c4bc7ba", + "sha256:311da331e31c55afc3f4f4f2ba9d07a1d700ffb7db5aa4f58300b9f56f2523dc", + "sha256:3578844a9ff4c342a409d010f909782afc52a31680876f7fab65bf133aa3f4db", + "sha256:4032c2898b4c0ff7a25cf7d68c3b1f2abdcaf4f25cc8b6802a941a842f9a95b6", + "sha256:40abd150eddfa0884c139bd281e87ff920d4cd52d685fc4ef25ddcc77ff7a220", + "sha256:43e32602651d07f8a0860ba0a45d8c8fe9ccd537030e7632d1258f7b84881416", + "sha256:45a21d25fe17168f4db09fcaabee5dd171763ad1bd8753c257297837f5ba9197", + "sha256:45bfbb126e31ecf63ef74c249d38d07e149c0663b4a191cf9e2e3445a80758d5", + "sha256:4745667c9956bcfd74ff677edd4c73d6cb578b6b47c5fb3d246aaa223dd6a004", + "sha256:4936a5d8915866b4f08ab18018f41ed93a2593788ad0a80796aada2e23d402e5", + "sha256:4a45a9698b3bcae05f91356f50df8dab3c3fdef3187548b9c4a396a6eb6760b5", + "sha256:4b84c1ca283278e2e22a3b9e2ce8ea55c0a1797d6e86255640a1b6293fe18b2a", + "sha256:4dc88397ed7f3b46f542f87e19050a7f82267225009ce65651ac44cb55b204b1", + "sha256:4e10a872077373c71d7938fb1a7ae0561f2e79aad2b1b5323dbb6325a389041a", + "sha256:4f1b5dcb4d9da5b441e0b14216b816be7b5b5d080c2ccb957adf84266411ff6b", + "sha256:50d25182d598312197f500a65acebf5430391764e6ffcdb73d96e80c5dd06fc7", + "sha256:529c5b9e27fced27befce26e2699eca3110c576f6427dfbd26e30b7666b2d6d1", + "sha256:571da625b22e953731307539b44b2177f6ab13b6142d7698c0f28b9379ae1be6", + "sha256:5a9de89e2480b385a99613798d375e69a0a53d4575bd74b133307c8e83a84751", + "sha256:5bcc46cf89cb1036c2d029c01f360c82180329997a75728b20dc205f34114327", + "sha256:5dfa6238a6236f2bb3ecaac9befd23cee0bcbb9e497003fb3aef875e19325c61", + "sha256:6342b961b18037e3df8692e8914c576816a966bf29f913ee2728e7e838bde9bd", + "sha256:65e112c175a0b0328822dd0d19ead9ef1d7925359d154fb52e46b080945eef38", + "sha256:6f8a2b15c4dd58133e92f95d4312efd09b87ec15b881885629dff70e89f1e751", + "sha256:726f749444d1cc73c1bf221343dc6fdbde2541ffe30860d2d5ef6e310a1f5478", + "sha256:742f39cd807df31c21e035aec63f6f61e139a60545cffb16e8e87f61609d7cba", + "sha256:7840c18ec27aa08ecdd8ff23df348c124378c6f3edf9a0e02b16a5a4ce504c89", + "sha256:79d1de24d3c7345719af8333b64f19a8777dd50a059851bfcfa583c7109eddf2", + "sha256:7ba9303c5334d64b547483be92c4bbacd37964ff3abd0b1e8c82c63ec6f7b3ec", + "sha256:85587d9dfbd2f7f8622cf57f3c1a19cee441b5607a982cdf4c08ef38d45d5a36", + "sha256:8711b86e447e689d1b693419708b6ad64bf0c57091b94a3f65c6d4bd7cfb7d9a", + "sha256:877edc4db25309d86af07d992926394936f491cce84fce439961729552e942fe", + "sha256:8bb17669e362d3456bebd5c69abb0c26e8ab29c10894f123c715b0217aece479", + "sha256:8bb17a1e50e35a8d07cab784caea68b33f739391ccb5e3161afb9db0bde8faf4", + "sha256:8d4640a6bb3aa29797bdcf0c5bae4e86da5f2fbf84b67a7fad549fa34c19aa98", + "sha256:90697f3d9e4b3ddccfb31b40637bac6d44b39288cd57f78e51ff13e70916eccc", + "sha256:90f127f57c00b111ea3ffd95f4c12ad83efebd10310fd718d66771dd64e568f1", + "sha256:95f8f70bca1e880da7559ef38b7f1778a3b39b586fc829b8a7e989e912aa988f", + "sha256:9a60c102a01dfa8c5d737499c9a5d5e7c2b6642009c9b80b27f228ec50ce6fb0", + "sha256:9c7f1821ec749ea29bd9d079e4f13a552371731d0b664962a60cbb2f31d571b5", + "sha256:9f81ee66fadedbfd4d5c49e64151db3b6f353b041ddf5ab0b151340a4467e038", + "sha256:9f8e530e29e1afe9231b1100645aa5cc240b823c0e4162f70046270a3559400c", + "sha256:a0c647db3f156e8c94a63c1fa0fc4f2ce8b70f0eb12f2726e6c19493198b1e99", + "sha256:a0cda60607ab4ffc14fa8425ea7c9ae78ad60923c3c8be94d19c14f83198b1cf", + "sha256:a5bff397d49da302b5afbdf244dd7ca480a827f5de856d957df05dfd7e73b490", + "sha256:a94bd391b955b24948b2986845f9c6ad8abc709c2d57d0515daeacf16a2a3a4c", + "sha256:ad4572bd37c1a6a7a12ff47da4f3578a13e3c8ee85a1f02d2435dfdc6d9ed394", + "sha256:b13b7de1686f1b5da7526dc4f0de410a685f5cb654e984b09ddd8d14be6fffc0", + "sha256:b1724c43c5c0d08b68c3407467e07794b9adf153b6de8300d61883e8d95fa640", + "sha256:b27d29cb718df9ed006f8c75a89dd90534437761b2477dc7a4145bde0daa60fc", + "sha256:b3afa3a78b0f011ff5a09dea37d74fcea9269b318d2828f18b2fbf9dde625a71", + "sha256:bd6a61007e678284178bb00931af59f686a2a55797505e0886241050ec5c243c", + "sha256:befeca45fd7787c08a3286fb72caaccfa4c3962760981dfeb0992f5ba9be5cb2", + "sha256:c2d31b8233f406e00f180e221986f436765c3bb06839e72c898feca31fef1d4e", + "sha256:c3e2518ce442b70314892a594e21157deb13fbc436f77ad6555439cfd9912035", + "sha256:c8d5fbee607db24ef6c7b0bd08c21226d10782df4149b9d6f1f1516c7c85092b", + "sha256:cc2cc804998e852bdffcc87e8d008043ffa85efe6d3516d9784714d709f14774", + "sha256:cd8a681107c6118f60a0714671cec7b301533f25984a5c898e547a33a01af75c", + "sha256:d056831ebf3fa8116672ae970ad19a9f5f1427a2217cd0e01c1eaac5f8222668", + "sha256:d5ac3e8e3f66ff88819205dbc67e6f771cbb80529325ca9f3bc03fa00c5c83aa", + "sha256:dba15ca2da7859300ae79d2ea2eb8bb0eb827b93a2f104981783add16a97058a", + "sha256:de6cabb89248b60ea9bb9d7848de78dfb824abfdc15f52448a8efe821dd7d559", + "sha256:e02f6d1cc2005b847176dd8770fdfe90f04a34a3f094b79a8369bde0aa8f6a04", + "sha256:e514bd4b27c953c46485b2be0ecd2421aa196c5a0cd7d67f1ccec16a56b00507", + "sha256:e53464124379764f982a69f5ab34d0d5c527e8ac1e788db86a25f79045e5b18d", + "sha256:e9cf59660a543bef86de457c671c1d78ad2d88c53bb9eb3fce6ce0cb9729d490", + "sha256:edfc1bc732bc5e62fdaea268a541eb442d5e04927cb27dfd8e92ef07213658d2", + "sha256:ee8e7a66be70a18f5e0558f2f6a89e39c608f87b027234848f76a6699975dcf8", + "sha256:effb7072efef7dca10a98c24be0cc882a40edc78e293b41f5b6dc7f1952215ed", + "sha256:f04e4ee7e3c123ac7f21cee6f819cfa9b5a376e656257dfa7a4d133b3590bdd9", + "sha256:f0531c7abe963affebd3fb6cf9ea87eb8c63a0240535d81d0223945bd41be254", + "sha256:f5afd1c216315682a6bbf606618de0e3817ed8eeafc27ad7660ef2f581d4fd46", + "sha256:f93d3c74e00268ac6042c080653a34d0f0e8903697fd8dc480c1e3de81c90faf", + "sha256:fbc4e6452cc48c3e1398fe930349e2ec9ad76a2c00e729f3e797700c2f0646e6", + "sha256:fc73fc2889a01a43737c7a7c7fb9ee13aa56065b22abbed0e787cc58a3747808" + ], + "markers": "python_version < '3.12' and (platform_python_implementation != 'CPython' or python_full_version > '3.7.10') and (platform_system == 'Darwin' or platform_system == 'Windows' or platform_system == 'Linux') and (platform_machine == 'x86_64' or platform_machine == 's390x' or platform_machine == 'armv7l' or platform_machine == 'ppc64le' or platform_machine == 'ppc64' or platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'arm64' or platform_machine == 'ARM64' or platform_machine == 'x86' or platform_machine == 'i686') and (platform_python_implementation == 'CPython' or platform_python_implementation == 'PyPy')", + "version": "==1.4.2" }, "requests": { "hashes": [ @@ -821,28 +1206,148 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", + "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.0" }, "tzdata": { "hashes": [ - "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", - "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639" + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" ], "markers": "python_version >= '2'", - "version": "==2025.1" + "version": "==2025.2" }, "urllib3": { "hashes": [ "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" ], - "markers": "python_version >= '3.9'", + "markers": "python_version >= '3.10'", "version": "==2.3.0" }, + "urllib3-future": { + "hashes": [ + "sha256:255fa9ba873e9045a5fb2e9838e2b108be35519c29e7f3accff13ee4c417a1cf", + "sha256:7243b5bb8d8cdbcbff342bc31b885e35662c4dcfd94d097473cce1bd02944cbf" + ], + "markers": "python_version >= '3.7'", + "version": "==2.12.914" + }, + "verlib2": { + "hashes": [ + "sha256:2862f19528db400d130253a2b71c7c3616ee14e1d54bf6833bc0929d2cddd141", + "sha256:cf8e2be044b834a2670f2d4c20a93cfc674933c0070543a6f61d531439cca200" + ], + "markers": "python_version >= '3.6'", + "version": "==0.3.1" + }, + "wassima": { + "hashes": [ + "sha256:10508102696d5e2cf4df6942a8ae251c136a49dc32591e9c3f7dd007f5ea1c2f", + "sha256:1102836ba373912537eba891e7e5893532d4ee915ee2486e981b73f925f63c37", + "sha256:11887557464e0c3f9694fb16406bb56c1fb1566178cd04bfb5b4624fad183b31", + "sha256:12c855cc5b96a2ac32d405ab7de1563fc91be54108b4fb16b06d125d07ea892b", + "sha256:134e863b692c35afe8f5ccbe8082fa39963804e20439a4c7aa98510197034704", + "sha256:17f129f4d36591772d906bcc893b76b236363fda61b575067ddfa8250f84ad30", + "sha256:17f132ffbab294902f8740708f27fd995ea04182fe4b4fde20be563f8a010715", + "sha256:18bc78b2230c6f1f9ddbeb6ca38439fea4cc8f60836af4f3538ed259e60e5eb8", + "sha256:194c3fad38603618dec03307d10a4ece852516df56560e04fb2562506f79c175", + "sha256:1b18ec743ab98dcbfc221749026b23fc573891651342f20971e53bdbf56d28ae", + "sha256:1fa19a3652509edd18f693cd9c873d8f73c9d1624eae6c3bf93e561b18ae2766", + "sha256:24bdb1a2b90c215e11ed7ce82ed7eada339c7dca8e0366916e4e3215b3b9d8d3", + "sha256:27d518f0863788c826faf387326f3babb3ea95a0b908f5b3ad2bc1fcc3c5a37d", + "sha256:350b5854dfb3eeb95cd17723b0f3503de0c01454da5ae7d60f192be2009239eb", + "sha256:3b3a4c8ffa76147507f0c88c5cc8c76ef96ab93b81e49b288a3a0b94ebfb34af", + "sha256:3e00fa8ff1aef7d8aad2e1b957add6cba8549a42e415400bd72ff1b61dc9da9d", + "sha256:3f29045dd0a7c287f850f1dc3948632a2d2cf7dd7ec02271c5f248f058da5650", + "sha256:4a528244e4a0f9e01b8593b1c8a60ac1d80ce8b13fe079f44b38328e4be075e3", + "sha256:4c4f5ca102fd083aa2b05c65a1fd18175e3dc7a889525fd2964219ee3c51edef", + "sha256:52358d86195954816231d2aa8c2919b85075320b6d3ba5b96216985c3182bfa0", + "sha256:52f473233ec4d57322c6295e85b3912dc1fc400d6308a04bd427b863934aa74e", + "sha256:556cded582aef3089de889b5a6efcf6d87fabfec55d574fcc3a4ada21308d487", + "sha256:564eda7bf0420c8cbebe5e8efc15f1b27fdcb37ebc4c2f92b8461ca83381b223", + "sha256:57a0ab5aed596f129fd4ea7584336b11fbef25c07d1351e37a959901dea8728e", + "sha256:58f1fddd660da8c8f30f4b8460129e2f217c226cd1b54b1cabb6465881fd788a", + "sha256:597b0d8ba697f4319bc1f301ed31630ca783c9fe82d2a2434dd2f7f709c4e394", + "sha256:5b194f0de77a4ae7bcf217a3ccd10798e94ca430cec6307628098a61cd2ac230", + "sha256:5f5ee564f4b836ed1b70ddb187c817e8f6f1ffb521a636bb20676f07b523396b", + "sha256:601f96340e4c8071994a39a76d4278e8e1d087cf385781dba795c5334262d865", + "sha256:61bfa09f38c36f1b1e6e44e7af888bb8f9d739e86099082a3b45875651a425e2", + "sha256:67fd323b8ad0e057c06b153983d8c50f812aad979ac89b07ed6952c345f6da02", + "sha256:69cb51f629d118256da3d2373575190c7e30d3fa67c344dc655f6c8ab3e83f0d", + "sha256:6b1d7ceeede8d8eed48616d2d33ed23d2dff307d0b17c577eafdadafe86a0478", + "sha256:6b7d696155ddd7ab5739ac221e8854115d0d8171bbf805074d9484083de386aa", + "sha256:6d23e9483756b81850b82e8b7ed20fd23de22b50d6a678f765c660d4206b7ce9", + "sha256:7b0229fecc849234f2a2d11e948ac38a9bab02d201fa4d6ad43c143e18c1a66e", + "sha256:7c53050b670d702eed541503175bd5441fc4bdf3898714f8eac8c6ae9db548ac", + "sha256:7d65676f1fc138d1742f704bf490045571b9c2c48cab7d2c2076a52729c143e5", + "sha256:7db25328c40cd574e5a68ef6507c5af4d1fa2a44cb3c028ff9ca6b522f8faf32", + "sha256:83ce1b09e9eb2ae033c303b74ecc4f3186bbc0897db1d8cd9942153b0631b8e0", + "sha256:86c509900cbb90b7b75155c580b22af591b696fa059059bcdbd75bc74179df85", + "sha256:87f80d0075f0d396b73d41bb1626a2dd5607e0db4b74cb17e55d874fcd538971", + "sha256:8b719755d556649f2fbf226cf1ca8581ade114751df1facec96f94e75bffdb3c", + "sha256:8e739d4192758df6e5363791f527deb91c615d63020ee8965df4bcd1a217f9a5", + "sha256:923d3bf8770dfeb3d94bdfee1c5b5a081592de69766436a395e1e6203c19cf71", + "sha256:97772bb55cb47da3de49ca4b59309a9bd91ead730a7cfac1992932486fb41352", + "sha256:98bdfdf734144277132f34f770eeb6b0db2c4de87415f34b178adee766632f24", + "sha256:98f38b1b01e6f270b9279d76261d6f222b72ef06b025cbd4911b962bb6de4c98", + "sha256:99318b5ea78843e3c3e19cd56367216774674a99848f00a6f2dcf84e36039641", + "sha256:9c623ef06876d432dc8acc93ed3494d3453333d767b1b06bba1a016ea9d850c9", + "sha256:9d0f9720dfd0155432d23bcc3605fe5831cd0f586ede4f14ff6f3bebe8fb867a", + "sha256:9e79216760faac6395bee8ca4077a53a309312faba0f71982127ad8625861780", + "sha256:a470c908fd9baaecf41715ea3c30c57b530d598ae5e9de7e0bd532755e66bb1b", + "sha256:a634b9b79e059f45a56ff3ef6e7241662bc6f0e5a096ee6eed6770ea368e8278", + "sha256:acd8195a53d0e84ea95bdf15a2651c53b829a3ddead21b4a620b6a0c5e1ae2ff", + "sha256:addbd207df3718fc9d9de5b6c90a5e3fbe667830cf629186c9fdcafbb6578cb4", + "sha256:ae2aec9d55e108ae2d22fd0bda24450a6c13c116f9698b9e7ba2c6492c4fe715", + "sha256:af6b70ca9788964c5da5b59ca412b62db2ea7f2386a91c0117667bdd963e828c", + "sha256:afa7d60a9203db36a55b6f2868da90aaa829ab415a21fba7fa75678789aeb16f", + "sha256:b08c1931c44e3c034e645f3e3a7f4c47e8b0758fb8f09a52d1e880a307a1066f", + "sha256:b22e356914e606ff398c002b9925df4454c5deca9dbe55b3ba4a5c9b2365cf0f", + "sha256:b8c0f50397c51086df941b48057c82f85d9da000bf4fe6f4bc64c4f649b26a5b", + "sha256:bc068bcd79fe017866f536e0ad9424793220be34e3124476e17e6cb77a97e690", + "sha256:bc30f5a605a366acb7f301b3421508eaec3c1a515c960791bd776cb63d016302", + "sha256:c0d246b3f8a771578279eab9cfcb820dedefd3dd5dc0e34b37a337fe46271fc0", + "sha256:c0fee0a8593028bde17b57527b1ac21fea74f209b3522363e3ba0197ffaa6323", + "sha256:c139d5b103bb1f085d8918815d62ad946224a658ac1a7cc1b93dc44bd498ff9a", + "sha256:c25235cec12c0e38b4104268e312c9c2f3527ebc126d296cff69ea7aa13434dc", + "sha256:c7429d038dc383966c692e752010cbb4d5dab0e515f231aa01cd746aed9db359", + "sha256:c85cd2e64967c0dce2927ad7c62c090aae6d6b7f9e3a6b9fb91f58b890ea6adc", + "sha256:ca04984df012020dd846599b8555666c544982c2a91dc6135565e6708624eb71", + "sha256:cb7d43c07d58ba13736e70dc3e064496efeb1ed4475a28afb26b7a3b030b89df", + "sha256:d018e05cb61eed3050d45bd0c0ef9b75420899f6ae254e68e7f2ef26975098c9", + "sha256:d24d42881eb74729b34014e2e87f3a4d0419c43db309de2dff3f39118716865f", + "sha256:d6e17f218af856ca22c30d1a1ac58b19bccf768b8589eb8d6e45e1f1ff258404", + "sha256:d855d0be1759c5efc404c04977ee48a8b6260aef6441e72c10973924dbde5a73", + "sha256:dea0dcc0e50978ef73be8cb384694b71a6e64b46847ee7decad96dc85fbf650c", + "sha256:e1e9228049cf2442ac486a03a0d543c5dff3089a915a3e39ab809b22672e1d76", + "sha256:e26d052a248d5be2257d848d6078d932cc1fd4e8226639f550344d0a7a2b8813", + "sha256:ee6ccb8197936a308a4034c90a42b30b37c46b7cbda66101d439d6983f59b368", + "sha256:eea9c37b45e73cebb4670afd1779db138eeff0f84ffc0871d2fb90c04c8d3aa8", + "sha256:f195bf641276261e6bc5f79f52601850c9bdbff8af401483b4805dbff535ed30", + "sha256:f264827618400ebeab16708c8acf7870f693b03bfb4d7e95253eb9b35074db5c", + "sha256:f44ccd2eaa433ff1a10f70242dc33315fc192b81664696154127bdd66ad7d3b2", + "sha256:f7a6068d8857c403e105e62132a00e9d9d401bd0efbff7f8b5b5bc8ab768a2d8", + "sha256:f9886176fe4bf1ac008c02adb5bd103f1191799f1897777d203ee44f615325a5", + "sha256:fa1f38d5583d283b40f998e2f13471bfa952e0c423ff95ec2ec329f3e1898107", + "sha256:fa65494e7bd0e3ba33b3e5a5ab30c2b6e95d3d1762baaa56151a0861618dc261", + "sha256:fd7186e23963714bab3c9a2ab75d002078335110d2c9fc883c65cbce43717f26", + "sha256:fec32c22b521fcdeb9aa7dee4373b2d81ca2d3fc8edc532f3e189d6f4f6f1f81" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.2" + }, "yarl": { "hashes": [ "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", @@ -943,11 +1448,46 @@ }, "anyio": { "hashes": [ - "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", - "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a" + "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", + "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c" ], "markers": "python_version >= '3.9'", - "version": "==4.8.0" + "version": "==4.9.0" + }, + "argon2-cffi": { + "hashes": [ + "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", + "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "argon2-cffi-bindings": { + "hashes": [ + "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670", + "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f", + "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583", + "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194", + "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c", + "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a", + "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082", + "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5", + "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f", + "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7", + "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d", + "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f", + "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae", + "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", + "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86", + "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367", + "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d", + "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", + "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb", + "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e", + "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351" + ], + "markers": "python_version >= '3.6'", + "version": "==21.2.0" }, "babel": { "hashes": [ @@ -1162,109 +1702,121 @@ }, "coverage": { "hashes": [ - "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95", - "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9", - "sha256:06097c7abfa611c91edb9e6920264e5be1d6ceb374efb4986f38b09eed4cb2fe", - "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0", - "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924", - "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574", - "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702", - "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3", - "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b", - "sha256:1a936309a65cc5ca80fa9f20a442ff9e2d06927ec9a4f54bcba9c14c066323f2", - "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea", - "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f", - "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3", - "sha256:220fa6c0ad7d9caef57f2c8771918324563ef0d8272c94974717c3909664e674", - "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9", - "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0", - "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e", - "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef", - "sha256:3688b99604a24492bcfe1c106278c45586eb819bf66a654d8a9a1433022fb2eb", - "sha256:3a1e465f398c713f1b212400b4e79a09829cd42aebd360362cd89c5bdc44eb87", - "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1", - "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2", - "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703", - "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e", - "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd", - "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3", - "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4", - "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45", - "sha256:676f92141e3c5492d2a1596d52287d0d963df21bf5e55c8b03075a60e1ddf8aa", - "sha256:69e62c5034291c845fc4df7f8155e8544178b6c774f97a99e2734b05eb5bed31", - "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8", - "sha256:78f5243bb6b1060aed6213d5107744c19f9571ec76d54c99cc15938eb69e0e86", - "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6", - "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288", - "sha256:7e39e845c4d764208e7b8f6a21c541ade741e2c41afabdfa1caa28687a3c98cf", - "sha256:8161d9fbc7e9fe2326de89cd0abb9f3599bccc1287db0aba285cb68d204ce929", - "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc", - "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985", - "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3", - "sha256:aa6f302a3a0b5f240ee201297fff0bbfe2fa0d415a94aeb257d8b461032389bd", - "sha256:ace9048de91293e467b44bce0f0381345078389814ff6e18dbac8fdbf896360e", - "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879", - "sha256:b01a840ecc25dce235ae4c1b6a0daefb2a203dba0e6e980637ee9c2f6ee0df57", - "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a", - "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad", - "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba", - "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d", - "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750", - "sha256:cec6b9ce3bd2b7853d4a4563801292bfee40b030c05a3d29555fd2a8ee9bd68c", - "sha256:d1a987778b9c71da2fc8948e6f2656da6ef68f59298b7e9786849634c35d2c3c", - "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f", - "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015", - "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558", - "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f", - "sha256:e7575ab65ca8399c8c4f9a7d61bbd2d204c8b8e447aab9d355682205c9dd948d", - "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d", - "sha256:ea31689f05043d520113e0552f039603c4dd71fa4c287b64cb3606140c66f425", - "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3", - "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953", - "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827", - "sha256:f25d8b92a4e31ff1bd873654ec367ae811b3a943583e05432ea29264782dc32c", - "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f", - "sha256:f973643ef532d4f9be71dd88cf7588936685fdb576d93a79fe9f65bc337d9d73" + "sha256:02fad4f8faa4153db76f9246bc95c1d99f054f4e0a884175bff9155cf4f856cb", + "sha256:092b134129a8bb940c08b2d9ceb4459af5fb3faea77888af63182e17d89e1cf1", + "sha256:0ce92c5a9d7007d838456f4b77ea159cb628187a137e1895331e530973dcf862", + "sha256:0dab4ef76d7b14f432057fdb7a0477e8bffca0ad39ace308be6e74864e632271", + "sha256:1165490be0069e34e4f99d08e9c5209c463de11b471709dfae31e2a98cbd49fd", + "sha256:11dd6f52c2a7ce8bf0a5f3b6e4a8eb60e157ffedc3c4b4314a41c1dfbd26ce58", + "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", + "sha256:171e9977c6a5d2b2be9efc7df1126fd525ce7cad0eb9904fe692da007ba90d81", + "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", + "sha256:18f544356bceef17cc55fcf859e5664f06946c1b68efcea6acdc50f8f6a6e776", + "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", + "sha256:1e6f867379fd033a0eeabb1be0cffa2bd660582b8b0c9478895c509d875a9d9e", + "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", + "sha256:25fe40967717bad0ce628a0223f08a10d54c9d739e88c9cbb0f77b5959367542", + "sha256:264ff2bcce27a7f455b64ac0dfe097680b65d9a1a293ef902675fa8158d20b24", + "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", + "sha256:2c492401bdb3a85824669d6a03f57b3dfadef0941b8541f035f83bbfc39d4282", + "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", + "sha256:34a3bf6b92e6621fc4dcdaab353e173ccb0ca9e4bfbcf7e49a0134c86c9cd303", + "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", + "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", + "sha256:392cc8fd2b1b010ca36840735e2a526fcbd76795a5d44006065e79868cc76ccf", + "sha256:3d03287eb03186256999539d98818c425c33546ab4901028c8fa933b62c35c3a", + "sha256:44683f2556a56c9a6e673b583763096b8efbd2df022b02995609cf8e64fc8ae0", + "sha256:44af11c00fd3b19b8809487630f8a0039130d32363239dfd15238e6d37e41a48", + "sha256:452735fafe8ff5918236d5fe1feac322b359e57692269c75151f9b4ee4b7e1bc", + "sha256:4c181ceba2e6808ede1e964f7bdc77bd8c7eb62f202c63a48cc541e5ffffccb6", + "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", + "sha256:520af84febb6bb54453e7fbb730afa58c7178fd018c398a8fcd8e269a79bf96d", + "sha256:553ba93f8e3c70e1b0031e4dfea36aba4e2b51fe5770db35e99af8dc5c5a9dfe", + "sha256:5b7b02e50d54be6114cc4f6a3222fec83164f7c42772ba03b520138859b5fde1", + "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", + "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", + "sha256:7ba5ff236c87a7b7aa1441a216caf44baee14cbfbd2256d306f926d16b026578", + "sha256:7e688010581dbac9cab72800e9076e16f7cccd0d89af5785b70daa11174e94de", + "sha256:80b5b207a8b08c6a934b214e364cab2fa82663d4af18981a6c0a9e95f8df7602", + "sha256:822fa99dd1ac686061e1219b67868e25d9757989cf2259f735a4802497d6da31", + "sha256:881cae0f9cbd928c9c001487bb3dcbfd0b0af3ef53ae92180878591053be0cb3", + "sha256:88d96127ae01ff571d465d4b0be25c123789cef88ba0879194d673fdea52f54e", + "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", + "sha256:8fed429c26b99641dc1f3a79179860122b22745dd9af36f29b141e178925070a", + "sha256:9bb47cc9f07a59a451361a850cb06d20633e77a9118d05fd0f77b1864439461b", + "sha256:a6b6b3bd121ee2ec4bd35039319f3423d0be282b9752a5ae9f18724bc93ebe7c", + "sha256:ae13ed5bf5542d7d4a0a42ff5160e07e84adc44eda65ddaa635c484ff8e55917", + "sha256:af94fb80e4f159f4d93fb411800448ad87b6039b0500849a403b73a0d36bb5ae", + "sha256:b4c144c129343416a49378e05c9451c34aae5ccf00221e4fa4f487db0816ee2f", + "sha256:b52edb940d087e2a96e73c1523284a2e94a4e66fa2ea1e2e64dddc67173bad94", + "sha256:b559adc22486937786731dac69e57296cb9aede7e2687dfc0d2696dbd3b1eb6b", + "sha256:b838a91e84e1773c3436f6cc6996e000ed3ca5721799e7789be18830fad009a2", + "sha256:ba8480ebe401c2f094d10a8c4209b800a9b77215b6c796d16b6ecdf665048950", + "sha256:bc96441c9d9ca12a790b5ae17d2fa6654da4b3962ea15e0eabb1b1caed094777", + "sha256:c90e9141e9221dd6fbc16a2727a5703c19443a8d9bf7d634c792fa0287cee1ab", + "sha256:d2e73e2ac468536197e6b3ab79bc4a5c9da0f078cd78cfcc7fe27cf5d1195ef0", + "sha256:d3154b369141c3169b8133973ac00f63fcf8d6dbcc297d788d36afbb7811e511", + "sha256:d66ff48ab3bb6f762a153e29c0fc1eb5a62a260217bc64470d7ba602f5886d20", + "sha256:d6874929d624d3a670f676efafbbc747f519a6121b581dd41d012109e70a5ebd", + "sha256:e33426a5e1dc7743dd54dfd11d3a6c02c5d127abfaa2edd80a6e352b58347d1a", + "sha256:e52eb31ae3afacdacfe50705a15b75ded67935770c460d88c215a9c0c40d0e9c", + "sha256:eae79f8e3501133aa0e220bbc29573910d096795882a70e6f6e6637b09522133", + "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", + "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", + "sha256:f5f99a93cecf799738e211f9746dc83749b5693538fbfac279a61682ba309387", + "sha256:fbba59022e7c20124d2f520842b75904c7b9f16c854233fa46575c69949fb5b9" ], "index": "pypi", - "version": "==7.6.12" + "version": "==7.7.1" }, "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" + }, + "docker": { + "hashes": [ + "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", + "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" + ], + "markers": "python_version >= '3.8'", + "version": "==7.1.0" }, "docutils": { "hashes": [ @@ -1274,6 +1826,12 @@ "markers": "python_version >= '3.9'", "version": "==0.21.2" }, + "events": { + "hashes": [ + "sha256:a7286af378ba3e46640ac9825156c93bdba7502174dd696090fdfcd4d80a1abd" + ], + "version": "==0.5" + }, "furo": { "hashes": [ "sha256:6cd97c58b47813d3619e63e9081169880fbe331f0ca883c871ff1f3f11814f5c", @@ -1340,11 +1898,11 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "jaraco.classes": { "hashes": [ @@ -1372,19 +1930,19 @@ }, "jeepney": { "hashes": [ - "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806", - "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755" + "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", + "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732" ], "markers": "sys_platform == 'linux'", - "version": "==0.8.0" + "version": "==0.9.0" }, "jinja2": { "hashes": [ - "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", - "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb" + "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", + "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" ], "markers": "python_version >= '3.7'", - "version": "==3.1.5" + "version": "==3.1.6" }, "keyring": { "hashes": [ @@ -1477,6 +2035,14 @@ "markers": "python_version >= '3.7'", "version": "==0.1.2" }, + "minio": { + "hashes": [ + "sha256:5247df5d4dca7bfa4c9b20093acd5ad43e82d8710ceb059d79c6eea970f49f79", + "sha256:c06ef7a43e5d67107067f77b6c07ebdd68733e5aa7eed03076472410ca19d876" + ], + "markers": "python_version >= '3.9'", + "version": "==7.2.15" + }, "more-itertools": { "hashes": [ "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", @@ -1487,33 +2053,41 @@ }, "nh3": { "hashes": [ - "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec", - "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c", - "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6", - "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38", - "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace", - "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7", - "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b", - "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784", - "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0", - "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150", - "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776", - "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330", - "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b", - "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d", - "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5", - "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5", - "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397", - "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886", - "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b", - "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a", - "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db", - "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2", - "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a", - "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208" + "sha256:087ffadfdcd497658c3adc797258ce0f06be8a537786a7217649fc1c0c60c293", + "sha256:20979783526641c81d2f5bfa6ca5ccca3d1e4472474b162c6256745fbfe31cd1", + "sha256:2a5174551f95f2836f2ad6a8074560f261cf9740a48437d6151fd2d4d7d617ab", + "sha256:31eedcd7d08b0eae28ba47f43fd33a653b4cdb271d64f1aeda47001618348fde", + "sha256:4990e7ee6a55490dbf00d61a6f476c9a3258e31e711e13713b2ea7d6616f670e", + "sha256:55823c5ea1f6b267a4fad5de39bc0524d49a47783e1fe094bcf9c537a37df251", + "sha256:6141caabe00bbddc869665b35fc56a478eb774a8c1dfd6fba9fe1dfdf29e6efa", + "sha256:637d4a10c834e1b7d9548592c7aad760611415fcd5bd346f77fd8a064309ae6d", + "sha256:63ca02ac6f27fc80f9894409eb61de2cb20ef0a23740c7e29f9ec827139fa578", + "sha256:6ae319f17cd8960d0612f0f0ddff5a90700fa71926ca800e9028e7851ce44a6f", + "sha256:6c9c30b8b0d291a7c5ab0967ab200598ba33208f754f2f4920e9343bdd88f79a", + "sha256:713d16686596e556b65e7f8c58328c2df63f1a7abe1277d87625dcbbc012ef82", + "sha256:818f2b6df3763e058efa9e69677b5a92f9bc0acff3295af5ed013da544250d5b", + "sha256:9d67709bc0d7d1f5797b21db26e7a8b3d15d21c9c5f58ccfe48b5328483b685b", + "sha256:a5f77e62aed5c4acad635239ac1290404c7e940c81abe561fd2af011ff59f585", + "sha256:a772dec5b7b7325780922dd904709f0f5f3a79fbf756de5291c01370f6df0967", + "sha256:a7ea28cd49293749d67e4fcf326c554c83ec912cd09cd94aa7ec3ab1921c8283", + "sha256:ac7006c3abd097790e611fe4646ecb19a8d7f2184b882f6093293b8d9b887431", + "sha256:b3b5c58161e08549904ac4abd450dacd94ff648916f7c376ae4b2c0652b98ff9", + "sha256:b8d55ea1fc7ae3633d758a92aafa3505cd3cc5a6e40470c9164d54dff6f96d42", + "sha256:bb0014948f04d7976aabae43fcd4cb7f551f9f8ce785a4c9ef66e6c2590f8629", + "sha256:d002b648592bf3033adfd875a48f09b8ecc000abd7f6a8769ed86b6ccc70c759", + "sha256:d426d7be1a2f3d896950fe263332ed1662f6c78525b4520c8e9861f8d7f0d243", + "sha256:fcff321bd60c6c5c9cb4ddf2554e22772bb41ebd93ad88171bbbb6f271255286" ], "markers": "python_version >= '3.8'", - "version": "==0.2.20" + "version": "==0.2.21" + }, + "opensearch-py": { + "hashes": [ + "sha256:52c60fdb5d4dcf6cce3ee746c13b194529b0161e0f41268b98ab8f1624abe2fa", + "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda" + ], + "index": "pypi", + "version": "==2.8.0" }, "packaging": { "hashes": [ @@ -1539,6 +2113,41 @@ "markers": "python_version >= '3.8'", "version": "==2.22" }, + "pycryptodome": { + "hashes": [ + "sha256:009e1c80eea42401a5bd5983c4bab8d516aef22e014a4705622e24e6d9d703c6", + "sha256:18d5b0ddc7cf69231736d778bd3ae2b3efb681ae33b64b0c92fb4626bb48bb89", + "sha256:2988ffcd5137dc2d27eb51cd18c0f0f68e5b009d5fec56fbccb638f90934f333", + "sha256:37ddcd18284e6b36b0a71ea495a4c4dca35bb09ccc9bfd5b91bfaf2321f131c1", + "sha256:3b76fa80daeff9519d7e9f6d9e40708f2fce36b9295a847f00624a08293f4f00", + "sha256:56c6f9342fcb6c74e205fbd2fee568ec4cdbdaa6165c8fde55dbc4ba5f584464", + "sha256:87a88dc543b62b5c669895caf6c5a958ac7abc8863919e94b7a6cafd2f64064f", + "sha256:8f4f6f47a7f411f2c157e77bbbda289e0c9f9e1e9944caa73c1c2e33f3f92d6e", + "sha256:96e73527c9185a3d9b4c6d1cfb4494f6ced418573150be170f6580cb975a7f5a", + "sha256:98fd9da809d5675f3a65dcd9ed384b9dc67edab6a4cda150c5870a8122ec961d", + "sha256:9dbb749cef71c28271484cbef684f9b5b19962153487735411e1020ca3f59cb1", + "sha256:9e1bb165ea1dc83a11e5dbbe00ef2c378d148f3a2d3834fb5ba4e0f6fd0afe4b", + "sha256:a0092fd476701eeeb04df5cc509d8b739fa381583cda6a46ff0a60639b7cd70d", + "sha256:a26bcfee1293b7257c83b0bd13235a4ee58165352be4f8c45db851ba46996dc6", + "sha256:a31fa5914b255ab62aac9265654292ce0404f6b66540a065f538466474baedbc", + "sha256:a6cf9553b29624961cab0785a3177a333e09e37ba62ad22314ebdbb01ca79840", + "sha256:aec7b40a7ea5af7c40f8837adf20a137d5e11a6eb202cde7e588a48fb2d871a8", + "sha256:b4bdce34af16c1dcc7f8c66185684be15f5818afd2a82b75a4ce6b55f9783e13", + "sha256:d086aed307e96d40c23c42418cbbca22ecc0ab4a8a0e24f87932eeab26c08627", + "sha256:d21c1eda2f42211f18a25db4eaf8056c94a8563cd39da3683f89fe0d881fb772", + "sha256:d4d1174677855c266eed5c4b4e25daa4225ad0c9ffe7584bb1816767892545d0", + "sha256:e653519dedcd1532788547f00eeb6108cc7ce9efdf5cc9996abce0d53f95d5a9", + "sha256:e7514a1aebee8e85802d154fdb261381f1cb9b7c5a54594545145b8ec3056ae6", + "sha256:f02baa9f5e35934c6e8dcec91fcde96612bdefef6e442813b8ea34e82c84bbfb", + "sha256:f1ae7beb64d4fc4903a6a6cca80f1f448e7a8a95b77d106f8a29f2eb44d17547", + "sha256:f5810bc7494e4ac12a4afef5a32218129e7d3890ce3f2b5ec520cc69eb1102ad", + "sha256:f6cf6aa36fcf463e622d2165a5ad9963b2762bebae2f632d719dfb8544903cf5", + "sha256:f7a683bc9fa585c0dfec7fa4801c96a48d30b30b096e3297f9374f40c2fedafc", + "sha256:fd7ab568b3ad7b77c908d7c3f7e167ec5a8f035c64ff74f10d47a4edd043d723" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==3.22.0" + }, "pygments": { "hashes": [ "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", @@ -1557,11 +2166,11 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", - "version": "==8.3.4" + "version": "==8.3.5" }, "pytest-ordering": { "hashes": [ @@ -1572,6 +2181,14 @@ "index": "pypi", "version": "==0.6" }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0.post0" + }, "pyyaml": { "hashes": [ "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", @@ -1673,19 +2290,19 @@ }, "rich": { "hashes": [ - "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", - "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90" + "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", + "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725" ], "markers": "python_full_version >= '3.8.0'", - "version": "==13.9.4" + "version": "==14.0.0" }, "roman-numerals-py": { "hashes": [ - "sha256:91199c4373658c03d87d9fe004f4a5120a20f6cb192be745c2377cce274ef41c", - "sha256:a1421ce66b3eab7e8735065458de3fa5c4a46263d50f9f4ac8f0e5e7701dd125" + "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", + "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d" ], "markers": "python_version >= '3.9'", - "version": "==3.0.0" + "version": "==3.1.0" }, "secretstorage": { "hashes": [ @@ -1697,11 +2314,19 @@ }, "setuptools": { "hashes": [ - "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", - "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3" + "sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54", + "sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8" ], "index": "pypi", - "version": "==75.8.0" + "version": "==78.1.0" + }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.17.0" }, "sniffio": { "hashes": [ @@ -1728,11 +2353,11 @@ }, "sphinx": { "hashes": [ - "sha256:3c0a40ff71ace28b316bde7387d93b9249a3688c202181519689b66d5d0aed53", - "sha256:5b0067853d6e97f3fa87563e3404ebd008fce03525b55b25da90706764da6215" + "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", + "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3" ], "markers": "python_version >= '3.11'", - "version": "==8.2.0" + "version": "==8.2.3" }, "sphinx-basic-ng": { "hashes": [ @@ -1790,6 +2415,27 @@ "markers": "python_version >= '3.9'", "version": "==2.0.0" }, + "testcontainers-core": { + "hashes": [ + "sha256:69a8bf2ddb52ac2d03c26401b12c70db0453cced40372ad783d6dce417e52095" + ], + "markers": "python_version >= '3.7'", + "version": "==0.0.1rc1" + }, + "testcontainers-minio": { + "hashes": [ + "sha256:54d330d085c0a11fc5da0b001af87aec4dd3e814104376bf7513e8646c77442a" + ], + "index": "pypi", + "version": "==0.0.1rc1" + }, + "testcontainers-opensearch": { + "hashes": [ + "sha256:0bdf270b5b7f53915832f7c31dd2bd3ffdc20b534ea6b32231cc7003049bd0e1" + ], + "index": "pypi", + "version": "==0.0.1rc1" + }, "twine": { "hashes": [ "sha256:a47f973caf122930bf0fbbf17f80b83bc1602c9ce393c7845f289a3001dc5384", @@ -1800,20 +2446,105 @@ }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", + "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5" ], "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "version": "==4.13.0" }, "urllib3": { "hashes": [ "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" ], - "markers": "python_version >= '3.9'", + "markers": "python_version >= '3.10'", "version": "==2.3.0" }, + "wrapt": { + "hashes": [ + "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f", + "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c", + "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", + "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", + "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", + "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c", + "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", + "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", + "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8", + "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", + "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061", + "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", + "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb", + "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62", + "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984", + "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", + "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2", + "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", + "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7", + "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", + "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", + "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", + "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", + "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", + "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", + "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", + "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563", + "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a", + "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f", + "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", + "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9", + "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", + "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82", + "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9", + "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", + "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", + "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", + "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", + "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", + "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7", + "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", + "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", + "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", + "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a", + "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3", + "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a", + "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", + "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", + "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", + "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", + "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", + "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", + "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", + "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", + "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", + "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", + "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2", + "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22", + "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72", + "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061", + "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f", + "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9", + "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04", + "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", + "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9", + "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f", + "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", + "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", + "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", + "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", + "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", + "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", + "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", + "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6", + "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", + "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb", + "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119", + "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b", + "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.2" + }, "zipp": { "hashes": [ "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", diff --git a/lib/python/coverage.xml b/lib/python/coverage.xml index b23a031c5f..ba3da4f2e6 100644 --- a/lib/python/coverage.xml +++ b/lib/python/coverage.xml @@ -1,14 +1,14 @@ <?xml version="1.0" ?> -<coverage version="7.6.10" timestamp="1741253336897" lines-valid="1941" lines-covered="1818" line-rate="0.9366" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0"> - <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.6.10 --> +<coverage version="7.7.1" timestamp="1743366739557" lines-valid="1967" lines-covered="1831" line-rate="0.9309" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0"> + <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.7.1 --> <!-- 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.9102" branch-rate="0" complexity="0"> + <package name="dbrepo" line-rate="0.8972" branch-rate="0" complexity="0"> <classes> - <class name="RestClient.py" filename="dbrepo/RestClient.py" complexity="0" line-rate="0.9102" branch-rate="0"> + <class name="RestClient.py" filename="dbrepo/RestClient.py" complexity="0" line-rate="0.8972" branch-rate="0"> <methods/> <lines> <line number="1" hits="1"/> @@ -902,6 +902,20 @@ <line number="1923" hits="1"/> <line number="1924" hits="1"/> <line number="1925" hits="1"/> + <line number="1927" hits="1"/> + <line number="1941" hits="0"/> + <line number="1942" hits="0"/> + <line number="1944" hits="0"/> + <line number="1945" hits="0"/> + <line number="1946" hits="0"/> + <line number="1947" hits="0"/> + <line number="1948" hits="0"/> + <line number="1949" hits="0"/> + <line number="1950" hits="0"/> + <line number="1951" hits="0"/> + <line number="1953" hits="0"/> + <line number="1954" hits="0"/> + <line number="1955" hits="0"/> </lines> </class> <class name="__init__.py" filename="dbrepo/__init__.py" complexity="0" line-rate="1" branch-rate="0"> @@ -910,7 +924,7 @@ </class> </classes> </package> - <package name="dbrepo.api" line-rate="0.959" branch-rate="0" complexity="0"> + <package name="dbrepo.api" line-rate="0.9595" branch-rate="0" complexity="0"> <classes> <class name="__init__.py" filename="dbrepo/api/__init__.py" complexity="0" line-rate="1" branch-rate="0"> <methods/> @@ -1326,20 +1340,18 @@ <line number="502" hits="1"/> <line number="505" hits="1"/> <line number="506" hits="1"/> - <line number="507" hits="1"/> + <line number="509" hits="1"/> <line number="510" hits="1"/> <line number="511" 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"/> @@ -1348,24 +1360,24 @@ <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="540" hits="1"/> <line number="541" hits="1"/> + <line number="542" hits="1"/> + <line number="543" hits="1"/> <line number="544" hits="1"/> + <line number="545" hits="1"/> <line number="548" hits="1"/> - <line number="549" hits="1"/> - <line number="550" 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="558" hits="1"/> - <line number="559" hits="1"/> - <line number="560" hits="1"/> + <line number="562" hits="1"/> <line number="563" hits="1"/> <line number="564" 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"/> @@ -1375,19 +1387,19 @@ <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="593" hits="1"/> <line number="594" hits="1"/> <line number="595" hits="1"/> @@ -1396,23 +1408,23 @@ <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="607" hits="1"/> <line number="608" hits="1"/> - <line number="609" hits="1"/> - <line number="610" hits="1"/> <line number="611" hits="1"/> + <line number="612" hits="1"/> + <line number="613" 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="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"/> @@ -1432,12 +1444,12 @@ <line number="644" hits="1"/> <line number="645" hits="1"/> <line number="646" hits="1"/> + <line number="647" hits="1"/> + <line number="648" hits="1"/> <line number="649" hits="1"/> <line number="650" 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"/> @@ -1461,17 +1473,17 @@ <line number="677" hits="1"/> <line number="678" hits="1"/> <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"/> <line number="691" hits="1"/> <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"/> @@ -1481,10 +1493,10 @@ <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"/> - <line number="709" hits="1"/> <line number="710" hits="1"/> <line number="711" hits="1"/> <line number="712" hits="1"/> @@ -1494,19 +1506,19 @@ <line number="716" hits="1"/> <line number="717" hits="1"/> <line number="718" hits="1"/> + <line number="719" hits="1"/> + <line number="720" hits="1"/> <line number="721" hits="1"/> <line number="722" hits="1"/> - <line number="723" hits="1"/> - <line number="724" hits="1"/> <line number="725" hits="1"/> + <line number="726" hits="1"/> + <line number="727" hits="1"/> <line number="728" hits="1"/> <line number="729" hits="1"/> - <line number="730" hits="1"/> - <line number="731" hits="1"/> + <line number="732" hits="1"/> + <line number="733" hits="1"/> <line number="734" hits="1"/> <line number="735" hits="1"/> - <line number="736" hits="1"/> - <line number="737" hits="1"/> <line number="738" hits="1"/> <line number="739" hits="1"/> <line number="740" hits="1"/> @@ -1514,68 +1526,73 @@ <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="758" hits="1"/> + <line number="759" hits="1"/> <line number="760" hits="1"/> <line number="761" hits="1"/> <line number="764" hits="1"/> <line number="765" hits="1"/> - <line number="766" hits="1"/> - <line number="767" hits="1"/> <line number="768" hits="1"/> <line number="769" 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="777" hits="1"/> <line number="778" hits="1"/> <line number="779" hits="1"/> - <line number="782" hits="1"/> + <line number="780" hits="1"/> <line number="783" hits="1"/> <line number="784" hits="1"/> <line number="785" hits="1"/> <line number="786" hits="1"/> + <line number="787" hits="1"/> + <line number="788" hits="1"/> <line number="789" hits="1"/> + <line number="792" hits="1"/> <line number="793" hits="1"/> <line number="794" hits="1"/> <line number="795" hits="1"/> - <line number="798" hits="1"/> - <line number="802" hits="1"/> + <line number="796" hits="1"/> + <line number="799" hits="1"/> <line number="803" hits="1"/> - <line number="806" hits="1"/> - <line number="807" hits="1"/> + <line number="804" hits="1"/> + <line number="805" hits="1"/> <line number="808" hits="1"/> - <line number="809" hits="1"/> - <line number="810" hits="1"/> + <line number="812" hits="1"/> <line number="813" hits="1"/> - <line number="814" hits="1"/> - <line number="815" hits="1"/> <line number="816" 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"/> + <line number="824" hits="1"/> <line number="825" hits="1"/> <line number="826" hits="1"/> <line number="827" hits="1"/> <line number="830" hits="1"/> <line number="831" hits="1"/> <line number="832" hits="1"/> - <line number="833" hits="1"/> - <line number="834" hits="1"/> + <line number="835" hits="1"/> + <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="847" hits="1"/> <line number="848" hits="1"/> <line number="849" hits="1"/> <line number="850" hits="1"/> @@ -1583,17 +1600,12 @@ <line number="854" hits="1"/> <line number="858" hits="1"/> <line number="859" hits="1"/> - <line number="862" hits="1"/> - <line number="866" hits="1"/> - <line number="867" hits="1"/> + <line number="860" hits="1"/> + <line number="861" hits="1"/> + <line number="864" 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="877" hits="1"/> <line number="878" hits="1"/> @@ -1602,17 +1614,17 @@ <line number="881" hits="1"/> <line number="882" 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="891" hits="1"/> <line number="892" hits="1"/> <line number="893" hits="1"/> - <line number="894" hits="1"/> - <line number="895" hits="1"/> <line number="896" hits="1"/> - <line number="897" hits="1"/> - <line number="898" hits="1"/> - <line number="899" hits="1"/> <line number="900" hits="1"/> <line number="901" hits="1"/> <line number="902" hits="1"/> @@ -1637,69 +1649,69 @@ <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="934" hits="1"/> - <line number="935" hits="1"/> - <line number="938" hits="1"/> + <line number="936" 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="949" hits="1"/> + <line number="948" hits="1"/> + <line number="952" hits="1"/> <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="959" hits="1"/> - <line number="960" hits="1"/> - <line number="962" hits="1"/> <line number="963" hits="1"/> + <line number="964" hits="1"/> <line number="966" hits="1"/> + <line number="967" 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="977" hits="1"/> - <line number="978" hits="1"/> - <line number="979" hits="1"/> + <line number="976" hits="1"/> <line number="980" hits="1"/> <line number="981" hits="1"/> - <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"/> + <line number="990" hits="1"/> + <line number="991" hits="1"/> <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"/> <line number="1002" hits="1"/> <line number="1003" hits="1"/> <line number="1004" hits="1"/> - <line number="1007" hits="1"/> + <line number="1005" hits="1"/> <line number="1008" hits="1"/> <line number="1009" hits="1"/> <line number="1012" hits="1"/> <line number="1013" hits="1"/> - <line number="1016" hits="1"/> + <line number="1014" hits="1"/> <line number="1017" hits="1"/> <line number="1018" hits="1"/> <line number="1019" hits="1"/> - <line number="1020" hits="1"/> - <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"/> @@ -1707,6 +1719,8 @@ <line number="1030" hits="1"/> <line number="1031" hits="1"/> <line number="1032" hits="1"/> + <line number="1033" hits="1"/> + <line number="1034" hits="1"/> <line number="1035" hits="1"/> <line number="1036" hits="1"/> <line number="1037" hits="1"/> @@ -1715,8 +1729,6 @@ <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"/> @@ -1734,6 +1746,8 @@ <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"/> <line number="1064" hits="1"/> <line number="1065" hits="1"/> <line number="1066" hits="1"/> @@ -1742,8 +1756,6 @@ <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="1075" hits="1"/> <line number="1076" hits="1"/> @@ -1751,6 +1763,8 @@ <line number="1078" hits="1"/> <line number="1079" 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"/> @@ -1761,8 +1775,6 @@ <line number="1090" hits="1"/> <line number="1091" hits="1"/> <line number="1092" hits="1"/> - <line number="1093" hits="1"/> - <line number="1094" hits="1"/> <line number="1095" hits="1"/> <line number="1096" hits="1"/> <line number="1097" hits="1"/> @@ -1771,6 +1783,8 @@ <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="1105" hits="1"/> <line number="1106" hits="1"/> <line number="1107" hits="1"/> @@ -1781,7 +1795,7 @@ <line number="1112" hits="1"/> <line number="1113" hits="1"/> <line number="1114" hits="1"/> - <line number="1115" hits="1"/> + <line number="1117" hits="1"/> <line number="1118" hits="1"/> <line number="1119" hits="1"/> <line number="1120" hits="1"/> @@ -1792,34 +1806,36 @@ <line number="1125" hits="1"/> <line number="1126" hits="1"/> <line number="1127" 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="1136" hits="1"/> + <line number="1137" 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="1144" hits="1"/> <line number="1145" hits="1"/> <line number="1146" hits="1"/> <line number="1147" hits="1"/> <line number="1148" hits="1"/> - <line number="1151" 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"/> - <line number="1157" hits="1"/> <line number="1158" hits="1"/> <line number="1159" hits="1"/> + <line number="1160" hits="1"/> + <line number="1161" hits="1"/> <line number="1162" hits="1"/> - <line number="1163" hits="1"/> - <line number="1166" hits="1"/> - <line number="1167" hits="1"/> - <line number="1168" hits="1"/> + <line number="1165" hits="1"/> <line number="1169" hits="1"/> <line number="1170" hits="1"/> <line number="1171" hits="1"/> @@ -1827,10 +1843,10 @@ <line number="1173" hits="1"/> <line number="1176" hits="1"/> <line number="1177" hits="1"/> - <line number="1178" hits="1"/> - <line number="1179" hits="1"/> <line number="1180" hits="1"/> <line number="1181" hits="1"/> + <line number="1182" hits="1"/> + <line number="1183" hits="1"/> <line number="1184" hits="1"/> <line number="1185" hits="1"/> <line number="1186" hits="1"/> @@ -1840,6 +1856,16 @@ <line number="1192" hits="1"/> <line number="1193" hits="1"/> <line number="1194" hits="1"/> + <line number="1195" hits="1"/> + <line number="1198" hits="1"/> + <line number="1199" hits="1"/> + <line number="1200" hits="1"/> + <line number="1201" hits="1"/> + <line number="1204" hits="1"/> + <line number="1205" hits="1"/> + <line number="1206" hits="1"/> + <line number="1207" hits="1"/> + <line number="1208" 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/RestClient.py b/lib/python/dbrepo/RestClient.py index 3459543d83..dbf1c7911f 100644 --- a/lib/python/dbrepo/RestClient.py +++ b/lib/python/dbrepo/RestClient.py @@ -1915,11 +1915,42 @@ class RestClient: if response.status_code == 400: raise MalformedError(f'Failed to update column: {response.text}') if response.status_code == 403: - raise ForbiddenError(f'Failed to update colum: not allowed') + raise ForbiddenError(f'Failed to update column: not allowed') if response.status_code == 404: - raise NotExistsError(f'Failed to update colum: not found') + raise NotExistsError(f'Failed to update column: not found') if response.status_code == 502: - raise ServiceConnectionError(f'Failed to update colum: failed to establish connection to search service') + raise ServiceConnectionError(f'Failed to update column: failed to establish connection to search service') if response.status_code == 503: - raise ServiceError(f'Failed to update colum: failed to save in search service') - raise ResponseCodeError(f'Failed to update colum: response code: {response.status_code} is not 202 (ACCEPTED)') + raise ServiceError(f'Failed to update column: failed to save in search service') + raise ResponseCodeError(f'Failed to update column: response code: {response.status_code} is not 202 (ACCEPTED)') + + def update_database_dashboard(self, database_id: str, uid: str) -> None: + """ + Update semantic information of a table column by given database id and table id and column id. + + :param database_id: The database id. + :param uid: The database uid. + + :raises MalformedError: If the payload is rejected by the service. + :raises ForbiddenError: If something went wrong with the authorization. + :raises NotExistsError: If the accept header is neither application/json nor application/ld+json. + :raises ServiceConnectionError: If something went wrong with connection to the search service. + :raises ServiceError: If something went wrong with obtaining the information in the search service. + :raises ResponseCodeError: If something went wrong with the retrieval of the identifiers. + """ + url = f'/api/database/{database_id}/dashboard' + response = self._wrapper(method="put", url=url, force_auth=True, + payload=DatabaseModifyDashboard(uid=uid)) + if response.status_code == 202: + return + if response.status_code == 400: + raise MalformedError(f'Failed to update database dashboard: {response.text}') + if response.status_code == 404: + raise NotExistsError(f'Failed to update database dashboard: not found') + if response.status_code == 502: + raise ServiceConnectionError( + f'Failed to update database dashboard: failed to establish connection to search service') + if response.status_code == 503: + raise ServiceError(f'Failed to update database dashboard: failed to save in search service') + raise ResponseCodeError( + f'Failed to update database dashboard: response code: {response.status_code} is not 202 (ACCEPTED)') diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 356f9b2200..00376c3737 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -502,6 +502,10 @@ class UpdateColumn(BaseModel): unit_uri: Optional[str] = None +class DatabaseModifyDashboard(BaseModel): + uid: str + + class ModifyVisibility(BaseModel): is_public: bool is_schema_public: bool @@ -762,11 +766,12 @@ class KeyAnalysis(BaseModel): class ColumnStatistic(BaseModel): - val_min: float - val_max: float + name: str mean: float median: float std_dev: float + val_min: float + val_max: float class ApiError(BaseModel): @@ -776,6 +781,11 @@ class ApiError(BaseModel): class TableStatistics(BaseModel): + total_rows: Optional[int] = None + total_columns: int + data_length: Optional[int] = None + max_data_length: Optional[int] = None + avg_row_length: Optional[int] = None columns: dict[str, ColumnStatistic] @@ -1076,6 +1086,8 @@ class ViewColumn(BaseModel): median: Optional[float] = None concept: Optional[ConceptBrief] = None unit: Optional[UnitBrief] = None + 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 @@ -1124,14 +1136,16 @@ class Database(BaseModel): internal_name: str is_public: bool is_schema_public: bool + is_dashboard_enabled: bool container: ContainerBrief identifiers: Optional[List[Identifier]] = field(default_factory=list) subsets: Optional[List[Identifier]] = field(default_factory=list) - preview_image: Optional[str] = None - description: Optional[str] = None tables: Optional[List[Table]] = field(default_factory=list) views: Optional[List[View]] = field(default_factory=list) accesses: Optional[List[DatabaseAccess]] = field(default_factory=list) + preview_image: Optional[str] = None + description: Optional[str] = None + dashboard_uid: Optional[str] = None exchange_name: Optional[str] = None diff --git a/dbrepo-search-service/init/omlib/exceptions/__init__.py b/lib/python/dbrepo/core/__init__.py similarity index 100% rename from dbrepo-search-service/init/omlib/exceptions/__init__.py rename to lib/python/dbrepo/core/__init__.py diff --git a/dbrepo-search-service/init/omlib/rdf/__init__.py b/lib/python/dbrepo/core/api/__init__.py similarity index 100% rename from dbrepo-search-service/init/omlib/rdf/__init__.py rename to lib/python/dbrepo/core/api/__init__.py diff --git a/dbrepo-dashboard-service/api/dto.py b/lib/python/dbrepo/core/api/dto.py similarity index 91% rename from dbrepo-dashboard-service/api/dto.py rename to lib/python/dbrepo/core/api/dto.py index e2dab237d5..73c50cfd91 100644 --- a/dbrepo-dashboard-service/api/dto.py +++ b/lib/python/dbrepo/core/api/dto.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional +from typing import Optional, List from pydantic import BaseModel @@ -48,3 +48,9 @@ class CreateDatasourceRequest(BaseModel): database_internal_name: str readonly: bool type: str + + +class User(BaseModel): + id: str + username: str + roles: List[str] diff --git a/lib/python/dbrepo/core/api/exceptions.py b/lib/python/dbrepo/core/api/exceptions.py new file mode 100644 index 0000000000..fda8031e3f --- /dev/null +++ b/lib/python/dbrepo/core/api/exceptions.py @@ -0,0 +1,5 @@ +class DashboardNotFound(Exception): + """ + The dashboard could not be found. + """ + pass diff --git a/lib/python/dbrepo/core/client/__init__.py b/lib/python/dbrepo/core/client/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/python/dbrepo/core/client/auth.py b/lib/python/dbrepo/core/client/auth.py new file mode 100644 index 0000000000..ec2bf4bf20 --- /dev/null +++ b/lib/python/dbrepo/core/client/auth.py @@ -0,0 +1,75 @@ +import logging +from typing import List, Any + +import requests +from jwt import jwk_from_pem, JWT +from jwt.exceptions import JWTDecodeError + +from dbrepo.api.dto import ApiError +from dbrepo.core.api.dto import User + + +class AuthServiceClient: + + def __init__(self, endpoint: str, client_id: str, client_secret: str, jwt_public_key: str): + self.endpoint = endpoint + self.client_id = client_id + self.client_secret = client_secret + self.jwt_public_key = jwt_public_key + + def get_user_token(self, username: str, password: str) -> str: + response = requests.post(f"{self.endpoint}/realms/dbrepo/protocol/openid-connect/token", + data={ + "username": username, + "password": password, + "grant_type": "password", + "client_id": self.client_id, + "client_secret": self.client_secret + }) + body = response.json() + if "access_token" not in body: + raise AssertionError("Failed to obtain user token(s)") + return response.json()["access_token"] + + def get_user_id(self, auth_header: str | None) -> (str | None, ApiError, int): + if auth_header is None: + return None, None, None + try: + user = self.verify_jwt(auth_header.split(" ")[1]) + logging.debug(f'mapped JWT to user.id {user.id}') + return user.id, None, None + except JWTDecodeError as e: + logging.error(f'Failed to decode JWT: {e}') + if str(e) == 'JWT Expired': + return None, ApiError(status='UNAUTHORIZED', message=f'Token expired', + code='search.user.unauthorized').model_dump(), 401 + return None, ApiError(status='FORBIDDEN', message=str(e), code='search.user.forbidden').model_dump(), 403 + + def verify_jwt(self, access_token: str) -> User: + public_key = jwk_from_pem(self.jwt_public_key.encode('utf-8')) + payload = JWT().decode(message=access_token, key=public_key, do_time_check=True) + return User(id=payload.get('uid'), username=payload.get('preferred_username'), + roles=payload.get('realm_access')["roles"]) + + def is_valid_token(self, token: str) -> bool | User: + if token is None or token == "": + return False + try: + return self.verify_jwt(access_token=token) + except JWTDecodeError: + return False + + def is_valid_password(self, username: str, password: str) -> Any: + if username is None or username == "" or password is None or password == "": + return False + try: + return self.verify_jwt(access_token=self.get_user_token(username=username, password=password)) + except AssertionError as error: + logging.error(error) + return False + except requests.exceptions.ConnectionError as error: + logging.error(f"Failed to connect to Authentication Service {error}") + return False + + def get_user_roles(self, user: User) -> List[str]: + return user.roles diff --git a/lib/python/dbrepo/core/client/dashboard.py b/lib/python/dbrepo/core/client/dashboard.py new file mode 100644 index 0000000000..0797c0a76f --- /dev/null +++ b/lib/python/dbrepo/core/client/dashboard.py @@ -0,0 +1,451 @@ +import logging + +import requests +from grafana_client import GrafanaApi +from grafana_client.client import GrafanaClientError, GrafanaException +from requests import Response + +from dbrepo.api.dto import Database, ColumnType, ViewColumn, View +from dbrepo.core.api.dto import Permission +from dbrepo.core.api.exceptions import DashboardNotFound + +statistics_row_title = 'Generated Statistics' + +disclaimer = 'Generic auto-generated chart' + +number_types = [ColumnType.SERIAL, ColumnType.BIT, ColumnType.SMALLINT, ColumnType.MEDIUMINT, ColumnType.INT, + ColumnType.BIGINT, ColumnType.FLOAT, ColumnType.DOUBLE, ColumnType.DECIMAL] + +time_types = [ColumnType.DATE, ColumnType.TIME, ColumnType.TIMESTAMP, ColumnType.YEAR] + +bool_types = [ColumnType.TINYINT, ColumnType.BOOL] + +section_height = 3 * 8 + + +def map_link(title: str, url: str, icon: str = 'info', open_new_window: bool = True) -> dict: + return dict(targetBlank=open_new_window, + asDropdown=False, + includeVars=False, + keepTime=False, + tags=[], + type='link', + icon=icon, + title=title, + url=url) + + +def _get_start_index(dashboard: dict) -> int | None: + return [panel['title'] for panel in dashboard['panels']].index(statistics_row_title) + + +def map_column_conversion(column: ViewColumn) -> dict: + destinationType = 'string' + dateFormat = None + if column.type in number_types: + destinationType = 'number' + elif column.type in time_types: + destinationType = 'time' + if column.type == ColumnType.YEAR: + dateFormat = 'YYYY' + elif column.type == ColumnType.TIME: + dateFormat = 'HH:mm:ss' + else: + dateFormat = 'YYYY-MM-dd' + elif column.type in bool_types: + destinationType = 'boolean' + return dict(targetField=column.internal_name, + destinationType=destinationType, + dateFormat=dateFormat) + + +def map_row(title: str, x: int = 0, y: int = 0) -> dict: + return dict(collapsed=False, + title=title, + type='row', + panels=[], + targets=[], + parser='backend', + gridPos=dict(h=1, + w=24, + x=x, + y=y)) + + +class DashboardServiceClient: + + def __init__(self, endpoint: str, username: str, password: str, base_url: str = 'http://localhost', + datasource_uid: str = 'dbrepojson0'): + self.client: GrafanaApi = GrafanaApi.from_url(url=f'{endpoint}', credential=(username, password)) + self.endpoint = endpoint + self.username = username + self.password = password + self.base_url = base_url + self.datasource_uid = datasource_uid + + def get_client(self): + return self.client + + def generic_get(self, api_url: str) -> Response: + request_url = self.endpoint + api_url + logging.debug(f'generic get url={request_url}, auth=({self.username}, <reacted>)') + return requests.get(request_url, auth=(self.username, self.password)) + + def generic_post(self, api_url: str, payload: dict) -> Response: + request_url = self.endpoint + api_url + logging.debug(f'generic post url={request_url}, payload={payload}, auth=({self.username}, <reacted>)') + return requests.post(request_url, json=payload, auth=(self.username, self.password)) + + def find(self, uid: str): + """ + Finds a dashboard with the given uid. + + @return The dashboard, if successful. Otherwise, `None`. + """ + if uid is None: + return None + try: + return self.client.dashboard.get_dashboard(uid) + except GrafanaClientError: + logging.warning(f"Failed to find dashboard with uid: {uid}") + return None + + def create(self, database_name: str, uid: str = '') -> dict: + dashboard = dict(uid=uid, + title=f'{database_name} Overview', + tags=['managed'], + timezone='browser', + refresh='30m', + preload=False, + panels=[]) + dashboard['panels'] = [] + payload = dict(folderUid='', + overwrite=False, + dashboard=dashboard) + dashboard = self.client.dashboard.update_dashboard(payload) + logging.info(f"Created dashboard with uid: {dashboard['uid']}") + return dashboard + + def delete(self, uid: str) -> None: + self.client.dashboard.delete_dashboard(uid) + + def update(self, database: Database) -> None: + dashboard = self.find(database.dashboard_uid) + if dashboard is None: + raise DashboardNotFound(f'Dashboard {database.dashboard_uid} not found') + dashboard = dashboard['dashboard'] + # update metadata + if not database.is_dashboard_enabled and 'managed' in dashboard['tags']: + dashboard['tags'].remove('managed') + if len(database.identifiers) > 0 and len(database.identifiers[0].titles) > 0: + dashboard['title'] = database.identifiers[0].titles[0].title + if len(database.identifiers) > 0 and len(database.identifiers[0].descriptions) > 0: + dashboard['description'] = database.identifiers[0].descriptions[0].description + dashboard['links'] = self.map_links(database) + # update panels + dashboard['panels'] = self.get_panels(dashboard, database) + payload = dict(folderUid='', + overwrite=True, + dashboard=dashboard) + response = self.client.dashboard.update_dashboard(payload) + logging.info(f"Updated dashboard with uid: {response['uid']}") + + def map_links(self, database: Database) -> [dict]: + links = [] + if len(database.identifiers) > 0: + links.append(map_link('Database', f"{self.base_url}/pid/{database.identifiers[0].id}")) + else: + links.append(map_link('Database', f"{self.base_url}/database/{database.id}")) + return links + + def update_anonymous_read_access(self, uid: str, is_public: bool, is_schema_public: bool) -> None: + permissions = self.client.dashboard.get_permissions_by_uid(uid) + viewer_role = [permission for permission in permissions if + 'permissionName' in permission and permission['permissionName'] != 'View'] + permission = '' + if is_public or is_schema_public: + permission = 'View' + if len(viewer_role) == 0: + logging.warning(f'Failed to find permissionName=View') + return None + try: + response = self.generic_post(f'/api/access-control/dashboards/{uid}/builtInRoles/Viewer', + Permission(permission=permission).model_dump()) + if response.status_code != 200: + raise OSError(f'Failed to update anonymous read access: {response.content}') + except GrafanaException as e: + raise OSError(f'Failed to update anonymous read access: {e.message}') + logging.info(f"Updated anonymous read access for dashboard with uid: {uid}") + + def _map_timeseries_panel(self, database_id: str, view: View, panel_type: str, h: int = 8, w: int = 12, x: int = 12, + y: int = 8) -> dict: + datasource = dict(uid=self.datasource_uid, + type='yesoreyeram-infinity-datasource') + fillOpacity = 0 + if panel_type == 'histogram': + fillOpacity = 60 + return dict(title=panel_type.capitalize(), + description=disclaimer, + type=panel_type, + datasource=datasource, + targets=[dict(datasource=datasource, + format='table', + global_query_id='', + hide=False, + refId='A', + root_selector='', + source='url', + type='json', + url=f'/api/database/{database_id}/view/{view.id}/data', + parser='backend', + url_options=dict(data='', + method='GET'))], + gridPos=dict(h=h, + w=w, + x=x, + y=y), + options=dict(legend=dict(displayMode='list', + placement='bottom', + showLegend=True), + tooltip=dict(mode='single', + sort='none')), + fieldConfig=dict( + defaults=dict(color=dict(mode='palette-classic'), + custom=dict( + axisBorderShow=False, + axisCenteredZero=False, + axisColorMode='text', + axisLabel='', + axisPlacement='auto', + barAlignment=0, + drawStyle='line', + fillOpacity=fillOpacity, + gradientMode='none', + hideFrom=dict(legend=False, + tooltip=False, + viz=False), + insertNulls=False, + lineInterpolation='linear', + lineWidth=1, + pointSize=5, + scaleDistribution=dict(type='linear'), + showPoints='auto', + spanNulls=False, + stacking=dict(group='A', + mode='none'), + thresholdsStyle=dict(mode='absolute')))), + transformations=[dict(id='convertFieldType', + options=dict(fields=dict(), + conversions=[map_column_conversion(column) for column in + view.columns]))]) + + def _map_number_panel(self, database_id: str, view_id: str, title: str, field: str, x: int = 18, + y: int = 0) -> dict: + datasource = dict(uid=self.datasource_uid, + type='yesoreyeram-infinity-datasource') + return dict(title=title, + type='stat', + datasource=datasource, + targets=[dict(datasource=datasource, + columns=[], + filters=[], + format='table', + global_query_id='', + hide=False, + refId='A', + root_selector='', + source='url', + type='json', + url=f'/api/database/{database_id}/view/{view_id}/statistic', + parser='backend', + url_options=dict(data='', + method='GET'))], + fieldConfig=dict(defaults=dict(mappings=[], + thresholds=dict(mode='absolute', + steps=[dict(color='blue', + value=None)]), + unit=''), + overrides=[]), + transformations=[dict(id='extractFields', + options=dict(delimiter=',', + source=field, + format='auto', + replace=False, + keepTime=False)), + dict(id='filterFieldsByName', + options=dict(include=dict(names=[field])))], + gridPos=dict(h=4, + w=6, + x=x, + y=y), + options=dict(colorMode='background', + graphMode='area', + justifyMode='auto', + orientation='auto', + reduceOptions=dict(calcs=[], + fields='/.*/', + values=True), + showPercentChange=False, + textMode='auto', + wideLayout=True)) + + def map_overview_panel(self, database_id: str, view_id: str, x: int = 0, y: int = 4) -> dict: + datasource = dict(uid=self.datasource_uid, + type='yesoreyeram-infinity-datasource') + return dict(title='Datasource Preview', + type='table', + gridPos=dict(h=8, + w=18, + x=x, + y=y), + fieldConfig=dict( + defaults=dict( + color=dict(mode='palette-classic'), + custom=dict(axisBorderShow=False, + axisCenteredZero=False, + axisColorMode='text', + axisLabel='', + axisPlacement='auto', + barAlignment=0, + drawStyle='line', + fillOpacity=0, + gradientMode='none', + hideFrom=dict( + legend=False, + tooltip=False, + viz=False), + insertNulls=False, + lineInterpolation='linear', + lineWidth=1, + pointSize=5, + scaleDistribution=dict( + type='linear'), + showPoints='auto', + spanNulls=False, + stacking=dict(group='A', + mode='none'), + thresholdsStyle=dict( + mode='off'))), + overrides=[]), + options=dict(legend=dict(displayMode='list', + placement='bottom', + showLegend=True, + calcs=[]), + tooltip=dict(mode='single', + sort='none')), + targets=[dict(format='json', + columns=[], + datasource=datasource, + filters=[], + global_query_id='', + refId='A', + root_selector='', + source='url', + type='json', + url=f'/api/database/{database_id}/view/{view_id}/data', + parser='backend', + url_options=dict(data='', + method='GET'))], + links=[dict(title='Cite', + url=f'{self.base_url}/database/{database_id}/view/{view_id}/data', + targetBlank=True)], + datasource=datasource) + + def map_statistics_panel(self, database_id: str, view_id: str, w: int = 12, h: int = 8, x: int = 0, + y: int = 8) -> dict: + datasource = dict(uid=self.datasource_uid, + type='yesoreyeram-infinity-datasource') + return dict(title='Statistics', + type='table', + gridPos=dict(h=h, + w=w, + x=x, + y=y), + datasource=datasource, + targets=[dict(datasource=datasource, + columns=[], + filters=[], + format='table', + global_query_id='', + hide=False, + refId='A', + root_selector='columns', + source='url', + type='json', + url=f'/api/database/{database_id}/view/{view_id}/statistic', + parser='backend', + url_options=dict(data='', + method='GET'))], + options=dict(cellHeight="sm", + showHeader=True, + footer=dict(countRows=False, + fields="", + reducer=["sum"], + show=False)), + transformations=[dict(id="organize", + options=dict(excludeByName=dict(), + includeByName=dict(), + indexByName=dict(name=0, + val_min=1, + val_max=2, + mean=3, + median=4, + std_dev=5), + renameByName=dict(name="Name", + mean="Mean", + median="Median", + std_dev="std.dev", + val_min="Minimum", + val_max="Maximum")))], + fieldConfig=dict(defaults=dict(custom=dict(align="auto", + filterable="true", + cellOptions=dict(type="auto"), + inspect=False), + mappings=[], + thresholds=dict(mode="absolute", + steps=[dict(color="green", + value=None), + dict(color="red", + value=80) + ])), + overrides=[])) + + def map_timeseries_panel(self, database_id: str, view: View, h: int = 8, w: int = 12, x: int = 12, + y: int = 8) -> dict: + return self._map_timeseries_panel(database_id, view, 'timeseries', h, w, x, y) + + def map_pie_panel(self, database_id: str, view: View, h: int = 8, w: int = 12, x: int = 12, y: int = 8) -> dict: + return self._map_timeseries_panel(database_id, view, 'piechart', h, w, x, y) + + def map_histogram_panel(self, database_id: str, view: View, h: int = 8, w: int = 12, x: int = 12, + y: int = 8) -> dict: + return self._map_timeseries_panel(database_id, view, 'histogram', h, w, x, y) + + def map_rows_panel(self, database_id: str, view_id: str, x: int = 18, y: int = 0) -> dict: + return self._map_number_panel(database_id, view_id, 'Rows', 'total_rows', x, y) + + def map_columns_panel(self, database_id: str, view_id: str, x: int = 18, y: int = 0) -> dict: + return self._map_number_panel(database_id, view_id, 'Variables', 'total_columns', x, y) + + def get_panels(self, dashboard: dict, database: Database) -> [dict]: + panels = dashboard['panels'] + try: + end_index = _get_start_index(dashboard) + logging.debug(f'splicing managed panels after index: {end_index}') + panels = panels[:end_index] + except ValueError: + logging.warning(f'No managed panels found') + original_panels_size = len(panels) + panels.append(map_row(statistics_row_title, 0, 0)) # statistics row + for i, view in enumerate(database.views): + # section + panels.append(map_row(view.name, 0, i * section_height + 0)) + panels.append(self.map_overview_panel(database.id, view.id, 0, i * section_height + 4)) + panels.append(self.map_rows_panel(database.id, view.id, 18, i * section_height + 0)) + panels.append(self.map_columns_panel(database.id, view.id, 18, i * section_height + 4)) + panels.append(self.map_statistics_panel(database.id, view.id, h=8, w=12, x=0, y=i * section_height + 8)) + panels.append(self.map_histogram_panel(database.id, view, h=8, w=12, x=12, y=i * section_height + 8)) + panels.append(self.map_timeseries_panel(database.id, view, h=8, w=8, x=0, y=i * section_height + 16)) + panels.append(self.map_pie_panel(database.id, view, h=8, w=8, x=8, y=i * section_height + 16)) + logging.info(f'Added {len(panels) - original_panels_size} managed panel(s)') + return panels diff --git a/dbrepo-search-service/init/clients/opensearch_client.py b/lib/python/dbrepo/core/client/search.py similarity index 88% rename from dbrepo-search-service/init/clients/opensearch_client.py rename to lib/python/dbrepo/core/client/search.py index deca261ce2..36dfae4907 100644 --- a/dbrepo-search-service/init/clients/opensearch_client.py +++ b/lib/python/dbrepo/core/client/search.py @@ -6,38 +6,39 @@ import os from collections.abc import MutableMapping from json import dumps, load -from dbrepo.api.dto import Database -from dbrepo.api.exceptions import ForbiddenError, NotExistsError from opensearchpy import OpenSearch, NotFoundError from requests import head -from omlib.constants import OM_IDS -from omlib.measure import om -from omlib.omconstants import OM -from omlib.unit import Unit +from dbrepo.api.dto import Database +from dbrepo.api.exceptions import ForbiddenError, NotExistsError +from dbrepo.core.omlib.constants import OM_IDS +from dbrepo.core.omlib.measure import om +from dbrepo.core.omlib.omconstants import OM +from dbrepo.core.omlib.unit import Unit -class OpenSearchClient: +class SearchServiceClient: """ The client to communicate with the OpenSearch database. """ - host: str = None instance: OpenSearch = None - metadata_endpoint: str = None - password: str = None - port: int = None - system_username: str = None - system_password: str = None - username: str = None def __init__(self, host: str = None, port: int = None, username: str = None, password: str = None): + if host is None: + host = 'search-db' self.host = os.getenv('OPENSEARCH_HOST', host) self.metadata_endpoint = os.getenv('METADATA_SERVICE_ENDPOINT', 'http://metadata-service:8080') + if username is None: + username = 'admin' + self.username = os.getenv('OPENSEARCH_USERNAME', username) + if password is None: + password = 'admin' self.password = os.getenv('OPENSEARCH_PASSWORD', password) + if port is None: + port = 9200 self.port = int(os.getenv('OPENSEARCH_PORT', port)) self.system_username = os.getenv('SYSTEM_USERNAME', 'admin') self.system_password = os.getenv('SYSTEM_PASSWORD', 'admin') - self.username = os.getenv('OPENSEARCH_USERNAME', username) def _instance(self) -> OpenSearch: """ @@ -51,19 +52,40 @@ class OpenSearchClient: http_auth=(self.username, self.password)) return self.instance - def update_database(self, database_id: str, data: Database) -> Database: + def database_exists(self, database_id: str): + try: + SearchServiceClient()._instance().get(index="database", id=database_id) + return True + except NotFoundError: + return False + + def index_update(self, mapping: dict) -> None: + if SearchServiceClient()._instance().indices.exists(index="database"): + logging.debug(f"index 'database' exists, removing...") + SearchServiceClient()._instance().indices.delete(index="database") + SearchServiceClient()._instance().indices.create(index="database", body=mapping) + logging.info(f"Created index 'database'") + + def save_database(self, database_id: str, data: Database, fetch: bool = False) -> Database | None: """ - Updates the database data with given id. + Creates the database data with given id. If a document with the id already exists, the document is updated. @param database_id: The database id. @param data: The database data. + @param fetch: When enabled, fetches the saved database data. Default: `False`. + + :return The saved database data. @returns: The updated database, if successful. - @throws: opensearchpy.exceptions.NotFoundError If the database was not found in the Search Database. + @throws: opensearchpy.exceptions.NotFoundError If the database was not found in the Search Database. Ignored when `force` is `True`. """ - logging.debug(f"updating database with id: {database_id} in search database") - self._instance().index(index="database", id=database_id, body=dumps(data.model_dump())) - response: dict = self._instance().get(index="database", id=database_id) + self._instance().update(index="database", id=database_id, + body={'doc': data.model_dump(), 'doc_as_upsert': True}) + logging.info(f'Updated database with id: {database_id}') + if fetch is False: + return None + response = self._instance().get(index="database", id=database_id) + logging.debug(f'fetched database for return value with id: {database_id}') return Database.model_validate(response["_source"]) def delete_database(self, database_id: str) -> None: @@ -215,7 +237,6 @@ class OpenSearchClient: "query": {"bool": {"must": musts}} } logging.debug(f'search in index database for type: {field_type}') - logging.debug(f'search body: {dumps(body)}') response = self._instance().search( index="database", body=dumps(body) diff --git a/dbrepo-analyse-service/clients/s3_client.py b/lib/python/dbrepo/core/client/storage.py similarity index 86% rename from dbrepo-analyse-service/clients/s3_client.py rename to lib/python/dbrepo/core/client/storage.py index 18cdba1ec3..8455cba8a5 100644 --- a/dbrepo-analyse-service/clients/s3_client.py +++ b/lib/python/dbrepo/core/client/storage.py @@ -7,14 +7,16 @@ from boto3.exceptions import S3UploadFailedError from botocore.exceptions import ClientError -class S3Client: +class StorageServiceClient: - def __init__(self): - endpoint_url = current_app.config['S3_ENDPOINT'] - aws_access_key_id = current_app.config['S3_ACCESS_KEY_ID'] - aws_secret_access_key = current_app.config['S3_SECRET_ACCESS_KEY'] - logging.info(f"retrieve file from S3, endpoint_url={current_app.config['S3_PROTO']}://{endpoint_url}, aws_access_key_id={aws_access_key_id}, aws_secret_access_key=(hidden)") - self.client = boto3.client(service_name='s3', endpoint_url=f"{current_app.config['S3_PROTO']}://{endpoint_url}", aws_access_key_id=aws_access_key_id, + def __init__(self, endpoint: str, access_key_id: str, secret_access_key: str): + endpoint = endpoint + aws_access_key_id = access_key_id + aws_secret_access_key = secret_access_key + logging.info( + f"retrieve file from S3, endpoint={current_app.config['S3_PROTO']}://{endpoint}, aws_access_key_id={aws_access_key_id}, aws_secret_access_key=(hidden)") + self.client = boto3.client(service_name='s3', endpoint_url=f"{current_app.config['S3_PROTO']}://{endpoint}", + aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key) self.bucket_exists_or_exit(current_app.config['S3_BUCKET']) diff --git a/lib/python/dbrepo/core/omlib/__init__.py b/lib/python/dbrepo/core/omlib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dbrepo-search-service/init/omlib/constants.py b/lib/python/dbrepo/core/omlib/constants.py similarity index 96% rename from dbrepo-search-service/init/omlib/constants.py rename to lib/python/dbrepo/core/omlib/constants.py index 34dad53e34..8460043979 100644 --- a/dbrepo-search-service/init/omlib/constants.py +++ b/lib/python/dbrepo/core/omlib/constants.py @@ -1,9 +1,9 @@ import rdflib from rdflib import URIRef -from omlib.dimension import Dimension -from omlib.scale import Scale -from omlib.unit import Prefix, Unit +from dbrepo.core.omlib.dimension import Dimension +from dbrepo.core.omlib.scale import Scale +from dbrepo.core.omlib.unit import Prefix, Unit class OM_IDS: diff --git a/dbrepo-search-service/init/omlib/dimension.py b/lib/python/dbrepo/core/omlib/dimension.py similarity index 96% rename from dbrepo-search-service/init/omlib/dimension.py rename to lib/python/dbrepo/core/omlib/dimension.py index bc05571bcf..8a6e94306d 100644 --- a/dbrepo-search-service/init/omlib/dimension.py +++ b/lib/python/dbrepo/core/omlib/dimension.py @@ -1,4 +1,4 @@ -from omlib.exceptions.dimensionexception import DimensionalException +from dbrepo.core.omlib.exceptions.dimensionexception import DimensionalException class Dimension: diff --git a/lib/python/dbrepo/core/omlib/exceptions/__init__.py b/lib/python/dbrepo/core/omlib/exceptions/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dbrepo-search-service/init/omlib/exceptions/dimensionexception.py b/lib/python/dbrepo/core/omlib/exceptions/dimensionexception.py similarity index 100% rename from dbrepo-search-service/init/omlib/exceptions/dimensionexception.py rename to lib/python/dbrepo/core/omlib/exceptions/dimensionexception.py diff --git a/dbrepo-search-service/init/omlib/exceptions/unitconversionexception.py b/lib/python/dbrepo/core/omlib/exceptions/unitconversionexception.py similarity index 100% rename from dbrepo-search-service/init/omlib/exceptions/unitconversionexception.py rename to lib/python/dbrepo/core/omlib/exceptions/unitconversionexception.py diff --git a/dbrepo-search-service/init/omlib/exceptions/unitidentityexception.py b/lib/python/dbrepo/core/omlib/exceptions/unitidentityexception.py similarity index 100% rename from dbrepo-search-service/init/omlib/exceptions/unitidentityexception.py rename to lib/python/dbrepo/core/omlib/exceptions/unitidentityexception.py diff --git a/dbrepo-search-service/init/omlib/measure.py b/lib/python/dbrepo/core/omlib/measure.py similarity index 98% rename from dbrepo-search-service/init/omlib/measure.py rename to lib/python/dbrepo/core/omlib/measure.py index eb19729b5d..f8b2d7fdc3 100644 --- a/dbrepo-search-service/init/omlib/measure.py +++ b/lib/python/dbrepo/core/omlib/measure.py @@ -1,10 +1,10 @@ import math -from omlib.constants import SI -from omlib.exceptions.dimensionexception import DimensionalException -from omlib.scale import Scale -from omlib.thing import Thing -from omlib.unit import Unit, PrefixedUnit, SingularUnit +from dbrepo.core.omlib.constants import SI +from dbrepo.core.omlib.exceptions.dimensionexception import DimensionalException +from dbrepo.core.omlib.scale import Scale +from dbrepo.core.omlib.thing import Thing +from dbrepo.core.omlib.unit import Unit, PrefixedUnit, SingularUnit def om(numerical_value, unit_or_scale, identifier=None): diff --git a/dbrepo-search-service/init/omlib/omconstants.py b/lib/python/dbrepo/core/omlib/omconstants.py similarity index 99% rename from dbrepo-search-service/init/omlib/omconstants.py rename to lib/python/dbrepo/core/omlib/omconstants.py index 8afb3f896a..0163fa69ed 100644 --- a/dbrepo-search-service/init/omlib/omconstants.py +++ b/lib/python/dbrepo/core/omlib/omconstants.py @@ -2,9 +2,9 @@ import rdflib from rdflib import URIRef, Literal -from omlib.dimension import Dimension -from omlib.scale import Scale -from omlib.unit import Prefix, Unit +from dbrepo.core.omlib.dimension import Dimension +from dbrepo.core.omlib.scale import Scale +from dbrepo.core.omlib.unit import Prefix, Unit class OM: diff --git a/lib/python/dbrepo/core/omlib/rdf/__init__.py b/lib/python/dbrepo/core/omlib/rdf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dbrepo-search-service/init/omlib/rdf/om-2.0.rdf b/lib/python/dbrepo/core/omlib/rdf/om-2.0.rdf similarity index 100% rename from dbrepo-search-service/init/omlib/rdf/om-2.0.rdf rename to lib/python/dbrepo/core/omlib/rdf/om-2.0.rdf diff --git a/dbrepo-search-service/init/omlib/scale.py b/lib/python/dbrepo/core/omlib/scale.py similarity index 95% rename from dbrepo-search-service/init/omlib/scale.py rename to lib/python/dbrepo/core/omlib/scale.py index b0fedec5c0..44c5783dbe 100644 --- a/dbrepo-search-service/init/omlib/scale.py +++ b/lib/python/dbrepo/core/omlib/scale.py @@ -1,11 +1,11 @@ from rdflib import URIRef -from omlib.dimension import Dimension -from omlib.exceptions.dimensionexception import DimensionalException -from omlib.exceptions.unitconversionexception import ScaleConversionException -from omlib.exceptions.unitidentityexception import ScaleIdentityException -from omlib.thing import Thing -from omlib.unit import Unit +from dbrepo.core.omlib.dimension import Dimension +from dbrepo.core.omlib.exceptions.dimensionexception import DimensionalException +from dbrepo.core.omlib.exceptions.unitconversionexception import ScaleConversionException +from dbrepo.core.omlib.exceptions.unitidentityexception import ScaleIdentityException +from dbrepo.core.omlib.thing import Thing +from dbrepo.core.omlib.unit import Unit class Scale(Thing): diff --git a/dbrepo-search-service/init/omlib/thing.py b/lib/python/dbrepo/core/omlib/thing.py similarity index 100% rename from dbrepo-search-service/init/omlib/thing.py rename to lib/python/dbrepo/core/omlib/thing.py diff --git a/dbrepo-search-service/init/omlib/unit.py b/lib/python/dbrepo/core/omlib/unit.py similarity index 99% rename from dbrepo-search-service/init/omlib/unit.py rename to lib/python/dbrepo/core/omlib/unit.py index c05fef1e9d..c9c63afe02 100644 --- a/dbrepo-search-service/init/omlib/unit.py +++ b/lib/python/dbrepo/core/omlib/unit.py @@ -2,11 +2,11 @@ import math from rdflib import URIRef -from omlib.exceptions.dimensionexception import DimensionalException -from omlib.exceptions.unitconversionexception import UnitConversionException -from omlib.exceptions.unitidentityexception import UnitIdentityException -from omlib.dimension import Dimension -from omlib.thing import SymbolThing +from dbrepo.core.omlib.exceptions.dimensionexception import DimensionalException +from dbrepo.core.omlib.exceptions.unitconversionexception import UnitConversionException +from dbrepo.core.omlib.exceptions.unitidentityexception import UnitIdentityException +from dbrepo.core.omlib.dimension import Dimension +from dbrepo.core.omlib.thing import SymbolThing class Unit(SymbolThing): diff --git a/lib/python/docs/index.rst b/lib/python/docs/index.rst index 80d1d6806b..b7b6bf88e0 100644 --- a/lib/python/docs/index.rst +++ b/lib/python/docs/index.rst @@ -6,7 +6,7 @@ Pandas `DataFrame <https://pandas.pydata.org/docs/reference/api/pandas.DataFrame provides an object-oriented API as well as low-level access to DBRepo services. .. note:: - The SDK has been implemented and documented for DBRepo version 1.7.3, earlier versions may be supported but are not tested for compatibility. + The SDK has been implemented and documented for DBRepo version 1.8.0, earlier versions may be supported but are not tested for compatibility. Quickstart ---------- diff --git a/lib/python/package.sh b/lib/python/package.sh deleted file mode 100755 index 2ad8d301e8..0000000000 --- a/lib/python/package.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -python -m build --sdist ./lib/python -python -m build --wheel ./lib/python diff --git a/lib/python/pyproject.toml b/lib/python/pyproject.toml index 0a34c76816..4ca8d9dfa9 100644 --- a/lib/python/pyproject.toml +++ b/lib/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dbrepo" -version = "1.7.3" +version = "1.8.0" description = "DBRepo Python Library" keywords = [ "DBRepo", @@ -10,13 +10,13 @@ authors = [ { name = "Martin Weise, TU Wien", email = "martin.weise@tuwien.ac.at" } ] readme = "README.md" -license = { file = "LICENSE" } +license = "Apache-2.0" +license-files = ["LICENSE"] classifiers = [ "Development Status :: 4 - Beta", "Topic :: Software Development :: Libraries", "Programming Language :: Python :: 3.11", "Operating System :: OS Independent", - "License :: OSI Approved :: Apache Software License", ] requires-python = ">=3.11" dependencies = [ @@ -34,7 +34,7 @@ requires = [ build-backend = "setuptools.build_meta" [project.urls] -Homepage = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" +Homepage = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/" Documentation = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/python/" Issues = "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues" Source = "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/" \ No newline at end of file diff --git a/lib/python/release.sh b/lib/python/release.sh deleted file mode 100755 index 9c5e62d2d0..0000000000 --- a/lib/python/release.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -echo "${CI_PIPYRC}" | base64 -d > .pypirc -python -m twine upload --config-file .pypirc --verbose --repository pypi ./lib/python/dist/dbrepo-* diff --git a/lib/python/setup.py b/lib/python/setup.py index 635365883e..5180231936 100644 --- a/lib/python/setup.py +++ b/lib/python/setup.py @@ -2,13 +2,19 @@ from distutils.core import setup setup(name="dbrepo", - version="1.7.3", + version="1.8.0", description="A library for communicating with DBRepo", - url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/", + url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/", author="Martin Weise", license="Apache-2.0", author_email="martin.weise@tuwien.ac.at", packages=[ "dbrepo", - "dbrepo.api" + "dbrepo.api", + "dbrepo.core", + "dbrepo.core.api", + "dbrepo.core.client", + "dbrepo.core.omlib", + "dbrepo.core.omlib.exceptions", + "dbrepo.core.omlib.rdf", ]) diff --git a/lib/python/test.sh b/lib/python/test.sh deleted file mode 100644 index cd0129654a..0000000000 --- a/lib/python/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source ./lib/python/venv/bin/activate -cd ./lib/python/ && coverage run -m pytest tests/*.py --junitxml=report.xml && coverage html && coverage report > ./coverage.txt \ No newline at end of file diff --git a/dbrepo-search-service/init/tests/conftest.py b/lib/python/tests/conftest.py similarity index 90% rename from dbrepo-search-service/init/tests/conftest.py rename to lib/python/tests/conftest.py index e2a00b1d86..c906c18fa7 100644 --- a/dbrepo-search-service/init/tests/conftest.py +++ b/lib/python/tests/conftest.py @@ -1,9 +1,8 @@ +import json import logging import os import pytest -import json - from testcontainers.opensearch import OpenSearchContainer @@ -15,7 +14,7 @@ def session(request): :return: The OpenSearch container """ logging.debug("[fixture] creating opensearch container") - container = OpenSearchContainer() + container = OpenSearchContainer("opensearchproject/opensearch:2.10.0") logging.debug("[fixture] starting opensearch container") container.start() @@ -41,7 +40,7 @@ def cleanup(request, session): :return: """ logging.info("[fixture] clean schema") - with open('./database.json', 'r') as f: + with open('./tests/opensearch/database.json', 'r') as f: if session.get_client().indices.exists(index="database"): session.get_client().indices.delete(index="database") session.get_client().indices.create(index="database", body=json.load(f)) diff --git a/lib/python/tests/keycloak/rs256.key b/lib/python/tests/keycloak/rs256.key new file mode 100644 index 0000000000..86b3eaf5c6 --- /dev/null +++ b/lib/python/tests/keycloak/rs256.key @@ -0,0 +1,3 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQABAoIBADNcMt6hAHub4JTAYS6Mra0EPRBO2XhWmACBrv3+8ETClXd5475KPLDewgRVtlmtbwU8G8awUXESQgPS9lfiqvQhPreA3cHlm6oP2WMKOEtakr2s8I+frsTBLCo0Ini9RaSzjoVVgS0zofyhASKi+T970MafSj5P3XNb8YBFdXgoYDiA7FXLH6a/+m7LScL+wGcFMAAeYESxZbMQLfH3v8L+4EcTraiwjLG17ZdlF3dpybMyUSse6ZQ/PdlyvBuzzLXhN6Ce2gd9ATfS+YWTzo7Yf+GU+ex5bIpVOfHqtuM/hyq7YGKENClsXwNZIAoFnvGCbvECAfgyapVrD30IfykCgYEA0rgsSZ82pxT40NxwgBD1g9lbNVBKXphRB/3S078qusUzJjT7AldEj4imGPhAbI7bI8gAeWJsp1XJWkjM8ktaVrh+NQl7p8e9OPh0pQF/5Bdg8ajbjXESpjnaU66pVYRQy/d+jNli/YRAHX5RUfsBl+6W4+WSVMGmKBiqJsur+ecCgYEAz1YVXClcmUnyZem5B+2E9noIzjF6ROE+jIb6rawM85P3Xd0lXtECQavtxw+Qk7I32qOwrxl1UpK2foVel3pazi+4OpMfmqtYGenRP1Zk1cZwrDo0cIemTDGjj3kJ8tYn12CGolFQpJZgK6OHzvG0tOxI5VZgjIViWNPe1PGWXtUCgYEAxXGNDe8BZs1f11S2lUlOw5yGug3hoYFXbAWJ5p7Ziuf8ZXB/QlJDC7se54a11wKEk6Jzz0lKRgE8CjzszJuOqnN0zn10QGIIC7nCklo1W6QMUmPGVWH994N976tZP6gbjQL6sT+AYcvpx7j0ubxYYeRNvnz+ACzzY964kGGHY0ECgYEAumlwPPNnMN7+VEjGNm2D7UMdJZ3wi3tkjF5ThdA5uMohTsAk+FG80KSu3RmOaGyEsUwY7+VYyYvlDm4E9PZqLBVVczyR3rMNPAcwPd0EPfvzk7WlLkOX7ct3fehaXH3VRlyfz9KCSeh1wOZ/lT1VtpD2nVOC7PSDzs92+kfXZZ0CgYAnrD1y4skgXkdwolZ3unn3EFyGm2d+X5aMTHwQPdWxqoNIAl/9wdghlzihwnPhhsxq1WzlxuC3V2IMrNPtRx70Mi+FbSmR5m4Xx5RptgMtMlwno+L40PzNJgMjHGjt0wcx3Vel8wuohDtnqMyS7P5nG1/TQx0Cyzwn7QOXlNpgbQ== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/lib/python/tests/keycloak/rsa256.pkey b/lib/python/tests/keycloak/rsa256.pkey new file mode 100644 index 0000000000..857dfb22be --- /dev/null +++ b/lib/python/tests/keycloak/rsa256.pkey @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB +-----END PUBLIC KEY----- diff --git a/lib/python/tests/opensearch/database.json b/lib/python/tests/opensearch/database.json new file mode 100644 index 0000000000..175a50dd9b --- /dev/null +++ b/lib/python/tests/opensearch/database.json @@ -0,0 +1,1418 @@ +{ + "aliases": {}, + "mappings": { + "properties": { + "accesses": { + "properties": { + "created": { + "type": "date" + }, + "type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "user": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + } + }, + "contact": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "container": { + "properties": { + "created": { + "type": "date" + }, + "host": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "image": { + "properties": { + "dialect": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "driver_class": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "registry": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "version": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "port": { + "type": "long" + }, + "ui_host": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "ui_port": { + "type": "long" + } + } + }, + "created": { + "type": "date" + }, + "owner": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "exchange_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "identifiers": { + "properties": { + "created": { + "type": "date" + }, + "owner": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "owners": { + "properties": { + "owner_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier_scheme": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier_scheme_uri": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "descriptions": { + "properties": { + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "licenses": { + "properties": { + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "identifier": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "uri": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "publication_day": { + "type": "long" + }, + "publication_month": { + "type": "long" + }, + "publication_year": { + "type": "long" + }, + "publisher": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query_normalized": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "status": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "titles": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "view_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "image": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "is_public": { + "type": "boolean" + }, + "is_schema_public": { + "type": "boolean" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "tables": { + "properties": { + "columns": { + "properties": { + "auto_generated": { + "type": "boolean" + }, + "type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "d": { + "type": "long" + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "is_null_allowed": { + "type": "boolean" + }, + "is_public": { + "type": "boolean" + }, + "is_schema_public": { + "type": "boolean" + }, + "mean": { + "type": "float" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "size": { + "type": "long" + }, + "std_dev": { + "type": "float" + }, + "table_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "constraints": { + "properties": { + "primary_key": { + "properties": { + "column": { + "properties": { + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "table_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "table": { + "properties": { + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + } + }, + "uniques": { + "properties": { + "columns": { + "properties": { + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "table_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "table": { + "properties": { + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + } + } + } + }, + "created": { + "type": "date" + }, + "owner": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "data_length": { + "type": "long" + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "is_public": { + "type": "boolean" + }, + "is_schema_public": { + "type": "boolean" + }, + "is_versioned": { + "type": "boolean" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "num_rows": { + "type": "long" + }, + "queue_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "routing_key": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "views": { + "properties": { + "columns": { + "properties": { + "auto_generated": { + "type": "boolean" + }, + "type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "is_null_allowed": { + "type": "boolean" + }, + "is_public": { + "type": "boolean" + }, + "is_schema_public": { + "type": "boolean" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "created": { + "type": "date" + }, + "owner": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "identifiers": { + "properties": { + "created": { + "type": "date" + }, + "owner": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "qualified_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "orcid": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "username": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "owners": { + "properties": { + "owner_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier_scheme": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_identifier_scheme_uri": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name_type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "database_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "descriptions": { + "properties": { + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "licenses": { + "properties": { + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "identifier": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "uri": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "publication_day": { + "type": "long" + }, + "publication_month": { + "type": "long" + }, + "publication_year": { + "type": "long" + }, + "publisher": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query_normalized": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "status": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "titles": { + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "type": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "view_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "initial_view": { + "type": "boolean" + }, + "internal_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "is_public": { + "type": "boolean" + }, + "is_schema_public": { + "type": "boolean" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "query_hash": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + } + }, + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "1" + } + } +} \ No newline at end of file diff --git a/dbrepo-analyse-service/tests/test_s3_client.py b/lib/python/tests/test_integration_core_storage_client.py similarity index 98% rename from dbrepo-analyse-service/tests/test_s3_client.py rename to lib/python/tests/test_integration_core_storage_client.py index cbc47a6740..c69fce877f 100644 --- a/dbrepo-analyse-service/tests/test_s3_client.py +++ b/lib/python/tests/test_integration_core_storage_client.py @@ -4,7 +4,7 @@ from clients.s3_client import S3Client from botocore.exceptions import ClientError -class S3ClientTest(unittest.TestCase): +class StorageServiceClientIntegrationTest(unittest.TestCase): # @Test def test_upload_file_succeeds(self): diff --git a/dbrepo-search-service/init/tests/test_keycloak_client.py b/lib/python/tests/test_unit_core_auth_client.py similarity index 97% rename from dbrepo-search-service/init/tests/test_keycloak_client.py rename to lib/python/tests/test_unit_core_auth_client.py index f52faf78c6..e8296b7993 100644 --- a/dbrepo-search-service/init/tests/test_keycloak_client.py +++ b/lib/python/tests/test_unit_core_auth_client.py @@ -7,7 +7,7 @@ import requests_mock from clients.keycloak_client import KeycloakClient -class JwtTest(unittest.TestCase): +class AuthServiceClientUnitTest(unittest.TestCase): def response(self, username) -> dict: return dict({ diff --git a/dbrepo-search-service/init/tests/test_opensearch_client.py b/lib/python/tests/test_unit_core_search_client.py similarity index 99% rename from dbrepo-search-service/init/tests/test_opensearch_client.py rename to lib/python/tests/test_unit_core_search_client.py index 54ef2340ab..6aeb6f98a7 100644 --- a/dbrepo-search-service/init/tests/test_opensearch_client.py +++ b/lib/python/tests/test_unit_core_search_client.py @@ -16,6 +16,7 @@ req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", exchange_name="dbrepo", is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief(id="7efe8b27-6cdc-4387-80e3-92ee28f4a7c5", name="MariaDB", internal_name="mariadb", @@ -53,7 +54,7 @@ req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", )]) -class OpenSearchClientTest(unittest.TestCase): +class SearchServiceClientUnitTest(unittest.TestCase): def test_update_database_succeeds(self): req.tables = [Table(id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", diff --git a/lib/python/tests/test_unit_database.py b/lib/python/tests/test_unit_database.py index 54a41cfbd7..ee4d0aeae4 100644 --- a/lib/python/tests/test_unit_database.py +++ b/lib/python/tests/test_unit_database.py @@ -76,6 +76,7 @@ class DatabaseUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief( id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", name='MariaDB Galera 11.1.3', @@ -134,6 +135,7 @@ class DatabaseUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief( id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", name='MariaDB Galera 11.1.3', @@ -261,6 +263,7 @@ class DatabaseUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief( id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", name='MariaDB Galera 11.1.3', @@ -379,6 +382,7 @@ class DatabaseUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, container=ContainerBrief( id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", name='MariaDB Galera 11.1.3', diff --git a/lib/python/tests/test_unit_query.py b/lib/python/tests/test_unit_query.py index 528d6775a7..719847fbfe 100644 --- a/lib/python/tests/test_unit_query.py +++ b/lib/python/tests/test_unit_query.py @@ -23,6 +23,7 @@ class QueryUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, tables=[Table(id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", name="Some Table", description="Test Table", diff --git a/lib/python/tests/test_unit_table.py b/lib/python/tests/test_unit_table.py index c67b54c614..8aa67d924e 100644 --- a/lib/python/tests/test_unit_table.py +++ b/lib/python/tests/test_unit_table.py @@ -1105,7 +1105,10 @@ class TableUnitTest(unittest.TestCase): def test_analyse_table_statistics_succeeds(self): with requests_mock.Mocker() as mock: exp = TableStatistics( - columns={"id": ColumnStatistic(val_min=1.0, val_max=9.0, mean=5.0, median=5.0, std_dev=2.73)}) + total_columns=1, + total_rows=1000, + columns={ + "id": ColumnStatistic(name="id", val_min=1.0, val_max=9.0, mean=5.0, median=5.0, std_dev=2.73)}) # mock mock.get( '/api/analyse/database/6bd39359-b154-456d-b9c2-caa516a45732/table/b3230b86-4743-498d-9015-3fad58049692/statistics', diff --git a/lib/python/tests/test_unit_view.py b/lib/python/tests/test_unit_view.py index cb26eeaba8..a3319f1fad 100644 --- a/lib/python/tests/test_unit_view.py +++ b/lib/python/tests/test_unit_view.py @@ -22,6 +22,7 @@ class ViewUnitTest(unittest.TestCase): internal_name='test_abcd', is_public=True, is_schema_public=True, + is_dashboard_enabled=True, tables=[Table(id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", name="Some Table", description="Test Table", diff --git a/make/build.mk b/make/build.mk index 968bd94d55..48e9212a6a 100644 --- a/make/build.mk +++ b/make/build.mk @@ -2,8 +2,9 @@ .PHONY: build-images build-images: ## Build Docker images. - docker build --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service + docker build --network=host -t dbrepo-core:build --target build ./lib/java/dbrepo-core docker build --network=host -t dbrepo-data-service:build --target build dbrepo-data-service + docker build --network=host -t dbrepo-metadata-service:build --target build dbrepo-metadata-service docker compose build --parallel .PHONY: build-data-service @@ -28,14 +29,20 @@ build-lib: ## Build the Python Library. rm -rf ./dbrepo-analyse-service/venv/ ./dbrepo-analyse-service/Pipfile.lock ./dbrepo-analyse-service/lib/* rm -rf ./dbrepo-search-service/venv/ ./dbrepo-search-service/Pipfile.lock ./dbrepo-search-service/lib/* rm -rf ./dbrepo-search-service/init/venv/ ./dbrepo-search-service/init/Pipfile.lock ./dbrepo-search-service/init/lib/* + rm -rf ./dbrepo-dashboard-service/venv/ ./dbrepo-dashboard-service/Pipfile.lock ./dbrepo-dashboard-service/lib/* + rm -rf ./dbrepo-dashboard-service/init/venv/ ./dbrepo-dashboard-service/init/Pipfile.lock ./dbrepo-dashboard-service/init/lib/* python3 -m build --sdist ./lib/python python3 -m build --wheel ./lib/python cp -r ./lib/python/dist/dbrepo-${APP_VERSION}* ./dbrepo-analyse-service/lib - (cd ./dbrepo-analyse-service && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) + (cd ./dbrepo-analyse-service && python3 -m venv venv && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) cp -r ./lib/python/dist/dbrepo-${APP_VERSION}* ./dbrepo-search-service/lib - (cd ./dbrepo-search-service && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) + (cd ./dbrepo-search-service && python3 -m venv venv && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) cp -r ./lib/python/dist/dbrepo-${APP_VERSION}* ./dbrepo-search-service/init/lib - (cd ./dbrepo-search-service/init && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) + (cd ./dbrepo-search-service/init && python3 -m venv venv && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) + cp -r ./lib/python/dist/dbrepo-${APP_VERSION}* ./dbrepo-dashboard-service/lib + (cd ./dbrepo-dashboard-service && python3 -m venv venv && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) + cp -r ./lib/python/dist/dbrepo-${APP_VERSION}* ./dbrepo-dashboard-service/init/lib + (cd ./dbrepo-dashboard-service/init && python3 -m venv venv && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install --dev) .PHONY: build-helm build-helm: ## Build the DBRepo and DBRepo MariaDB Galera Helm Charts. diff --git a/mkdocs.yml b/mkdocs.yml index 536eed294e..bf9e14a9dd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,5 @@ site_name: Database Repository -site_url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ +site_url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/ repo_url: https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services repo_name: fda-services site_author: Research Unit Data Science, Technische Universität Wien @@ -18,12 +18,12 @@ nav: - Overview: concepts/index.md - Authentication: concepts/authentication.md - Data Versioning: concepts/data-versioning.md + - Dashboards: concepts/dashboards.md - Data Visibility: concepts/data-visibility.md - Messaging: concepts/messaging.md - Monitoring: concepts/monitoring.md - Persistent Identifier: concepts/pid.md - Search: concepts/search.md - - User Interface: concepts/ui.md - API: - Overview: api/index.md - Databases: @@ -37,16 +37,14 @@ nav: - Analyse Service: api/analyse-service.md - Auth Service: api/auth-service.md - Broker Service: api/broker-service.md - - Dashboard Service: api/dashboard-service.md - Data Service: api/data-service.md - Gateway Service: api/gateway-service.md - Identity Service: api/identity-service.md - Metadata Service: api/metadata-service.md - Search Service: api/search-service.md - Storage Service: api/storage-service.md - - Upload Service: api/upload-service.md - UI: - - Customization: api/ui.md + - Repository: api/ui.md - Examples: - Air Quality Data: examples/air.md - COVID-19 Data: examples/covid-19.md @@ -120,9 +118,9 @@ markdown_extensions: custom_icons: - .docs/overrides/.icons extra: - homepage: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ + homepage: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.8/ version: - default: 1.7 + default: 1.8 provider: mike social: - icon: simple/artifacthub diff --git a/sonar-project.properties b/sonar-project.properties index 0ec728cec7..90e7004f97 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,7 +2,7 @@ sonar.projectKey=fair-data-austria-db-repository_fda-services_a57fa043-ab99-4cdd-a721-162d9a916d77 sonar.host.url=https://s39.datalab.tuwien.ac.at # project -sonar.projectVersion=1.7.3 +sonar.projectVersion=1.8.0 # general sonar.qualitygate.wait=true sonar.projectCreation.mainBranchName=master diff --git a/versions.json b/versions.json index 95ca2a62a6..0fafe8664c 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,9 @@ [ + { + "version": "1.8", + "title": "1.8", + "aliases": [] + }, { "version": "1.7", "title": "1.7", -- GitLab