diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 7817c84c7f6da1e595b076148cc8bdc105cdda08..cdeb4e3624f4f6aa78a0e1a1f6c3cfaa3cb33d20 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -109,7 +109,7 @@ services: dbrepo-auth-service-init: init: true restart: "no" - image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.1 environment: AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} @@ -130,7 +130,7 @@ services: restart: "no" container_name: dbrepo-metadata-service hostname: metadata-service - image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.1 volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: @@ -193,7 +193,7 @@ services: restart: "no" container_name: dbrepo-analyse-service hostname: analyse-service - image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.1 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -248,7 +248,7 @@ services: restart: "no" container_name: dbrepo-search-db hostname: search-db - image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.6.1 healthcheck: test: curl -sSL localhost:9200/_plugins/_security/health | jq .status | grep UP interval: 10s @@ -272,18 +272,20 @@ services: restart: "no" container_name: dbrepo-search-service hostname: search-service - image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.1 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} COLLECTION: ${COLLECTION:-['database','table','column','identifier','unit','concept','user','view']} + LOG_LEVEL: ${LOG_LEVEL:-info} 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} - LOG_LEVEL: ${LOG_LEVEL:-info} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: test: curl -sSL localhost:8080/health | grep 'UP' || exit 1 interval: 10s @@ -294,7 +296,7 @@ services: restart: "no" container_name: dbrepo-ui hostname: ui - image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.1 environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://localhost}" @@ -363,13 +365,16 @@ services: init: true container_name: dbrepo-search-service-init hostname: search-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.1 environment: + LOG_LEVEL: ${LOG_LEVEL:-info} 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} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" depends_on: dbrepo-search-db: condition: service_healthy @@ -417,7 +422,7 @@ services: restart: "no" container_name: dbrepo-dashboard-service hostname: dashboard-service - image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.6.1 ports: - "3000:3000" volumes: @@ -444,7 +449,7 @@ services: init: true container_name: dbrepo-storage-service-init hostname: storage-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.1 environment: S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-seaweedfsadmin} S3_BUCKET: "${S3_BUCKET:-dbrepo}" @@ -489,7 +494,7 @@ services: restart: "no" container_name: dbrepo-data-service hostname: data-service - image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.0 + image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.1 volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: diff --git a/.docs/.swagger/api.base.yaml b/.docs/.swagger/api.base.yaml index df4d4f97d02b4a3c379c5c967ee01537ab631e97..fc0a733ccc7e1c4134f8a444c9b6fe08acb7aabb 100644 --- a/.docs/.swagger/api.base.yaml +++ b/.docs/.swagger/api.base.yaml @@ -24,7 +24,7 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 title: DBRepo REST API - version: 1.6.0 + version: 1.6.1 openapi: 3.1.0 servers: - description: Test Instance diff --git a/.docs/.swagger/api.yaml b/.docs/.swagger/api.yaml index b99640757acf76ab5b009f68c9b6d8a85d8c183d..dc7a627e743279d6eddf788cc9b1c18411912e50 100644 --- a/.docs/.swagger/api.yaml +++ b/.docs/.swagger/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.6.0 + version: 1.6.1 servers: - description: Test Instance url: 'https://test.dbrepo.tuwien.ac.at' diff --git a/.docs/api/data-service.md b/.docs/api/data-service.md index 257c68c1957fa697957c9dfc3f6b681693ac3f9d..bc43a5d3631f7a9b4ecd85c64472bd25095a9603 100644 --- a/.docs/api/data-service.md +++ b/.docs/api/data-service.md @@ -24,25 +24,32 @@ author: Martin Weise ## Overview -The Data Service is responsible for inserting AMQP tuples from the Broker Service into the Data DB +The Data Service is responsible for inserting AMQP tuples from the Broker Service into the Data DB via [Spring AMQP](https://docs.spring.io/spring-amqp/reference/html/). To increase the number of consumers, scale the Data Service up. ## Data Processing -The Data Service uses [Apache Spark](https://spark.apache.org/), a data engine to load data from/into +The Data Service uses [Apache Spark](https://spark.apache.org/), a data engine to load data from/into the [Data Database](../data-db) with a wide range of open-source connectors. The default deployment uses a local mode of -embedded processing directly in the service until there exists +embedded processing directly in the service until there exists a [Bitnami Chart](https://artifacthub.io/packages/helm/bitnami/spark) for Spark 4. Retrieving data from a subset internally generates a view with the 64-character hash of the query. This view is not automatically deleted currently. +## Caching + +The Data Service uses [Caffeine](https://github.com/ben-manes/caffeine), a caching solution that is used to temporarily +cache the connection details from the [Metadata Service](../metadata-service) such that they don't have to be queried +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). + ## Limitations -* Views in DBRepo can only have 63-character length (it is assumed only internal views have the maximum length of 64 +* Views in DBRepo can only have 63-character length (it is assumed only internal views have the maximum length of 64 characters). -* Local mode of embedded processing of Apache Spark directly in the service using +* Local mode of embedded processing of Apache Spark directly in the service using a [`local[2]`](https://spark.apache.org/docs/latest/#running-the-examples-and-shell) configuration. !!! question "Do you miss functionality? Do these limitations affect you?" diff --git a/.docs/concepts/data-visibility.md b/.docs/concepts/data-visibility.md index e76448ec3eaddb09ecf7d601d37433f641f19751..04f37c6979bd9019d954859535a757c72da4b63e 100644 --- a/.docs/concepts/data-visibility.md +++ b/.docs/concepts/data-visibility.md @@ -2,32 +2,34 @@ author: Martin Weise --- -There are several ways to set the visibility of (meta-)data in DBRepo. It is possible to set the data to public/private -and the schema to be public/private for each database and separately for each table, each view and each subset of a -database. +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. + +## Visibility In total there are three possible scenarios: -## Public +#### Public !!! info "Possible use-case: data publication supplement to an open-access publication" -Where the database's data and metadata is set to be *public*. This means everything in the database (tables, views, +Where the database's data and metadata is set to be *visible*. This means everything in the database (tables, views, subsets) are visible by anyone from the public. -## Mixed +#### Private !!! info "Possible use-case: private sensor measurements with timed embargo" -Where the database's data and metadata is set to be *private*. This means everything in the database (tables, views, -subsets) are by default not visible by anyone from the public. You can however make specific views that join tables -and/or filter certain columns and apply a 14-day delay-embargo. +Where the database's data set to be *hidden* but the schema to be *visible*. This means everything in the database +(tables, views, subsets) are by default not visible by anyone from the public. You can however make specific views that +join tables and/or filter certain columns and apply a 14-day delay-embargo. <figure markdown>  <figcaption>Figure 1: Public view that joins two private tables and applies a time-embargo</figcaption> </figure> -## Private +#### Draft -!!! info "Possible use-case: data storage for trusted-/virtual research environments" \ No newline at end of file +!!! info "Possible use-case: project data storage before publication" \ No newline at end of file diff --git a/.docs/index.md b/.docs/index.md index e3307bd493e33dc0a03ce3fc2a770e726c30cd3f..e16f9f5da6ccc94637fc0c1b56868e4fda84b023 100644 --- a/.docs/index.md +++ b/.docs/index.md @@ -14,7 +14,7 @@ author: Martin Weise   -Documentation for version: [v1.6.0](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases). +Documentation for version: [v1.6.1](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 diff --git a/.docs/kubernetes.md b/.docs/kubernetes.md index 232584ee75a51aaa0eff2eff56bac6631406766c..cc16bbe210d1b4ea98cd27ad8c47248bc551bafb 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.6.0" \ + --version "1.6.1" \ --create-namespace \ --cleanup-on-fail ``` diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e71b7ee27f04784778509256cdd427c74ce5cf18..8bf70c0c712a5b76676b1d10d8663ff1f02a4923 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,8 +9,8 @@ variables: SONARQUBE_VERSION: "10.0" BUN_VERSION: "1.1.40" DOC_VERSION: "1.6" - APP_VERSION: "1.6.0" - CHART_VERSION: "1.6.0" + APP_VERSION: "1.6.1" + CHART_VERSION: "1.6.1" 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. diff --git a/Makefile b/Makefile index 11befeed00edf3090a7a0ac04296b95dd3ccbe7d..2479e382e55e3c20f1dd7f9c998fa5807a3f0e05 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: all -APP_VERSION ?= 1.6.0 -CHART_VERSION ?= 1.6.0 +APP_VERSION ?= 1.6.1 +CHART_VERSION ?= 1.6.1 REPOSITORY_URL ?= registry.datalab.tuwien.ac.at/dbrepo .PHONY: all diff --git a/dbrepo-analyse-service/Pipfile b/dbrepo-analyse-service/Pipfile index 69b9ee840951c7c27bb036d94057477ae73ceb52..831f8e532dd5f5796ca93cc6ca52fa7cecebb608 100644 --- a/dbrepo-analyse-service/Pipfile +++ b/dbrepo-analyse-service/Pipfile @@ -21,7 +21,7 @@ numpy = "*" pandas = "*" minio = "*" pydantic = "*" -dbrepo = {path = "./lib/dbrepo-1.6.0.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.6.1.tar.gz"} opensearch-py = "*" [dev-packages] diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index 0a59148511a9af575c5bd78df44601ab2b9d27b8..c668b400e4fa26855881c6b78400b2c66becbc0f 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e3a8db6afce757927a19df8fe01aea426b0f15868df14c8f98a83f2c19a688da" + "sha256": "683cc19a3205b9b5f9b99db8b71c0abadadfd652a94dcf710a73aeca92b97227" }, "pipfile-spec": 6, "requires": { @@ -175,20 +175,20 @@ }, "boto3": { "hashes": [ - "sha256:2446e819cf4e295833474cdcf2c92bc82718ce537e9ee1f17f7e3d237f60e69b", - "sha256:7de2c44c960e486f3c57e5203ea6393c6c4f0914c5f81c789ceb8b5d2ba5d1c5" + "sha256:258ab77225a81d3cf3029c9afe9920cd9dec317689dfadec6f6f0a23130bb60a", + "sha256:eb21380d73fec6645439c0d802210f72a0cdb3295b02953f246ff53f512faa8f" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.35.93" + "version": "==1.36.1" }, "botocore": { "hashes": [ - "sha256:47f7161000af6036f806449e3de12acdd3ec11aac7f5578e43e96241413a0f8f", - "sha256:b8d245a01e7d64c41edcf75a42be158df57b9518a83a3dbf5c7e4b8c2bc540cc" + "sha256:dec513b4eb8a847d79bbefdcdd07040ed9d44c20b0001136f0890a03d595705a", + "sha256:f789a6f272b5b3d8f8756495019785e33868e5e00dd9662a3ee7959ac939bb12" ], "markers": "python_version >= '3.8'", - "version": "==1.35.93" + "version": "==1.36.1" }, "certifi": { "hashes": [ @@ -268,7 +268,7 @@ "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" ], - "markers": "platform_python_implementation != 'PyPy'", + "markers": "python_version >= '3.8'", "version": "==1.17.1" }, "charset-normalizer": { @@ -412,9 +412,9 @@ }, "dbrepo": { "hashes": [ - "sha256:769c6d9c4475b26d3f752dcc9910346798d31afeca45ef014f48dd293074b8fb" + "sha256:251f3c2088bbd289cee86d5394b1e62e29aa081f994dd0845d895e3330f6a106" ], - "path": "./lib/dbrepo-1.6.0.tar.gz" + "path": "./lib/dbrepo-1.6.1.tar.gz" }, "events": { "hashes": [ @@ -1230,12 +1230,12 @@ }, "pydantic": { "hashes": [ - "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d", - "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06" + "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", + "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.10.4" + "version": "==2.10.5" }, "pydantic-core": { "hashes": [ @@ -1427,11 +1427,11 @@ }, "referencing": { "hashes": [ - "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", - "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" + "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794", + "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade" ], - "markers": "python_version >= '3.8'", - "version": "==0.35.1" + "markers": "python_version >= '3.9'", + "version": "==0.36.1" }, "requests": { "hashes": [ @@ -1553,19 +1553,19 @@ }, "s3transfer": { "hashes": [ - "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", - "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7" + "sha256:3f25c900a367c8b7f7d8f9c34edc87e300bde424f779dc9f0a8ae4f9df9264f6", + "sha256:8fa0aa48177be1f3425176dfe1ab85dcd3d962df603c3dbfc585e6bf857ef0ff" ], "markers": "python_version >= '3.8'", - "version": "==0.10.4" + "version": "==0.11.1" }, "setuptools": { "hashes": [ - "sha256:84fb203f278ebcf5cd08f97d3fb96d3fbed4b629d500b29ad60d11e00769b183", - "sha256:886ff7b16cd342f1d1defc16fc98c9ce3fde69e087a4e1983d7ab634e5f41f4f" + "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", + "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3" ], "markers": "python_version >= '3.9'", - "version": "==75.7.0" + "version": "==75.8.0" }, "six": { "hashes": [ @@ -1877,7 +1877,7 @@ "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" ], - "markers": "platform_python_implementation != 'PyPy'", + "markers": "python_version >= '3.8'", "version": "==1.17.1" }, "charset-normalizer": { @@ -2241,74 +2241,88 @@ }, "wrapt": { "hashes": [ - "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d", - "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301", - "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635", - "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a", - "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed", - "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721", - "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801", - "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b", - "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1", - "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88", - "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8", - "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0", - "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f", - "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578", - "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7", - "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045", - "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada", - "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d", - "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b", - "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a", - "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977", - "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea", - "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346", - "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13", - "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22", - "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339", - "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9", - "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181", - "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c", - "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90", - "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a", - "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489", - "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f", - "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504", - "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea", - "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569", - "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4", - "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce", - "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab", - "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a", - "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f", - "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c", - "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9", - "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf", - "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d", - "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627", - "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d", - "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4", - "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c", - "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d", - "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad", - "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b", - "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33", - "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371", - "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1", - "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393", - "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106", - "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df", - "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379", - "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451", - "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b", - "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575", - "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed", - "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb", - "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838" + "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.0" + "version": "==1.17.2" } } } diff --git a/dbrepo-analyse-service/lib/dbrepo-1.5.0.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.5.0.tar.gz deleted file mode 100644 index dfe9572952b2d1408cf85e7eef799ba83e8f60a0..0000000000000000000000000000000000000000 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.5.0.tar.gz and /dev/null differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.5.1.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.5.1.tar.gz deleted file mode 100644 index ca01f15711ae3ba792d5ecfca40356b50dda6b15..0000000000000000000000000000000000000000 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.5.1.tar.gz and /dev/null differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.5.2.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.5.2.tar.gz deleted file mode 100644 index 52bf0fe9a030ce509450bc52427eb7e2c1f1da13..0000000000000000000000000000000000000000 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.5.2.tar.gz and /dev/null differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz deleted file mode 100644 index 2bb796d8fece2d97c3b2168248ff493dfa24a549..0000000000000000000000000000000000000000 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz and /dev/null differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.1.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.6.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..7914db1bb84dddf85611cda3b766c0c0cdc094c7 Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.6.1.tar.gz differ diff --git a/dbrepo-auth-service/init/app.py b/dbrepo-auth-service/init/app.py index 7d43f163fa3f50e326ba71933674500121d9fef2..948ed9fe2c16124367d0bb206177128310d45e5e 100644 --- a/dbrepo-auth-service/init/app.py +++ b/dbrepo-auth-service/init/app.py @@ -1,4 +1,7 @@ +import logging import os +import sys + import mariadb from keycloak import KeycloakAdmin @@ -8,8 +11,24 @@ admin = KeycloakAdmin(server_url=os.getenv('AUTH_SERVICE_ENDPOINT', 'http://loca username=os.getenv('AUTH_SERVICE_ADMIN', 'admin'), password=os.getenv('AUTH_SERVICE_ADMIN_PASSWORD', 'admin'), verify=True) -user_id = admin.get_user_id(username=system_username) -print(f'Successfully fetched user id: {user_id}') +keycloak_user_id = admin.get_user_id(username=system_username) +logging.info(f'Successfully fetched keycloak user id: {keycloak_user_id}') +ldap_user = admin.get_user(user_id=keycloak_user_id) +if ldap_user is None: + logging.error(f'Failed to obtain user') + sys.exit(1) +ldap_user_attrs = ldap_user.get('attributes') +if ldap_user_attrs is None: + logging.error(f'Failed to obtain user attributes') + sys.exit(1) +if 'LDAP_ID' not in ldap_user_attrs: + logging.error(f'Failed to obtain ldap id: LDAP_ID not in attributes {ldap_user_attrs}') + sys.exit(1) +if len(ldap_user_attrs['LDAP_ID']) != 1: + logging.error(f'Failed to obtain ldap id: wrong length {len(ldap_user_attrs["LDAP_ID"])} != 1') + sys.exit(1) +ldap_user_id = ldap_user_attrs['LDAP_ID'][0] +logging.info(f'Successfully fetched ldap user id: {ldap_user_id}') try: conn = mariadb.connect(user=os.getenv('METADATA_USERNAME', 'root'), @@ -19,13 +38,13 @@ try: database=os.getenv('METADATA_DB', 'dbrepo')) cursor = conn.cursor() cursor.execute( - "INSERT IGNORE INTO `mdb_users` (`id`, `username`, `email`, `mariadb_password`) VALUES (?, ?, ?, PASSWORD(?))", - (user_id, system_username, 'some@admin', '1234567890')) + "INSERT IGNORE INTO `mdb_users` (`id`, `username`, `email`, `mariadb_password`, `is_internal`) VALUES (?, ?, LEFT(UUID(), 20), PASSWORD(LEFT(UUID(), 20)), true)", + (ldap_user_id, system_username)) conn.commit() conn.close() except mariadb.Error as e: - print(f"Error connecting to MariaDB Platform: {e}") + logging.info(f"Error connecting to MariaDB Platform: {e}") exit(1) -print(f'Successfully inserted user') +logging.info(f'Successfully inserted user') exit(0) diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 0b244a12a46ec7d9ec25ba86fd01c9f2d5b97d5f..884824994aff8a6e8f05bce24c44307ffe64c2b8 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -11,7 +11,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> <name>dbrepo-data-service</name> - <version>1.6.0</version> + <version>1.6.1</version> <description>Service that manages the data</description> @@ -60,6 +60,8 @@ <!-- see https://github.com/apache/spark/blob/cde8e4a82e20a363861f451ebd5138efb3194ab8/pom.xml --> <hadoop.version>3.4.0</hadoop.version> <jakarta-servlet.version>5.0.0</jakarta-servlet.version> + <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + </sonar.coverage.jacoco.xmlReportPaths> </properties> <dependencies> diff --git a/dbrepo-data-service/querystore/pom.xml b/dbrepo-data-service/querystore/pom.xml index 3917fc4976354fffd39805995f82e9a322742631..943c115d117529adea091f02f77037367c12a32c 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-data-service-querystore</artifactId> <name>dbrepo-data-service-querystore</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies/> diff --git a/dbrepo-data-service/report/pom.xml b/dbrepo-data-service/report/pom.xml index 99c9261cea42c59e2daa5c68140e971c410874be..ca03190a449b76f7217590283097978be9d8a0ab 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>report</artifactId> <name>dbrepo-data-service-report</name> - <version>1.6.0</version> + <version>1.6.1</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 9eb0cddee6c2577ea82dbe09f71f13192bc1a4c4..e72392c7071cb3083c894fbc3654266f34650f01 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>rest-service</artifactId> <name>dbrepo-data-service-rest-service</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>services</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> </dependency> </dependencies> diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java index 334128637ec5113e6478567d30e44b2f61ea3f5b..87a4d32532c586c0f2517862f0cd3cc104f4f054 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java @@ -1,14 +1,50 @@ package at.tuwien.endpoints; +import at.tuwien.api.user.UserDetailsDto; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; +import org.springframework.security.core.Authentication; +import java.security.Principal; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +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; + final UserDetailsDto user = (UserDetailsDto) authentication.getPrincipal(); + if (user.getId() == null) { + return null; + } + return UUID.fromString(user.getId()); + } + public List<Map<String, Object>> transform(Dataset<Row> dataset) { return dataset.collectAsList() .stream() 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 64d69a9013647c3bd886a690172994fcc382de95..7947e87a495595441c945e950453499c635aaac2 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 @@ -29,7 +29,7 @@ import java.util.UUID; @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database/{databaseId}/access") -public class AccessEndpoint { +public class AccessEndpoint extends AbstractEndpoint { private final AccessService accessService; private final CredentialService credentialService; @@ -139,7 +139,7 @@ public class AccessEndpoint { access.getType()); final PrivilegedDatabaseDto database = credentialService.getDatabase(databaseId); final PrivilegedUserDto user = credentialService.getUser(userId); - if (database.getAccesses().stream().noneMatch(a -> a.getUser().getId().equals(userId))) { + if (database.getAccesses().stream().noneMatch(a -> a.getHuserid().equals(userId))) { log.error("Failed to update access to user with id {}: no access", userId); throw new NotAllowedException("Failed to update access to user with id " + userId + ": no access"); } 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 0043b64dfe742fa97ea8a9bdbef671b5cc6118c1..d101a8c97393a41ecf4e76ea4e4fb4aa3c1f4993 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 @@ -35,7 +35,7 @@ import java.sql.SQLException; @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database") -public class DatabaseEndpoint { +public class DatabaseEndpoint extends AbstractEndpoint { private final SubsetService queryService; private final AccessService accessService; 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 4f1b5d59c94cee09b4666a8171367cd9d737ea27..f30251a5ff09e895a7324a9857134c789f6b3c03 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 @@ -11,7 +11,6 @@ import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -73,7 +72,7 @@ public class SubsetEndpoint extends AbstractEndpoint { @GetMapping @Observed(name = "dbrepo_subset_list") @Operation(summary = "Find subsets", - description = "Finds subsets in the query store. The result can be optionally filtered by setting `persisted`. When set to *true*, only persisted queries are returned, otherwise only non-persisted queries are returned.", + description = "Finds subsets in the query store. When the database schema is marked as hidden, the user needs to be authorized, have at least read-access to the database. The result can be optionally filtered by setting `persisted`. When set to *true*, only persisted queries are returned, otherwise only non-persisted queries are returned.", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -98,11 +97,13 @@ public class SubsetEndpoint extends AbstractEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<List<QueryDto>> list(@NotNull @PathVariable("databaseId") Long databaseId, - @RequestParam(name = "persisted", required = false) Boolean filterPersisted) + @RequestParam(name = "persisted", required = false) Boolean filterPersisted, + Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, NotAllowedException, MetadataServiceException { log.debug("endpoint find subsets in database, databaseId={}, filterPersisted={}", databaseId, filterPersisted); final PrivilegedDatabaseDto database = credentialService.getDatabase(databaseId); + endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); final List<QueryDto> queries; try { queries = subsetService.findAll(database, filterPersisted); @@ -117,7 +118,7 @@ public class SubsetEndpoint extends AbstractEndpoint { @GetMapping("/{subsetId}") @Observed(name = "dbrepo_subset_find") @Operation(summary = "Find subset", - description = "Finds a subset in the data database. Requests with HTTP header `Accept=application/json` return the metadata, requests with HTTP header `Accept=text/csv` return the data as downloadable file.", + description = "Finds a subset in the data database. When the database schema is marked as hidden, the user needs to be authorized, have at least read-access to the database. Requests with HTTP header `Accept=application/json` return the metadata, requests with HTTP header `Accept=text/csv` return the data as downloadable file.", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -154,15 +155,17 @@ public class SubsetEndpoint extends AbstractEndpoint { }) public ResponseEntity<?> findById(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("subsetId") Long subsetId, - @NotNull HttpServletRequest httpServletRequest, - @RequestParam(required = false) Instant timestamp) + @NotNull @RequestHeader("Accept") String accept, + @RequestParam(required = false) Instant timestamp, + Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, UserNotFoundException, - MetadataServiceException, TableNotFoundException, ViewMalformedException, QueryMalformedException { - String accept = httpServletRequest.getHeader("Accept"); + MetadataServiceException, TableNotFoundException, ViewMalformedException, QueryMalformedException, + NotAllowedException { log.debug("endpoint find subset in database, databaseId={}, subsetId={}, accept={}, timestamp={}", databaseId, subsetId, accept, timestamp); final PrivilegedDatabaseDto database = credentialService.getDatabase(databaseId); + endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); final QueryDto subset; try { subset = subsetService.findById(database, subsetId); @@ -175,7 +178,7 @@ public class SubsetEndpoint extends AbstractEndpoint { timestamp = Instant.now(); log.debug("timestamp not set: default to {}", timestamp); } - if (accept == null) { + if (accept == null || accept.isEmpty() || accept.isBlank()) { accept = MediaType.APPLICATION_JSON_VALUE; log.debug("accept header not set: default to {}", accept); } @@ -200,13 +203,13 @@ public class SubsetEndpoint extends AbstractEndpoint { throw new DatabaseUnavailableException("Failed to find data: " + e.getMessage(), e); } } - throw new FormatNotAvailableException("Must provide either application/json or text/csv headers"); + throw new FormatNotAvailableException("Must provide either application/json or text/csv value for header 'Accept': provided " + accept + " instead"); } @PostMapping @Observed(name = "dbrepo_subset_create") @Operation(summary = "Create subset", - description = "Creates a subset in the query store of the data database. Requires role `execute-query` for private databases.", + description = "Creates a subset in the query store of the data database. Can also be used without authentication if (and only if) the database is marked as public (i.e. when `is_public` = `is_schema_public` is set to `true`). Otherwise at least read access is required.", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -264,7 +267,12 @@ public class SubsetEndpoint extends AbstractEndpoint { endpointValidator.validateDataParams(page, size); endpointValidator.validateForbiddenStatements(data.getStatement()); /* parameters */ - final UUID userId = principal != null ? UserUtil.getId(principal) : null; + final UUID userId; + if (principal != null) { + userId = getId(principal); + } else { + userId = null; + } if (page == null) { page = 0L; log.debug("page not set: default to {}", page); @@ -279,6 +287,7 @@ public class SubsetEndpoint extends AbstractEndpoint { } /* create */ final PrivilegedDatabaseDto database = credentialService.getDatabase(databaseId); + endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); try { final Long subsetId = subsetService.create(database, data.getStatement(), timestamp, userId); return getData(databaseId, subsetId, principal, request, page, size); @@ -342,8 +351,9 @@ public class SubsetEndpoint extends AbstractEndpoint { log.error("Failed to re-execute query: no authentication found"); throw new NotAllowedException("Failed to re-execute query: no authentication found"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } + log.trace("visibility for database: is_public={}, is_schema_public={}", database.getIsPublic(), database.getIsSchemaPublic()); /* parameters */ if (page == null) { page = 0L; @@ -426,7 +436,7 @@ public class SubsetEndpoint extends AbstractEndpoint { log.debug("endpoint persist query, databaseId={}, queryId={}, data.persist={}, principal.name={}", databaseId, queryId, data.getPersist(), principal.getName()); final PrivilegedDatabaseDto database = credentialService.getDatabase(databaseId); - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); try { subsetService.persist(database, queryId, data.getPersist()); final QueryDto dto = subsetService.findById(database, queryId); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 11720b49063e9ba0c1dbc1b1f844aa215a6b3b4d..f0ec00a035e729157726b65af9f3c85949581c4e 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 @@ -13,7 +13,6 @@ import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -277,7 +276,7 @@ public class TableEndpoint extends AbstractEndpoint { log.error("Failed find table data: authentication required"); throw new NotAllowedException("Failed to find table data: authentication required"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } try { final HttpHeaders headers = new HttpHeaders(); @@ -335,17 +334,18 @@ public class TableEndpoint extends AbstractEndpoint { public ResponseEntity<Void> insertRawTuple(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @Valid @RequestBody TupleDto data, - @NotNull Principal principal) + @NotNull Principal principal, + @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException, StorageUnavailableException, StorageNotFoundException, MetadataServiceException { log.debug("endpoint insert raw table data, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, UserUtil.getId(principal)); - endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); + final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); try { tableService.createTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.CREATED) .build(); } catch (SQLException e) { @@ -387,17 +387,18 @@ public class TableEndpoint extends AbstractEndpoint { public ResponseEntity<Void> updateRawTuple(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @Valid @RequestBody TupleUpdateDto data, - @NotNull Principal principal) + @NotNull Principal principal, + @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { log.debug("endpoint update raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, UserUtil.getId(principal)); - endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); + final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); try { tableService.updateTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -439,17 +440,18 @@ public class TableEndpoint extends AbstractEndpoint { public ResponseEntity<Void> deleteRawTuple(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @Valid @RequestBody TupleDeleteDto data, - @NotNull Principal principal) + @NotNull Principal principal, + @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { log.debug("endpoint delete raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, UserUtil.getId(principal)); - endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); + final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); try { tableService.deleteTuple(table, data); - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -510,7 +512,7 @@ public class TableEndpoint extends AbstractEndpoint { log.error("Failed to find table history: no authentication found"); throw new NotAllowedException("Failed to find table history: no authentication found"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } try { final List<TableHistoryDto> dto = tableService.history(table, size); @@ -622,7 +624,7 @@ public class TableEndpoint extends AbstractEndpoint { log.error("Failed to export private table: principal is null"); throw new NotAllowedException("Failed to export private table: principal is null"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } final Dataset<Row> dataset = tableService.getData(table.getDatabase(), table.getInternalName(), timestamp, null, null, null, null); @@ -669,14 +671,15 @@ public class TableEndpoint extends AbstractEndpoint { public ResponseEntity<Void> importDataset(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @Valid @RequestBody ImportDto data, - @NotNull Principal principal) + @NotNull Principal principal, + @RequestHeader("Authorization") String authorization) throws RemoteUnavailableException, TableNotFoundException, NotAllowedException, MetadataServiceException, StorageNotFoundException, MalformedException, StorageUnavailableException, QueryMalformedException, DatabaseUnavailableException { log.debug("endpoint insert table data, databaseId={}, tableId={}, data.location={}", databaseId, tableId, data.getLocation()); final PrivilegedTableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, UserUtil.getId(principal)); - endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), UserUtil.getId(principal)); + final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); if (data.getLineTermination() == null) { data.setLineTermination("\\r\\n"); log.debug("line termination not present, default to {}", data.getLineTermination()); @@ -687,7 +690,7 @@ public class TableEndpoint extends AbstractEndpoint { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database", e); } - metadataServiceGateway.updateTableStatistics(databaseId, tableId); + metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.accepted() .build(); } 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 c8da4239861264539b2140c64fde2b95a8fb8bc4..2b0463483d66429dfb0afd942bbc80ccdfb2fd26 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 @@ -9,7 +9,6 @@ import at.tuwien.api.database.internal.PrivilegedViewDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -275,7 +274,7 @@ public class ViewEndpoint extends AbstractEndpoint { log.error("Failed to get data from view: unauthorized"); throw new NotAllowedException("Failed to get data from view: unauthorized"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } try { final HttpHeaders headers = new HttpHeaders(); @@ -351,7 +350,7 @@ public class ViewEndpoint extends AbstractEndpoint { log.error("Failed to export private view: principal is null"); throw new NotAllowedException("Failed to export private view: principal is null"); } - credentialService.getAccess(databaseId, UserUtil.getId(principal)); + credentialService.getAccess(databaseId, getId(principal)); } final Dataset<Row> dataset = tableService.getData(view.getDatabase(), view.getInternalName(), timestamp, null, null, null, null); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/utils/UserUtil.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/utils/UserUtil.java deleted file mode 100644 index 7a99e839edd3b97758e713260f798ae5357c53c6..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/utils/UserUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package at.tuwien.utils; - -import at.tuwien.api.user.UserDetailsDto; -import org.springframework.security.core.Authentication; - -import java.security.Principal; -import java.util.UUID; - -public class UserUtil { - - public static 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 static UUID getId(Principal principal) { - if (principal == null) { - return null; - } - final Authentication authentication = (Authentication) principal; - final UserDetailsDto user = (UserDetailsDto) authentication.getPrincipal(); - if (user.getId() == null) { - return null; - } - return UUID.fromString(user.getId()); - } - -} 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 1c6adfd6a5b87355e76f9b40147fe91f5de4d4e2..25b858f51bd3f643f7879b9eac2dbb648b00aabb 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,14 +1,17 @@ package at.tuwien.validation; import at.tuwien.api.database.AccessTypeDto; +import at.tuwien.api.database.DatabaseAccessDto; +import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.config.QueryConfig; -import at.tuwien.exception.NotAllowedException; -import at.tuwien.exception.PaginationException; -import at.tuwien.exception.QueryNotSupportedException; +import at.tuwien.endpoints.AbstractEndpoint; +import at.tuwien.exception.*; +import at.tuwien.gateway.MetadataServiceGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.security.Principal; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -18,13 +21,15 @@ import java.util.regex.Pattern; @Log4j2 @Component -public class EndpointValidator { +public class EndpointValidator extends AbstractEndpoint { private final QueryConfig queryConfig; + private final MetadataServiceGateway metadataServiceGateway; @Autowired - public EndpointValidator(QueryConfig queryConfig) { + public EndpointValidator(QueryConfig queryConfig, MetadataServiceGateway metadataServiceGateway) { this.queryConfig = queryConfig; + this.metadataServiceGateway = metadataServiceGateway; } public void validateDataParams(Long page, Long size) throws PaginationException { @@ -43,6 +48,56 @@ public class EndpointValidator { } } + public void validateOnlyPrivateSchemaAccess(PrivilegedDatabaseDto database, Principal principal) + throws NotAllowedException, RemoteUnavailableException, MetadataServiceException { + validateOnlyPrivateSchemaAccess(database, principal, false); + } + + public void validateOnlyPrivateSchemaAccess(PrivilegedDatabaseDto database, Principal principal, + boolean writeAccessOnly) throws NotAllowedException, + RemoteUnavailableException, MetadataServiceException { + if (database.getIsSchemaPublic()) { + log.trace("database schema with id {} is public: no access needed", database.getId()); + return; + } + validateOnlyAccess(database, principal, writeAccessOnly); + } + + public void validateOnlyPrivateSchemaHasRole(PrivilegedDatabaseDto database, Principal principal, String role) + throws NotAllowedException { + if (database.getIsSchemaPublic()) { + log.trace("database with id {} has public schema: no access needed", database.getId()); + return; + } + log.trace("database with id {} has private schema", database.getId()); + if (principal == null) { + log.error("Access not allowed: no authorization provided"); + throw new NotAllowedException("Access not allowed: no authorization provided"); + } + log.trace("principal: {}", principal.getName()); + if (!hasRole(principal, role)) { + log.error("Access not allowed: role {} missing", role); + throw new NotAllowedException("Access not allowed: role " + role + " missing"); + } + log.trace("principal has role '{}': access granted", role); + } + + public void validateOnlyAccess(PrivilegedDatabaseDto database, Principal principal, boolean writeAccessOnly) + throws NotAllowedException, RemoteUnavailableException, MetadataServiceException { + if (principal == null) { + throw new NotAllowedException("No principal provided"); + } + if (isSystem(principal)) { + return; + } + final DatabaseAccessDto access = metadataServiceGateway.getAccess(database.getId(), getId(principal)); + log.trace("found access: {}", access); + if (writeAccessOnly && !(access.getType().equals(AccessTypeDto.WRITE_OWN) || access.getType().equals(AccessTypeDto.WRITE_ALL))) { + log.error("Access not allowed: no write access"); + throw new NotAllowedException("Access not allowed: no write access"); + } + } + public void validateForbiddenStatements(String query) throws QueryNotSupportedException { final List<String> words = new LinkedList<>(); Arrays.stream(queryConfig.getForbiddenKeywords()) 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 03d89895cb607cee20bc84cd8cd3195c029a9ab8..b5f592d570cb73677baaa00666af945901e1d256 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml @@ -74,7 +74,7 @@ dbrepo: 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}" - credentialCacheTimeout: "${CREDENTIAL_CACHE_TIMEOUT:3600}" + credentialCacheTimeout: "${CREDENTIAL_CACHE_TIMEOUT:60}" 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/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index e7de4a04b3b48d089d254d4da2d442ba4a5334f7..8a08f8231fe0de7babf1db995dc60786407425f8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -6,6 +6,7 @@ import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryPersistDto; import at.tuwien.endpoints.SubsetEndpoint; import at.tuwien.exception.*; +import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.CredentialService; import at.tuwien.service.SchemaService; import at.tuwien.service.StorageService; @@ -23,13 +24,13 @@ 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.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; 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.sql.SQLException; import java.time.Instant; import java.util.List; @@ -55,6 +56,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @MockBean private SchemaService schemaService; + @MockBean + private MetadataServiceGateway metadataServiceGateway; + @MockBean private HttpServletRequest httpServletRequest; @@ -74,15 +78,31 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void list_succeeds() throws DatabaseUnavailableException, NotAllowedException, QueryNotFoundException, - DatabaseNotFoundException, RemoteUnavailableException, SQLException, MetadataServiceException { + public void list_publicDataPrivateSchemaAnonymous_fails() throws QueryNotFoundException, DatabaseNotFoundException, + RemoteUnavailableException, SQLException, MetadataServiceException { /* mock */ when(subsetService.findAll(DATABASE_3_PRIVILEGED_DTO, null)) .thenReturn(List.of(QUERY_1_DTO, QUERY_2_DTO, QUERY_3_DTO, QUERY_4_DTO, QUERY_5_DTO, QUERY_6_DTO)); /* test */ - final List<QueryDto> response = generic_list(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO); + assertThrows(NotAllowedException.class, () -> { + generic_list(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO, null); + }); + } + + @Test + @WithMockUser(username = USER_3_USERNAME) + public void list_publicDataPrivateSchema_succeeds() throws DatabaseUnavailableException, NotAllowedException, + QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, SQLException, + MetadataServiceException { + + /* mock */ + when(subsetService.findAll(DATABASE_3_PRIVILEGED_DTO, null)) + .thenReturn(List.of(QUERY_1_DTO, QUERY_2_DTO, QUERY_3_DTO, QUERY_4_DTO, QUERY_5_DTO, QUERY_6_DTO)); + + /* test */ + final List<QueryDto> response = generic_list(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO, USER_3_PRINCIPAL); assertEquals(6, response.size()); } @@ -92,14 +112,14 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - generic_list(null, null); + generic_list(null, null, null); }); } @Test - @WithAnonymousUser - public void list_unavailable_fails() throws SQLException, QueryNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, MetadataServiceException { + @WithMockUser(username = USER_3_USERNAME) + public void list_publicDataAndPrivateSchemaUnavailable_fails() throws SQLException, QueryNotFoundException, + DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException { /* mock */ when(credentialService.getDatabase(DATABASE_3_ID)) @@ -110,15 +130,48 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - generic_list(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO); + generic_list(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO, USER_3_PRINCIPAL); }); } @Test @WithAnonymousUser - public void findById_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, - FormatNotAvailableException, TableNotFoundException, MetadataServiceException, SQLException, + public void findById_privateDataPrivateSchemaAnonymous_fails() throws DatabaseNotFoundException, SQLException, + RemoteUnavailableException, UserNotFoundException, QueryNotFoundException, MetadataServiceException { + + /* mock */ + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_1_PRIVILEGED_DTO, QUERY_1_ID)) + .thenReturn(QUERY_1_DTO); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_findById(DATABASE_1_ID, QUERY_1_ID, "application/json", null, null); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void findById_privateDataPrivateSchema_succeeds() throws DatabaseNotFoundException, SQLException, + RemoteUnavailableException, UserNotFoundException, QueryNotFoundException, MetadataServiceException, DatabaseUnavailableException, TableNotFoundException, StorageUnavailableException, NotAllowedException, ViewMalformedException, QueryMalformedException, FormatNotAvailableException { + + /* mock */ + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_1_PRIVILEGED_DTO, QUERY_1_ID)) + .thenReturn(QUERY_1_DTO); + + /* test */ + generic_findById(DATABASE_1_ID, QUERY_1_ID, "application/json", null, USER_1_PRINCIPAL); + } + + @Test + @WithMockUser(username = USER_3_USERNAME) + public void findById_publicDataPrivateSchema_succeeds() throws DatabaseNotFoundException, SQLException, + RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, NotAllowedException, + StorageUnavailableException, QueryMalformedException, QueryNotFoundException, + FormatNotAvailableException, TableNotFoundException, MetadataServiceException, ViewMalformedException { /* mock */ @@ -128,7 +181,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .thenReturn(QUERY_5_DTO); /* test */ - generic_findById(QUERY_5_ID, MediaType.APPLICATION_JSON, null); + generic_findById(DATABASE_3_ID, QUERY_5_ID, "application/json", null, USER_3_PRINCIPAL); } @Test @@ -137,29 +190,29 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { UserNotFoundException, QueryNotFoundException, MetadataServiceException { /* mock */ - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(subsetService.findById(DATABASE_3_PRIVILEGED_DTO, QUERY_5_ID)) - .thenReturn(QUERY_5_DTO); + when(credentialService.getDatabase(DATABASE_4_ID)) + .thenReturn(DATABASE_4_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_4_PRIVILEGED_DTO, QUERY_7_ID)) + .thenReturn(QUERY_7_DTO); /* test */ assertThrows(FormatNotAvailableException.class, () -> { - generic_findById(QUERY_5_ID, MediaType.APPLICATION_PDF, null); + generic_findById(DATABASE_4_ID, QUERY_7_ID, "application/pdf", null, null); }); } @Test - @WithAnonymousUser - public void findById_acceptCsv_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, + @WithMockUser(username = USER_1_USERNAME) + public void findById_privateDataPrivateSchemaAcceptCsv_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, FormatNotAvailableException, SQLException, MetadataServiceException, - TableNotFoundException, ViewMalformedException { + TableNotFoundException, ViewMalformedException, NotAllowedException { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(subsetService.findById(DATABASE_3_PRIVILEGED_DTO, QUERY_5_ID)) + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_1_PRIVILEGED_DTO, QUERY_1_ID)) .thenReturn(QUERY_5_DTO); when(storageService.transformDataset(any(Dataset.class))) .thenReturn(EXPORT_RESOURCE_DTO); @@ -167,15 +220,15 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .thenReturn(mock); /* test */ - generic_findById(QUERY_5_ID, MediaType.parseMediaType("text/csv"), null); + generic_findById(DATABASE_1_ID, QUERY_1_ID, "text/csv", null, USER_1_PRINCIPAL); } @Test @WithAnonymousUser - public void findById_timestamp_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, - QueryNotFoundException, FormatNotAvailableException, SQLException, MetadataServiceException, - TableNotFoundException, ViewMalformedException { + public void findById_publicDataPrivateSchemaAnonymous_fails() throws DatabaseNotFoundException, + RemoteUnavailableException, UserNotFoundException, StorageUnavailableException, QueryMalformedException, + QueryNotFoundException, SQLException, MetadataServiceException, TableNotFoundException, + ViewMalformedException { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ @@ -189,12 +242,38 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .thenReturn(EXPORT_RESOURCE_DTO); /* test */ - generic_findById(QUERY_5_ID, MediaType.parseMediaType("text/csv"), Instant.now()); + assertThrows(NotAllowedException.class, () -> { + generic_findById(DATABASE_3_ID, QUERY_5_ID, "text/csv", Instant.now(), null); + }); } @Test @WithAnonymousUser - public void findById_notFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException { + public void findById_publicDataPublicSchemaAnonymous_fails() throws DatabaseNotFoundException, SQLException, + RemoteUnavailableException, UserNotFoundException, QueryMalformedException, StorageUnavailableException, + QueryNotFoundException, MetadataServiceException, TableNotFoundException, ViewMalformedException { + final Dataset<Row> mock = sparkSession.emptyDataFrame(); + + /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_4_PRIVILEGED_DTO, QUERY_5_ID)) + .thenReturn(QUERY_5_DTO); + when(subsetService.getData(any(PrivilegedDatabaseDto.class), any(QueryDto.class), eq(null), eq(null))) + .thenReturn(mock); + when(storageService.transformDataset(any(Dataset.class))) + .thenReturn(EXPORT_RESOURCE_DTO); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_findById(DATABASE_3_ID, QUERY_5_ID, "text/csv", Instant.now(), null); + }); + } + + @Test + @WithAnonymousUser + public void findById_notFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -203,13 +282,13 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - generic_findById(QUERY_5_ID, MediaType.APPLICATION_JSON, null); + generic_findById(DATABASE_3_ID, QUERY_5_ID, "application/json", null, null); }); } @Test - @WithAnonymousUser - public void findById_unavailable_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + @WithMockUser(username = USER_3_USERNAME) + public void findById_publicDataAndPrivateSchemaUnavailable_fails() throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException, SQLException, UserNotFoundException, QueryNotFoundException { /* mock */ @@ -221,13 +300,13 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - generic_findById(QUERY_5_ID, MediaType.APPLICATION_JSON, null); + generic_findById(DATABASE_3_ID, QUERY_5_ID, "application/json", null, USER_3_PRINCIPAL); }); } @Test - @WithAnonymousUser - public void findById_unavailableExport_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + @WithMockUser(username = USER_1_USERNAME) + public void findById_publicDataPrivateSchemaUnavailableExport_fails() throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException, SQLException, QueryMalformedException, UserNotFoundException, QueryNotFoundException, TableNotFoundException, ViewMalformedException, StorageUnavailableException { @@ -244,7 +323,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - generic_findById(QUERY_5_ID, MediaType.parseMediaType("text/csv"), null); + generic_findById(DATABASE_3_ID, QUERY_5_ID, "text/csv", null, USER_1_PRINCIPAL); }); } @@ -326,7 +405,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-query"}) public void create_unavailable_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, SQLException, MetadataServiceException, QueryMalformedException, TableNotFoundException, - ViewMalformedException, UserNotFoundException, QueryNotFoundException, QueryStoreInsertException { + ViewMalformedException, UserNotFoundException, QueryNotFoundException, QueryStoreInsertException, + NotAllowedException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -339,6 +419,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(null), eq(null)); when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong())) .thenReturn(QUERY_5_DTO); + when(metadataServiceGateway.getAccess(DATABASE_3_ID, USER_1_ID)) + .thenReturn(DATABASE_3_USER_1_READ_ACCESS_DTO); doThrow(SQLException.class) .when(subsetService) .create(eq(DATABASE_3_PRIVILEGED_DTO), eq(QUERY_5_STATEMENT), any(Instant.class), eq(USER_1_ID)); @@ -402,7 +484,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void create_anonymous_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, + public void create_publicDataPublicSchemaAnonymous_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException, UserNotFoundException, QueryStoreInsertException, TableMalformedException, NotAllowedException, SQLException, QueryNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotSupportedException, PaginationException, @@ -413,19 +495,75 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .build(); /* mock */ - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong())) + when(credentialService.getDatabase(DATABASE_4_ID)) + .thenReturn(DATABASE_4_PRIVILEGED_DTO); + when(subsetService.findById(eq(DATABASE_4_PRIVILEGED_DTO), anyLong())) .thenReturn(QUERY_5_DTO); - when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L))) + when(subsetService.getData(eq(DATABASE_4_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L))) .thenReturn(mock); - when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString())) + when(schemaService.inspectView(eq(DATABASE_4_PRIVILEGED_DTO), anyString())) .thenReturn(VIEW_5_DTO); when(httpServletRequest.getMethod()) .thenReturn("POST"); /* test */ - subsetEndpoint.create(DATABASE_3_ID, request, null, httpServletRequest, null, null, null); + subsetEndpoint.create(DATABASE_4_ID, request, null, httpServletRequest, null, null, null); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void create_privateDataPrivateSchema_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, + MetadataServiceException, UserNotFoundException, QueryStoreInsertException, TableMalformedException, + NotAllowedException, SQLException, QueryNotFoundException, DatabaseUnavailableException, + StorageUnavailableException, QueryMalformedException, QueryNotSupportedException, PaginationException, + StorageNotFoundException, TableNotFoundException, ViewMalformedException, ViewNotFoundException { + final Dataset<Row> mock = sparkSession.emptyDataFrame(); + final ExecuteStatementDto request = ExecuteStatementDto.builder() + .statement(QUERY_1_STATEMENT) + .build(); + + /* mock */ + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(subsetService.findById(eq(DATABASE_1_PRIVILEGED_DTO), anyLong())) + .thenReturn(QUERY_1_DTO); + when(subsetService.getData(eq(DATABASE_1_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L))) + .thenReturn(mock); + when(schemaService.inspectView(eq(DATABASE_1_PRIVILEGED_DTO), anyString())) + .thenReturn(VIEW_1_DTO); + when(httpServletRequest.getMethod()) + .thenReturn("POST"); + + /* test */ + subsetEndpoint.create(DATABASE_1_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, null, null); + } + + @Test + @WithAnonymousUser + public void create_privateDataPublicSchemaAnonymous_fails() throws DatabaseNotFoundException, SQLException, + MetadataServiceException, UserNotFoundException, QueryNotFoundException, QueryMalformedException, + TableNotFoundException, ViewMalformedException, ViewNotFoundException, RemoteUnavailableException { + final Dataset<Row> mock = sparkSession.emptyDataFrame(); + final ExecuteStatementDto request = ExecuteStatementDto.builder() + .statement(QUERY_5_STATEMENT) + .build(); + + /* mock */ + when(credentialService.getDatabase(DATABASE_2_ID)) + .thenReturn(DATABASE_2_PRIVILEGED_DTO); + when(subsetService.findById(eq(DATABASE_2_PRIVILEGED_DTO), anyLong())) + .thenReturn(QUERY_2_DTO); + when(subsetService.getData(eq(DATABASE_2_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L))) + .thenReturn(mock); + when(schemaService.inspectView(eq(DATABASE_2_PRIVILEGED_DTO), anyString())) + .thenReturn(VIEW_4_DTO); + when(httpServletRequest.getMethod()) + .thenReturn("POST"); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + subsetEndpoint.create(DATABASE_2_ID, request, null, httpServletRequest, null, null, null); + }); } @Test @@ -687,9 +825,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { }); } - protected List<QueryDto> generic_list(Long databaseId, PrivilegedDatabaseDto database) throws NotAllowedException, - DatabaseUnavailableException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - MetadataServiceException { + protected List<QueryDto> generic_list(Long databaseId, PrivilegedDatabaseDto database, Principal principal) + throws NotAllowedException, DatabaseUnavailableException, QueryNotFoundException, DatabaseNotFoundException, + RemoteUnavailableException, MetadataServiceException { /* mock */ if (database != null) { @@ -702,22 +840,19 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { } /* test */ - final ResponseEntity<List<QueryDto>> response = subsetEndpoint.list(databaseId, null); + final ResponseEntity<List<QueryDto>> response = subsetEndpoint.list(databaseId, null, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); return response.getBody(); } - protected void generic_findById(Long subsetId, MediaType accept, Instant timestamp) throws UserNotFoundException, - DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, + protected void generic_findById(Long databaseId, Long subsetId, String accept, Instant timestamp, + Principal principal) throws UserNotFoundException, DatabaseUnavailableException, + StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, FormatNotAvailableException, - MetadataServiceException, TableNotFoundException, ViewMalformedException, SQLException { - - /* mock */ - when(mockHttpServletRequest.getHeader("Accept")) - .thenReturn(accept.toString()); + MetadataServiceException, TableNotFoundException, ViewMalformedException { /* test */ - final ResponseEntity<?> response = subsetEndpoint.findById(DATABASE_3_ID, subsetId, mockHttpServletRequest, timestamp); + final ResponseEntity<?> response = subsetEndpoint.findById(databaseId, subsetId, accept, timestamp, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); } 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 ed720ac930565c0c1f97b291058d4aa293ba0061..e3171892a0be41f816feb749990a70aafc252f3d 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 @@ -165,9 +165,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void statistic_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - TableMalformedException, DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException, - SQLException { + public void statistic_succeeds() throws DatabaseUnavailableException, TableNotFoundException, SQLException, + TableMalformedException, RemoteUnavailableException, MetadataServiceException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) @@ -454,10 +453,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .createTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.CREATED, response.getStatusCode()); } @@ -473,7 +472,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -495,7 +494,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -518,7 +517,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -545,7 +544,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -568,7 +567,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); /* test */ - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -590,7 +589,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -613,7 +612,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); /* test */ - tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -641,10 +640,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .updateTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -663,7 +662,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -688,7 +687,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -714,7 +713,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -743,7 +742,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -772,10 +771,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .updateTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -801,7 +800,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -830,10 +829,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .updateTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -858,10 +857,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -876,7 +875,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -897,7 +896,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -919,7 +918,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -944,7 +943,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -969,10 +968,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -994,7 +993,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1019,10 +1018,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -1269,10 +1268,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .importDataset(TABLE_8_PRIVILEGED_DTO, request); doNothing() .when(metadataServiceGateway) - .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID); + .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); /* test */ - final ResponseEntity<Void> response = tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + final ResponseEntity<Void> response = tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } @@ -1287,7 +1286,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_4_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_4_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1308,7 +1307,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1334,7 +1333,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1360,7 +1359,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1382,7 +1381,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1404,7 +1403,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); /* test */ - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -1425,7 +1424,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1447,7 +1446,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); /* test */ - tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_3_ID, TABLE_8_ID, request, USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -1468,7 +1467,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_USER_2_WRITE_ALL_ACCESS_DTO); /* test */ - tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, request, USER_2_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, request, USER_2_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -1489,7 +1488,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO); /* test */ - tableEndpoint.importDataset(DATABASE_1_ID, TABLE_2_ID, request, USER_2_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_1_ID, TABLE_2_ID, request, USER_2_PRINCIPAL, TOKEN_ACCESS_TOKEN); } @Test @@ -1510,7 +1509,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, request, USER_2_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, request, USER_2_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } @@ -1532,7 +1531,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - tableEndpoint.importDataset(DATABASE_1_ID, TABLE_2_ID, request, USER_2_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_1_ID, TABLE_2_ID, request, USER_2_PRINCIPAL, TOKEN_ACCESS_TOKEN); }); } 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 720e0652b3ee7f9dc0f30eb9ec014efe76275009..f65de0707eec016f502d66f45e8f52b5811f042f 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 @@ -31,8 +31,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @@ -45,6 +44,10 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { @Qualifier("restTemplate") private RestTemplate restTemplate; + @MockBean + @Qualifier("internalRestTemplate") + private RestTemplate internalRestTemplate; + @Autowired private MetadataServiceGateway metadataServiceGateway; @@ -66,7 +69,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Table", TABLE_1_INTERNAL_NAME); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .body(TABLE_1_DTO)); @@ -87,7 +90,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)); /* test */ @@ -101,7 +104,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.ServiceUnavailable.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)); /* test */ @@ -114,7 +117,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getTableById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .body(TABLE_1_DTO)); @@ -134,7 +137,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.add(customHeaders.get(j), ""); } /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .body(TABLE_1_DTO)); @@ -157,7 +160,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Table", TABLE_1_INTERNAL_NAME); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .build()); @@ -178,7 +181,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Port", "" + CONTAINER_1_PORT); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .body(DATABASE_1_PRIVILEGED_DTO)); @@ -193,7 +196,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class)); /* test */ @@ -207,7 +210,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class)); /* test */ @@ -220,7 +223,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getDatabaseById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -237,7 +240,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .build()); @@ -258,7 +261,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.add(customHeaders.get(j), ""); } /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .build()); @@ -276,7 +279,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .body(CONTAINER_1_DTO)); @@ -291,7 +294,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class)); /* test */ @@ -305,7 +308,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class)); /* test */ @@ -318,7 +321,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getContainerById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -338,7 +341,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.add(customHeaders.get(j), ""); } /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -356,7 +359,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ContainerDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) .build()); @@ -379,7 +382,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-View", VIEW_1_INTERNAL_NAME); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(ViewDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .body(VIEW_1_DTO)); @@ -394,7 +397,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class)); /* test */ @@ -408,7 +411,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class)); /* test */ @@ -421,7 +424,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getViewById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -441,7 +444,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.add(customHeaders.get(j), ""); } /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .build()); @@ -463,7 +466,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Database", DATABASE_1_INTERNALNAME); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .build()); @@ -478,7 +481,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.ok() .body(USER_1_DTO)); @@ -492,7 +495,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); /* test */ @@ -506,7 +509,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); /* test */ @@ -519,7 +522,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getUserById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -533,7 +536,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getUserById_emptyBody_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.ok() .build()); @@ -551,7 +554,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .body(USER_1_DTO)); @@ -568,7 +571,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); /* test */ @@ -582,7 +585,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class)); /* test */ @@ -595,7 +598,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getPrivilegedUserById_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -615,7 +618,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.add(customHeaders.get(j), ""); } /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .build()); @@ -633,7 +636,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) .thenReturn(ResponseEntity.ok() .headers(headers) .build()); @@ -648,7 +651,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getAccess_succeeds() throws RemoteUnavailableException, NotAllowedException, MetadataServiceException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) .thenReturn(ResponseEntity.ok() .body(DATABASE_1_USER_1_READ_ACCESS_DTO)); @@ -661,7 +664,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); /* test */ @@ -675,7 +678,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.Forbidden.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); /* test */ @@ -689,7 +692,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class)); /* test */ @@ -702,7 +705,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getAccess_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -716,7 +719,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getAccess_emptyBody_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) .thenReturn(ResponseEntity.ok() .build()); @@ -730,7 +733,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getIdentifiers_witSubset_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) .thenReturn(ResponseEntity.ok() .body(new IdentifierBriefDto[]{IDENTIFIER_1_BRIEF_DTO})); @@ -743,7 +746,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getIdentifiers_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) .thenReturn(ResponseEntity.ok() .body(new IdentifierBriefDto[]{IDENTIFIER_1_BRIEF_DTO})); @@ -757,7 +760,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class)); /* test */ @@ -771,7 +774,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) + .when(internalRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class)); /* test */ @@ -784,7 +787,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getIdentifiers_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -798,7 +801,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void getIdentifiers_emptyBody_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierBriefDto[].class))) .thenReturn(ResponseEntity.ok() .build()); @@ -809,15 +812,16 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void updateTableStatistics_succeeds() throws RemoteUnavailableException, MetadataServiceException, TableNotFoundException { + public void updateTableStatistics_succeeds() throws RemoteUnavailableException, MetadataServiceException, + TableNotFoundException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.accepted() .build()); /* test */ - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); + metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID, TOKEN_ACCESS_TOKEN); } @Test @@ -825,12 +829,12 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class)); + .when(internalRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ assertThrows(RemoteUnavailableException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); + metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID, TOKEN_ACCESS_TOKEN); }); } @@ -839,12 +843,12 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ doThrow(HttpClientErrorException.NotFound.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class)); + .when(internalRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ assertThrows(TableNotFoundException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); + metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID, TOKEN_ACCESS_TOKEN); }); } @@ -852,13 +856,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { public void updateTableStatistics_statusCode_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class))) + when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); /* test */ assertThrows(MetadataServiceException.class, () -> { - metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); + metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID, TOKEN_ACCESS_TOKEN); }); } 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 01bce16b08f84e7ad3901beb143ef0737d9ad571..e48f0c048da2dd6c83934566e6e5d9956838ba62 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 @@ -27,7 +27,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; @@ -131,7 +130,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* mock */ try { - subsetEndpoint.list(DATABASE_1_ID, null); + subsetEndpoint.list(DATABASE_1_ID, null, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } @@ -151,7 +150,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - subsetEndpoint.findById(DATABASE_1_ID, QUERY_1_ID, new MockHttpServletRequest(), null); + subsetEndpoint.findById(DATABASE_1_ID, QUERY_1_ID, "application/json", null, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } @@ -176,17 +175,17 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - tableEndpoint.insertRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleDto.builder().build(), USER_1_PRINCIPAL); + tableEndpoint.insertRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleDto.builder().build(), USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } catch (Exception e) { /* ignore */ } try { - tableEndpoint.updateRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleUpdateDto.builder().build(), USER_1_PRINCIPAL); + tableEndpoint.updateRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleUpdateDto.builder().build(), USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } catch (Exception e) { /* ignore */ } try { - tableEndpoint.deleteRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleDeleteDto.builder().build(), USER_1_PRINCIPAL); + tableEndpoint.deleteRawTuple(DATABASE_1_ID, TABLE_1_ID, TupleDeleteDto.builder().build(), USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } catch (Exception e) { /* ignore */ } @@ -201,7 +200,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, ImportDto.builder().build(), USER_1_PRINCIPAL); + tableEndpoint.importDataset(DATABASE_1_ID, TABLE_1_ID, ImportDto.builder().build(), USER_1_PRINCIPAL, TOKEN_ACCESS_TOKEN); } catch (Exception e) { /* ignore */ } 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 6a3851b445cf83b74eaccf1b6a3b86bf61ec03d8..158c6743a4e7bac049cae0211fe764030ab4a3f0 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 @@ -37,7 +37,7 @@ public class SubsetEndpointMvcTest extends AbstractUnitTest { private MockMvc mockMvc; @Test - public void findById_noAcceptHeader_succeeds() throws Exception { + public void findById_noAcceptHeader_fails() throws Exception { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -48,11 +48,11 @@ public class SubsetEndpointMvcTest extends AbstractUnitTest { /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_3_ID + "/subset/" + QUERY_5_ID)) .andDo(print()) - .andExpect(status().isOk()); + .andExpect(status().isBadRequest()); } @Test - public void findById_jsonAcceptHeader_succeeds() throws Exception { + public void findById_privateDataPublicSchema_jsonAcceptHeader_fails() throws Exception { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -64,6 +64,22 @@ public class SubsetEndpointMvcTest extends AbstractUnitTest { this.mockMvc.perform(get("/api/database/" + DATABASE_3_ID + "/subset/" + QUERY_5_ID) .accept(MediaType.APPLICATION_JSON)) .andDo(print()) + .andExpect(status().isForbidden()); + } + + @Test + public void findById_publicDataPublicSchema_jsonAcceptHeader_succeeds() throws Exception { + + /* mock */ + when(metadataServiceGateway.getDatabaseById(DATABASE_4_ID)) + .thenReturn(DATABASE_4_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_4_PRIVILEGED_DTO, QUERY_7_ID)) + .thenReturn(QUERY_5_DTO); + + /* test */ + this.mockMvc.perform(get("/api/database/" + DATABASE_4_ID + "/subset/" + QUERY_7_ID) + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) .andExpect(status().isOk()); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java index d5cf6dd22e3cbe341ebe612d246bb716ff5c9f6a..2a0ad624dbbb8399cf9d360148c96bd0524c8453 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java @@ -358,7 +358,6 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { assertEquals("not_in_metadata_db2", response.getInternalName()); assertEquals("not_in_metadata_db2", response.getName()); assertEquals(DATABASE_1_ID, response.getVdbid()); - assertEquals(DATABASE_1_ID, response.getDatabase().getId()); assertEquals(DATABASE_1_OWNER, response.getOwner().getId()); assertFalse(response.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); @@ -383,20 +382,18 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { assertEquals(DATABASE_1_ID, column3.getDatabaseId()); } - protected static void assertViewColumn(ViewColumnDto column, Long id, Long databaseId, String name, - String internalName, ColumnTypeDto type, Long size, Long d, - Boolean nullAllowed, String description) { - log.trace("assert column: {}", internalName); + protected static void assertViewColumn(ViewColumnDto column, ViewColumnDto other) { assertNotNull(column); - assertEquals(id, column.getId()); - assertEquals(databaseId, column.getDatabaseId()); - assertEquals(name, column.getName()); - assertEquals(internalName, column.getInternalName()); - assertEquals(type, column.getColumnType()); - assertEquals(size, column.getSize()); - assertEquals(d, column.getD()); - assertEquals(nullAllowed, column.getIsNullAllowed()); - assertEquals(description, column.getDescription()); + assertNotNull(other); + assertEquals(column.getId(), other.getId()); + assertEquals(column.getDatabaseId(), other.getDatabaseId()); + assertEquals(column.getName(), other.getName()); + assertEquals(column.getInternalName(), other.getInternalName()); + assertEquals(column.getColumnType(), other.getColumnType()); + assertEquals(column.getSize(), other.getSize()); + assertEquals(column.getD(), other.getD()); + assertEquals(column.getIsNullAllowed(), other.getIsNullAllowed()); + assertEquals(column.getDescription(), other.getDescription()); } protected static void assertColumn(ColumnDto column, Long id, Long tableId, Long databaseId, String name, @@ -407,8 +404,6 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { assertEquals(id, column.getId()); assertEquals(tableId, column.getTableId()); assertEquals(databaseId, column.getDatabaseId()); - assertNotNull(column.getTable()); - assertEquals(tableId, column.getTable().getId()); assertEquals(name, column.getName()); assertEquals(internalName, column.getInternalName()); assertEquals(type, column.getColumnType()); 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 5bfaa043d1ded11c26797b94d0ff2cf0d9e509ba..b5555611c666f60f0af6e2d8a122dc11ec3264dd 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 @@ -55,21 +55,7 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { public void create_succeeds() throws SQLException, ViewMalformedException { /* test */ - final ViewDto response = viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); - assertEquals(VIEW_1_NAME, response.getName()); - assertEquals(VIEW_1_INTERNAL_NAME, response.getInternalName()); - assertEquals(VIEW_1_QUERY, response.getQuery()); - assertNotNull(response.getQueryHash()); - assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); - final List<ViewColumnDto> columns = response.getColumns(); - assertEquals(VIEW_1_COLUMNS.size(), columns.size()); - ViewColumnDto ref = VIEW_1_COLUMNS_DTO.get(0); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(0), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDescription()); - ref = VIEW_1_COLUMNS_DTO.get(1); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(1), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDescription()); - ref = VIEW_1_COLUMNS_DTO.get(2); - SchemaServiceIntegrationTest.assertViewColumn(columns.get(2), null, ref.getDatabaseId(), ref.getName(), ref.getInternalName(), ref.getColumnType(), ref.getSize(), ref.getD(), ref.getIsNullAllowed(), ref.getDescription()); - + viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); } @Test @@ -81,7 +67,6 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { assertEquals("not_in_metadata_db2", view0.getName()); assertEquals("not_in_metadata_db2", view0.getInternalName()); assertEquals(DATABASE_1_ID, view0.getVdbid()); - assertEquals(DATABASE_1_ID, view0.getDatabase().getId()); assertEquals(DATABASE_1_OWNER, view0.getOwner().getId()); assertFalse(view0.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, view0.getIsPublic()); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java deleted file mode 100644 index 13ddfce8d3c171b79096d2e0d1d05948848a8c86..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package at.tuwien.utils; - -import at.tuwien.test.BaseTest; -import org.junit.jupiter.api.Test; - - -import static org.junit.jupiter.api.Assertions.*; - -public class UserUtilTest extends BaseTest { - - @Test - public void constructor_succeeds() { - - /* test */ - new UserUtil(); - } - - @Test - public void hasRole_succeeds() { - assertTrue(UserUtil.hasRole(USER_1_PRINCIPAL, "find-container")); - } - - @Test - public void hasRole_principalMissing_fails() { - assertFalse(UserUtil.hasRole(null, "find-container")); - } - - @Test - public void hasRole_roleMissing_fails() { - assertFalse(UserUtil.hasRole(USER_1_PRINCIPAL, null)); - } - - @Test - public void getId_succeeds() { - assertEquals(USER_1_ID, UserUtil.getId(USER_1_PRINCIPAL)); - } - - @Test - public void getId_principalMissing_fails() { - assertNull(UserUtil.getId(null)); - } - - @Test - public void getId_roleMissing_fails() { - assertNull(UserUtil.getId(USER_LOCAL_ADMIN_PRINCIPAL)); - } -} diff --git a/dbrepo-data-service/rest-service/src/test/resources/application.properties b/dbrepo-data-service/rest-service/src/test/resources/application.properties index 3094970e3f8a2cdaaa47107549d2762b517b63bd..a0bb7de2bbbdfb31d85a3980355112185e51ca98 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-data-service/rest-service/src/test/resources/application.properties @@ -1,5 +1,5 @@ # enable local spring profile -spring.profiles.active=local +spring.profiles.active=local,junit # disable discovery spring.cloud.discovery.enabled=false @@ -12,7 +12,7 @@ spring.cloud.config.enabled=false dbrepo.credentialCacheTimeout=3 # internal datasource -spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS FDA;NON_KEYWORDS=value +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS DBREPO;NON_KEYWORDS=value spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password diff --git a/dbrepo-data-service/rest-service/src/test/resources/init/weather_at.sql b/dbrepo-data-service/rest-service/src/test/resources/init/weather_at.sql new file mode 100644 index 0000000000000000000000000000000000000000..050ad3fb54db0e86b25f487423c8e648f2bd8e39 --- /dev/null +++ b/dbrepo-data-service/rest-service/src/test/resources/init/weather_at.sql @@ -0,0 +1,11 @@ +CREATE +DATABASE weather_at; +USE +weather_at; + +CREATE TABLE mfcc +( + location VARCHAR(255) PRIMARY KEY, + lat DOUBLE PRECISION NULL, + lng DOUBLE PRECISION NULL +) WITH SYSTEM VERSIONING COMMENT 'Hello mfcc'; diff --git a/dbrepo-data-service/services/pom.xml b/dbrepo-data-service/services/pom.xml index 180987ded0cb6336af854b2d610a5a103619a166..666cda76a43da22b1993729bf9df8c58ca4d75e9 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>services</artifactId> <name>dbrepo-data-service-services</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service-querystore</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> </dependency> </dependencies> diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index 4bdb9cb89f9d93d14c34bb318667882e299f0201..c511f2b511ff3cd66d52f63a55ca8ca73ce2a6c9 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -36,7 +36,7 @@ public class GatewayConfig { } @Bean - public RestTemplate restTemplate() { + public RestTemplate internalRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(metadataEndpoint)); restTemplate.getInterceptors() @@ -44,4 +44,9 @@ public class GatewayConfig { return restTemplate; } + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + } 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 8c86d26bf4d7eb66d496713e2f286fade575aee0..e2851071dad176ca44a9f2d0952a0392101ad2eb 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 @@ -118,11 +118,13 @@ public interface MetadataServiceGateway { /** * Update the table statistics in the metadata service. * - * @param databaseId The database id. - * @param tableId The table id. + * @param databaseId The database id. + * @param tableId The table id. + * @param authorization The authorization header. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws TableNotFoundException The table was not found. * @throws MetadataServiceException The remote service returned invalid data. */ - void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, MetadataServiceException, RemoteUnavailableException; + void updateTableStatistics(Long databaseId, Long tableId, String authorization) throws TableNotFoundException, + MetadataServiceException, RemoteUnavailableException; } 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 8e63bbb7b6aac5eee92a87c3d1221ff07b00c7e5..7d834992cc73b689bc990b6639061ae1ca2ddb71 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,6 +1,7 @@ package at.tuwien.gateway.impl; import at.tuwien.api.container.ContainerDto; +import at.tuwien.api.container.image.ImageDto; import at.tuwien.api.container.internal.PrivilegedContainerDto; import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.ViewDto; @@ -11,21 +12,21 @@ import at.tuwien.api.database.table.internal.PrivilegedTableDto; import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.user.UserDto; import at.tuwien.api.user.internal.PrivilegedUserDto; +import at.tuwien.config.GatewayConfig; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.mapper.MetadataMapper; import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.*; 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; +import org.springframework.web.util.DefaultUriBuilderFactory; import java.time.Instant; import java.util.List; @@ -36,11 +37,17 @@ import java.util.UUID; public class MetadataServiceGatewayImpl implements MetadataServiceGateway { private final RestTemplate restTemplate; + private final RestTemplate internalRestTemplate; + private final GatewayConfig gatewayConfig; private final MetadataMapper metadataMapper; @Autowired - public MetadataServiceGatewayImpl(RestTemplate restTemplate, MetadataMapper metadataMapper) { + public MetadataServiceGatewayImpl(@Qualifier("internalRestTemplate") RestTemplate internalRestTemplate, + RestTemplate restTemplate, GatewayConfig gatewayConfig, + MetadataMapper metadataMapper) { this.restTemplate = restTemplate; + this.internalRestTemplate = internalRestTemplate; + this.gatewayConfig = gatewayConfig; this.metadataMapper = metadataMapper; } @@ -48,8 +55,10 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { public PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, ContainerNotFoundException, MetadataServiceException { final ResponseEntity<ContainerDto> response; + final String url = "/api/container/" + containerId; + log.debug("get privileged container info from metadata service: {}", url); try { - response = restTemplate.exchange("/api/container/" + containerId, HttpMethod.GET, HttpEntity.EMPTY, + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ContainerDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find container with id {}: {}", containerId, e.getMessage()); @@ -85,10 +94,9 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { MetadataServiceException { final ResponseEntity<PrivilegedDatabaseDto> response; final String url = "/api/database/" + id; - log.debug("find privileged database from url: {}", url); + log.debug("get privileged database info from metadata service: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, - PrivilegedDatabaseDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, PrivilegedDatabaseDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find database with id {}: {}", id, e.getMessage()); throw new RemoteUnavailableException("Failed to find database: " + e.getMessage(), e); @@ -125,9 +133,9 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { RemoteUnavailableException, MetadataServiceException { final ResponseEntity<TableDto> response; final String url = "/api/database/" + databaseId + "/table/" + id; - log.debug("find privileged table from url: {}", url); + log.debug("get privileged table info from metadata service: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find table with id {}: {}", id, e.getMessage()); throw new RemoteUnavailableException("Failed to find table: " + e.getMessage(), e); @@ -167,9 +175,9 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { ViewNotFoundException, MetadataServiceException { final ResponseEntity<ViewDto> response; final String url = "/api/database/" + databaseId + "/view/" + id; - log.debug("find privileged view from url: {}", url); + log.debug("get privileged view info from metadata service: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ViewDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ViewDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find view with id {}: {}", id, e.getMessage()); throw new RemoteUnavailableException("Failed to find view: " + e.getMessage(), e); @@ -193,12 +201,18 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { throw new MetadataServiceException("Failed to find view with id " + id + ": body is empty"); } final PrivilegedViewDto view = metadataMapper.viewDtoToPrivilegedViewDto(response.getBody()); - view.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Type").get(0)); - view.getDatabase().getContainer().setHost(response.getHeaders().get("X-Host").get(0)); - view.getDatabase().getContainer().setPort(Integer.parseInt(response.getHeaders().get("X-Port").get(0))); - view.getDatabase().getContainer().setUsername(response.getHeaders().get("X-Username").get(0)); - view.getDatabase().getContainer().setPassword(response.getHeaders().get("X-Password").get(0)); - view.getDatabase().setInternalName(response.getHeaders().get("X-Database").get(0)); + view.setDatabase(PrivilegedDatabaseDto.builder() + .internalName(response.getHeaders().get("X-Database").get(0)) + .container(PrivilegedContainerDto.builder() + .host(response.getHeaders().get("X-Host").get(0)) + .port(Integer.parseInt(response.getHeaders().get("X-Port").get(0))) + .username(response.getHeaders().get("X-Username").get(0)) + .password(response.getHeaders().get("X-Password").get(0)) + .image(ImageDto.builder() + .jdbcMethod(response.getHeaders().get("X-Type").get(0)) + .build()) + .build()) + .build()); view.setInternalName(response.getHeaders().get("X-View").get(0)); view.setLastRetrieved(Instant.now()); return view; @@ -208,8 +222,10 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { public UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException { final ResponseEntity<UserDto> response; + final String url = "/api/user/" + userId; + log.debug("get user info from metadata service: {}", url); try { - response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find user with id {}: {}", userId, e.getMessage()); throw new RemoteUnavailableException("Failed to find user: " + e.getMessage(), e); @@ -232,8 +248,10 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { public PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException { final ResponseEntity<UserDto> response; + final String url = "/api/user/" + userId; + log.debug("get privileged user info from metadata service: {}", url); try { - response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find user with id {}: {}", userId, e.getMessage()); throw new RemoteUnavailableException("Failed to find user: " + e.getMessage(), e); @@ -267,8 +285,10 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { public DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, NotAllowedException, MetadataServiceException { final ResponseEntity<DatabaseAccessDto> response; + final String url = "/api/database/" + databaseId + "/access/" + userId; + log.debug("get database access from metadata service: {}", url); try { - response = restTemplate.exchange("/api/database/" + databaseId + "/access/" + userId, HttpMethod.GET, HttpEntity.EMPTY, DatabaseAccessDto.class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, DatabaseAccessDto.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find database access for user with id {}: {}", userId, e.getMessage()); throw new RemoteUnavailableException("Failed to find database access: " + e.getMessage(), e); @@ -292,9 +312,9 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { RemoteUnavailableException, DatabaseNotFoundException { final ResponseEntity<IdentifierBriefDto[]> response; final String url = "/api/identifier?dbid=" + databaseId + (subsetId != null ? ("&qid=" + subsetId) : ""); - log.trace("mapped url: {}", url); + log.debug("get identifiers from metadata service: {}", url); try { - response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, IdentifierBriefDto[].class); + response = internalRestTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, IdentifierBriefDto[].class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to find identifiers for database with id {} and subset with id {}: {}", databaseId, subsetId, e.getMessage()); throw new RemoteUnavailableException("Failed to find identifiers: " + e.getMessage(), e); @@ -314,13 +334,16 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } @Override - public void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, MetadataServiceException, - RemoteUnavailableException { + public void updateTableStatistics(Long databaseId, Long tableId, String authorization) throws TableNotFoundException, + MetadataServiceException, RemoteUnavailableException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table/" + tableId + "/statistic"; - log.trace("mapped url: {}", url); + log.debug("update table statistics in metadata service: {}", url); + internalRestTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayConfig.getMetadataEndpoint())); + final HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", authorization); try { - response = restTemplate.exchange(url, HttpMethod.PUT, HttpEntity.EMPTY, Void.class); + response = internalRestTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(null, headers), Void.class); } catch (ResourceAccessException | HttpServerErrorException e) { log.error("Failed to update table statistic for table with id {}: {}", tableId, e.getMessage()); throw new RemoteUnavailableException("Failed to update table statistic: " + e.getMessage(), e); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java index b89e6b9c0feb3a282c38afbf39f07ef2d85fb546..5b96a5934b83e2c4636590f7515f70c04aef5826 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 @@ -33,7 +33,10 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.sql.*; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -87,14 +90,13 @@ public interface DataMapper { * @param database The database. * @param resultSet The inspected schema. * @return The database containing the updated view/table. - * @throws SQLException + * @throws SQLException If the result set does not contain the requested parameter. */ default ViewDto schemaResultSetToView(DatabaseDto database, ResultSet resultSet) throws SQLException { return ViewDto.builder() .name(resultSet.getString(1)) .internalName(resultSet.getString(1)) .vdbid(database.getId()) - .database(database) .isInitialView(false) .isPublic(database.getIsPublic()) .query(resultSet.getString(9)) @@ -124,7 +126,7 @@ public interface DataMapper { return statistic; } - default TableDto resultSetToTable(ResultSet resultSet, TableDto table, QueryConfig queryConfig) throws SQLException { + default TableDto resultSetToTable(ResultSet resultSet, TableDto table) throws SQLException { final ColumnDto column = ColumnDto.builder() .ordinalPosition(resultSet.getInt(1) - 1) /* start at zero */ .isNullAllowed(resultSet.getString(3).equals("YES")) @@ -132,7 +134,6 @@ public interface DataMapper { .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) .name(resultSet.getString(10)) .internalName(resultSet.getString(10)) - .table(table) .tableId(table.getId()) .databaseId(table.getTdbid()) .description(resultSet.getString(11)) @@ -181,7 +182,7 @@ public interface DataMapper { .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) .name(resultSet.getString(10)) .internalName(resultSet.getString(10)) - .databaseId(view.getDatabase().getId()) + .databaseId(view.getVdbid()) .build(); /* fix boolean and set size for others */ if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { @@ -193,7 +194,7 @@ public interface DataMapper { } view.getColumns() .add(column); - log.trace("parsed view {}.{} column: {}", view.getDatabase().getInternalName(), view.getInternalName(), column.getInternalName()); + log.trace("parsed view column: {}.{}", view.getInternalName(), column.getInternalName()); return view; } @@ -320,7 +321,7 @@ public interface DataMapper { if (!resultSet.next()) { throw new TableNotFoundException("Failed to find table in the information schema"); } - final TableDto table = TableDto.builder() + return TableDto.builder() .name(resultSet.getString(1)) .internalName(resultSet.getString(1)) .isVersioned(resultSet.getString(2).equals("SYSTEM VERSIONED")) @@ -343,7 +344,6 @@ public interface DataMapper { .build()) .isPublic(database.getIsPublic()) .build(); - return table; } default void prepareStatementWithColumnTypeObject(PreparedStatement ps, ColumnTypeDto columnType, int idx, Object value) throws SQLException { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java index dc073e855d7505d3bdf9d269040af58040d07174..e2b0c984e0f53c68bf9d384a301ab62ad67bbff7 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java @@ -5,7 +5,6 @@ import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; -import at.tuwien.config.QueryConfig; import at.tuwien.exception.TableNotFoundException; import at.tuwien.exception.ViewNotFoundException; import at.tuwien.mapper.DataMapper; @@ -28,15 +27,12 @@ import java.util.LinkedList; public class SchemaServiceMariaDbImpl extends HibernateConnector implements SchemaService { private final DataMapper dataMapper; - private final QueryConfig queryConfig; private final MariaDbMapper mariaDbMapper; private final MetadataMapper metadataMapper; @Autowired - public SchemaServiceMariaDbImpl(DataMapper dataMapper, QueryConfig queryConfig, MariaDbMapper mariaDbMapper, - MetadataMapper metadataMapper) { + public SchemaServiceMariaDbImpl(DataMapper dataMapper, MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper) { this.dataMapper = dataMapper; - this.queryConfig = queryConfig; this.mariaDbMapper = mariaDbMapper; this.metadataMapper = metadataMapper; } @@ -65,7 +61,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche final ResultSet resultSet2 = statement2.executeQuery(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); while (resultSet2.next()) { - table = dataMapper.resultSetToTable(resultSet2, table, queryConfig); + table = dataMapper.resultSetToTable(resultSet2, table); } /* obtain check constraints metadata */ start = System.currentTimeMillis(); @@ -97,10 +93,8 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche final TableDto tmpTable = table; uk.getColumns() .forEach(column -> { - column.setTable(tmpTable); column.setTableId(tmpTable.getId()); column.setDatabaseId(database.getId()); - column.setIsPublic(database.getIsPublic()); }); } } @@ -109,7 +103,6 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche final TableDto tmpTable = table; tmpTable.getColumns() .forEach(column -> { - column.setTable(tmpTable); column.setTableId(tmpTable.getId()); column.setDatabaseId(database.getId()); }); @@ -139,7 +132,6 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche throw new ViewNotFoundException("Failed to find view in the information schema"); } ViewDto view = dataMapper.schemaResultSetToView(database, resultSet1); - view.setDatabase(database); view.setVdbid(database.getId()); view.setOwner(database.getOwner()); /* obtain view columns */ @@ -154,7 +146,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche .columns(new LinkedList<>()) .build(); while (resultSet2.next()) { - tmp = dataMapper.resultSetToTable(resultSet2, tmp, queryConfig); + tmp = dataMapper.resultSetToTable(resultSet2, tmp); } view.setColumns(tmp.getColumns() .stream() 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 4d688393cb8b0aa3054bea77c9ad0cc534aa5e65..fb244bb30113ab90f4f2209bf4e80b5d11cd9185 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 @@ -90,13 +90,14 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public Dataset<Row> getData(PrivilegedDatabaseDto database, QueryDto subset, Long page, Long size) throws ViewMalformedException, SQLException, QueryMalformedException, TableNotFoundException { - if (!viewService.existsByName(database, metadataMapper.queryDtoToViewName(subset))) { - log.warn("Missing internal view {} for subset with id {}: create it from subset query", metadataMapper.queryDtoToViewName(subset), subset.getId()); + final String viewName = metadataMapper.queryDtoToViewName(subset); + if (!viewService.existsByName(database, viewName)) { + log.warn("Missing internal view {} for subset with id {}: create it from subset query", viewName, subset.getId()); viewService.create(database, subset); } else { - log.debug("internal view {} for subset with id {} exists", metadataMapper.queryDtoToViewName(subset), subset.getId()); + log.debug("internal view {}.{} for subset with id {} exists", database.getInternalName(), viewName, subset.getId()); } - return tableService.getData(database, metadataMapper.queryDtoToViewName(subset), subset.getExecution(), page, size, null, null); + return tableService.getData(database, viewName, subset.getExecution(), page, size, null, null); } @Override 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 c8da7fd688702c0c69091c9ee27fd972da73b98a..c34f057e0129bd1c65277648adf3b5985952235c 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 @@ -170,7 +170,11 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table final long start = System.currentTimeMillis(); final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tableNameToUpdateTableRawQuery(table.getInternalName())); log.trace("prepare with arg 1={}", data.getDescription()); - statement.setString(1, data.getDescription()); + if (data.getDescription() == null) { + statement.setString(1, ""); + } else { + statement.setString(1, data.getDescription()); + } statement.executeUpdate(); log.debug("executed statement in {} ms", System.currentTimeMillis() - start); connection.commit(); 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 989fe4e1a1de03502616d02e74e5aba99e6544af..d85bdc53ac235a3a95bb8b3543bddcfdd143dc6d 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 @@ -141,7 +141,6 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe .identifiers(new LinkedList<>()) .isInitialView(false) .vdbid(database.getId()) - .database(metadataMapper.privilegedDatabaseDtoToDatabaseDto(database)) .columns(new LinkedList<>()) .build(); try { diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 92f2b1721e33cf68c00a62169dc0128606bea4b7..c9ce89d1be71f4791c5e55dbb7c24f46e979355a 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS `mdb_users` email character varying(255) NOT NULL, orcid character varying(255), affiliation character varying(255), + is_internal BOOLEAN NOT NULL DEFAULT FALSE, mariadb_password character varying(255) NOT NULL, theme character varying(255) NOT NULL default ('light'), language character varying(3) NOT NULL default ('en'), diff --git a/dbrepo-metadata-db/migration/schema_1.5.0-to-1.6.0.sql b/dbrepo-metadata-db/migration/schema_1.5.0-to-1.6.0.sql index c04efaa1bbf7a9987ab845381a775fb7fd7c1940..be4e88a9c1489eb1554d62d44253c225ea7d427d 100644 --- a/dbrepo-metadata-db/migration/schema_1.5.0-to-1.6.0.sql +++ b/dbrepo-metadata-db/migration/schema_1.5.0-to-1.6.0.sql @@ -15,12 +15,16 @@ ALTER TABLE `mdb_tables` DROP SYSTEM VERSIONING; ALTER TABLE `mdb_tables` ADD COLUMN `is_schema_public` BOOLEAN NOT NULL DEFAULT TRUE; +ALTER TABLE `mdb_tables` + ADD COLUMN `is_public` BOOLEAN NOT NULL DEFAULT TRUE; ALTER TABLE `mdb_tables` DROP FOREIGN KEY `mdb_tables_ibfk_2`; ALTER TABLE `mdb_tables` DROP COLUMN `created_by`; -UPDATE `mdb_tables` -SET `is_schema_public` = `is_public`; +UPDATE `mdb_tables` t +SET `is_schema_public` = (SELECT d.is_public FROM mdb_databases d where d.id = t.tDBID); +UPDATE `mdb_tables` t +SET `is_schema_public` = (SELECT d.is_public FROM mdb_databases d where d.id = t.tDBID); ALTER TABLE `mdb_tables` ADD SYSTEM VERSIONING; diff --git a/dbrepo-metadata-service/api/pom.xml b/dbrepo-metadata-service/api/pom.xml index 8e77c818a4f1c0b353a854636b1f437edf4d5546..9baf18ff69870ee00658f67dc5fa5e43bab49581 100644 --- a/dbrepo-metadata-service/api/pom.xml +++ b/dbrepo-metadata-service/api/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-api</artifactId> <name>dbrepo-metadata-service-api</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> <scope>compile</scope> </dependency> </dependencies> diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java index 7324094f4c373916d7026d7edf80a50a23c976f6..5c5bf22005be92dbd172bfa4abd580dd298d6d5c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/ExportResourceDto.java @@ -7,6 +7,7 @@ import org.springframework.core.io.InputStreamResource; @Setter @ToString @Builder +@EqualsAndHashCode @AllArgsConstructor @NoArgsConstructor public class ExportResourceDto { diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java index ed521fccdf83f9c9ffcbdb69081624c18c863609..03aeb19ab41e375822af6741e61b3161d67a7591 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ChannelDetailsDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java index 9973c875e83cf24f69100ea6c52bd28a260d842a..ad82492d7d4d867c4c706bfbc1f1549e9fafcd95 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ConsumerDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java index 47adfb26e44fafff8e1f64bde9d72fb1f584c8e2..dffe2c1e0e300fb631d7af34a09e605e1064a462 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateExchangeDto.java @@ -1,16 +1,15 @@ package at.tuwien.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java index fea40fd7ccbbc4d1831593bb10fefa06528e7057..372ce8219b0ee2ac63308c9f8028361d8471cb10 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateUserDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java index be72924306a6eec019296808e5e11845a605c0a8..b27ea597c20a670df8897834b28bc62fcb95c0f7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/CreateVirtualHostDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java index 6a6aceef067084ac9fbe6e92f2175d15ecac8011..403a04f00b4d437db1746cca1977989e61a85dc8 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/ExchangeDto.java @@ -1,16 +1,15 @@ package at.tuwien.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java index 6ed572f96246ec8c078d925602f0aefde871a3a9..054548dbf06e683bcd787109afbff0359b59ca65 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantExchangePermissionsDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java index a00578529ce4b1617382757406989fad2d4d3a73..7e84edb80eb21faafbc4eb0ca87f4c5aa65464e4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/GrantVirtualHostPermissionsDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java index 2bfcb7efe64b78341ff1b32e9b0fb47f954d5dff..8a266043a1a63f216d2ca0a378d69f11458e6555 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueBriefDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.amqp; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java index 27ad5ba2878ff7f59f59fb5b2cb67239361c9da9..acc2091d41a158b07c7b23679be7e7ac1c385fc5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/QueueDto.java @@ -1,15 +1,15 @@ package at.tuwien.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java index 57fb360e64c377063ff982c7b75d6476c70b5ca5..bdd806f71e1312c05d27f034704297fa7c2bd885 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/TopicPermissionDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java index f932dfcf999f15761c13a8de0ed3c45d3bb216e1..a786456efd0945d480ace653457f3e8a284ab78c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/UserDetailsDto.java @@ -2,14 +2,14 @@ package at.tuwien.api.amqp; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java index 1cc1bd7f88e47fa14fe632e7129fbf70bcfcb4ce..0602c418da993c7bea9e2e557203128c9772fc8c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/amqp/VirtualHostPermissionDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java index fd76994630fac1b0ebf1c24002aed5f51f823405..0beb8a379491869edef613a594616beb21d1da83 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java @@ -1,11 +1,10 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.List; @@ -13,6 +12,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CredentialDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CredentialDto.java index 591b73e8067ed8f722a1102f7216c04cc3a328a2..a9f95ad04d9c5e2ca8c953dc5169f5f0d9250bb0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CredentialDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/CredentialDto.java @@ -1,15 +1,15 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java index c05f053c3b1de0d0758074161a73555069b25ad4..93d562ca77a81caf86f93a9ec6e96184f706d7ae 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java @@ -1,9 +1,8 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.List; @@ -11,6 +10,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java index 9b8ad90ea55d8d4aba75e637e4f9906fcc7e86d9..01c0a2d0348a2facf9009d9b865fd52338f2bab9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java @@ -11,6 +11,7 @@ import java.io.Serializable; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/LoginRequestDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/LoginRequestDto.java index 5d0de083d9a6e6612301163033e1b043c6a94f78..809de9881bc424fefe1da8937df03217facb1456 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/LoginRequestDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/LoginRequestDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java index bd4bcd27370c1c392efba5f413aaa56a93c58293..b759aff16843ef5cf8cc13466af20c1383599996 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RefreshTokenRequestDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RefreshTokenRequestDto.java index c774a602805d7b81e15aee1783fda3bad42eb8a9..05b8dfd3b5f51007011ea2f2f0d87e34181aeae4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RefreshTokenRequestDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/RefreshTokenRequestDto.java @@ -9,6 +9,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java index 3cd30bc60fca15117f1173585ba5245d362d9208..c9110e041aaf1187675c58d2365cf63e1f1f2003 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java @@ -1,17 +1,17 @@ package at.tuwien.api.auth; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/TokenIntrospectDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/TokenIntrospectDto.java index a1756e0c9090eb64192be72f9f3b58e6d1efe954..8a2fa624b5794a36304949c3269ac3958beeaee1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/TokenIntrospectDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/TokenIntrospectDto.java @@ -2,14 +2,14 @@ package at.tuwien.api.auth; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java index 4038a39dc608db197ca0572882cca1218b4f6c32..9b1f8fcd4791d018970cb8559b5a7dcd1b1d7210 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java @@ -14,6 +14,7 @@ import java.time.Instant; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java index 312dcf998417f13c6d552dcb25d843516f799f1e..a4215c03928529186468081dfa054d6fd434f820 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/DataTypeDto.java @@ -10,6 +10,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java index 38adbd6f0d6592a0e802d2bf33147916bbd9f139..880db11fbd9818ed432f8dab7a910c48a51bf72e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java @@ -10,6 +10,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java index ea47c51e477e45359598076478fdce87b6c3ddc3..3baa76171b1ad00ab575a0fafa403c675e16f640 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/ImageDto.java @@ -12,6 +12,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java index a954bf4a61d52a1d4ee3063cf7187f8865969554..96113b5347e6fcd8d99878154686927da9c978ac 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/image/OperatorDto.java @@ -10,12 +10,15 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString public class OperatorDto { + private Long id; + @NotBlank @JsonProperty("display_name") @Schema(example = "XOR") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java index 8c51a0442aff61f4dbea7ae3302c3dcd8503a1fb..4a689a69ce93dead9cbb6bd27916326a986f22f1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/CrossrefDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java index 99a28ba5f2edb22e723362c466a6e724d551455e..b493cf89ff6ea61df68ef919c6a380b9a81769d2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/form/CrossrefLiteralFormDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java index d37f005d058265859f22e18b1f588f0c1127d9db..7bdaf0f93117c31dd91017f0e3fcda885060cd54 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefLabelDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java index 4073032f251b6c3ce90765ed0ce2a9b779cf4328..a70c161d83752cc338c0e0ccf416cc84a8ee8c8b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/crossref/label/CrossrefPrefLabelDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java index 7abc667741cc8ae31f3e0a7dd3e4ef66e8b78ccd..7e929eb74843d7ad5589652c269f59d8bd7db498 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseAccessDto.java @@ -2,21 +2,17 @@ package at.tuwien.api.database; import at.tuwien.api.user.UserBriefDto; -import at.tuwien.api.user.UserDto; -import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -25,12 +21,10 @@ public class DatabaseAccessDto { @NotNull @JsonIgnore - @ToString.Exclude private UUID huserid; @NotNull @JsonIgnore - @ToString.Exclude private Long hdbid; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java index e8456c42ef8d0dc6a464a43be64c940faa46c792..46072e83dc14af22d09923d3e9462a53506aa4f8 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java @@ -1,9 +1,7 @@ package at.tuwien.api.database; import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.identifier.IdentifierDto; 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; @@ -11,12 +9,13 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.List; +import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -43,14 +42,18 @@ public class DatabaseBriefDto { @Schema(example = "true") private Boolean isPublic; + @NotNull + @JsonProperty("is_schema_public") + @Schema(example = "true") + private Boolean isSchemaPublic; + private List<IdentifierBriefDto> identifiers; - @ToString.Exclude @NotNull private UserBriefDto contact; @NotNull @JsonProperty("owner_id") - private UserBriefDto ownerId; + private UUID ownerId; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseCreateDto.java index a20d9456bbd33addde563579ee03e9f7d17c6f73..f87673764ea55479e86ede7e3f2b70c94cd16b9a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseCreateDto.java @@ -10,6 +10,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java index 3343f23b68597b89d1fcd1af177191365ce20d1c..5fc253c4335044a1eaabbb43d02f7ae07510178b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java @@ -4,7 +4,6 @@ import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.identifier.IdentifierBriefDto; 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; @@ -12,12 +11,12 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -62,7 +61,6 @@ public class DatabaseDto { @Schema(example = "true") private Boolean isSchemaPublic; - @ToString.Exclude @NotNull private ContainerBriefDto container; @@ -72,11 +70,9 @@ public class DatabaseDto { private List<IdentifierBriefDto> subsets; - @ToString.Exclude @NotNull private UserBriefDto contact; - @ToString.Exclude @NotNull private UserBriefDto owner; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java index 627714f6cb358d1d7d53285f1646d565378553fd..5160ae76bfc3b9fc6445a33ff9c1bb277f9bc4dd 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyImageDto.java @@ -6,6 +6,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java index f5a9aa0961a5e9bb99862354e723701ba1b5ba74..e641deade282e838c478b87f249e9b26676c4972 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseModifyVisibilityDto.java @@ -2,14 +2,14 @@ package at.tuwien.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java index 75a517f4c19ace60ab23002b64fe5b3e14e64345..5a8e6beb1086a996aa77f47ff4f1530b62af00df 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseTransferDto.java @@ -1,8 +1,7 @@ package at.tuwien.api.database; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.UUID; @@ -10,6 +9,7 @@ import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java index 20fdf01de167eb9ec8c7b95ab5be7622f5eb51ff..a6384b3487bf1df7d320c2befa303ad59613d5f1 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LicenseDto.java @@ -1,15 +1,15 @@ package at.tuwien.api.database; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java index 7c4a9a72472e8b36cfe3964262c75c77ef916e10..65f5120d9b7cc78442bd071a6b02cbf70f534a41 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/LoadFileDto.java @@ -9,6 +9,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/SubjectModifyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/SubjectModifyDto.java index 984f37b790264a2e048d32b8d8b210d5550b4936..a82f6669ed62eac5402e0141d2bf414d01dbc462 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/SubjectModifyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/SubjectModifyDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.database; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/UpdateDatabaseAccessDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/UpdateDatabaseAccessDto.java index 8a83c998d267e1c3b64300c8e5cbf115d83f3979..32084c865feafc27fd1ae0a1a534229b347d3538 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/UpdateDatabaseAccessDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/UpdateDatabaseAccessDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java index e29bfbc109b13b9671b66e94d86d104e2fa2ad23..9b7c9fca89472a956b5d142e69c498c616fce81a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java @@ -1,7 +1,5 @@ package at.tuwien.api.database; -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 jakarta.validation.constraints.NotBlank; @@ -9,12 +7,12 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java index 613f9c5e71e54bdc09a8c78752d7a40f0eb0eb88..4005433afedbd5440b939d97bcd874f570a56c29 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java @@ -1,8 +1,6 @@ package at.tuwien.api.database; import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.concepts.ConceptDto; -import at.tuwien.api.database.table.columns.concepts.UnitDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -14,6 +12,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -29,7 +28,7 @@ public class ViewColumnDto { @NotNull @Schema(example = "0") - @JsonProperty("ordinal_position") + @JsonProperty("ord") private Integer ordinalPosition; @NotBlank @@ -55,7 +54,7 @@ public class ViewColumnDto { private Long length; @NotNull - @JsonProperty("column_type") + @JsonProperty("type") @Schema(example = "string") private ColumnTypeDto columnType; @@ -65,19 +64,10 @@ public class ViewColumnDto { @Schema(example = "0") private Long d; - private ConceptDto concept; - - private UnitDto unit; - @Size(max = 2048) @Schema(example = "Column comment") private String description; - @NotNull - @JsonProperty("is_public") - @Schema(example = "true") - private Boolean isPublic; - @NotNull @JsonProperty("is_null_allowed") @Schema(example = "false") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java index e63e6933d5da3e7270cc3145cc613800241db382..142a751ec4cc8eaceee7a9402af2c711d1acaa19 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java @@ -2,16 +2,16 @@ package at.tuwien.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Size; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java index 294bd04bd4ef873ac08cab943d0726f6ba9efaeb..d1ee156e9b95c09a9dd31c1ddf01926818f75879 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -2,7 +2,6 @@ package at.tuwien.api.database; import at.tuwien.api.identifier.IdentifierDto; 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; @@ -10,12 +9,12 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -29,10 +28,6 @@ public class ViewDto { @JsonProperty("database_id") private Long vdbid; - @NotNull - @ToString.Exclude - private DatabaseDto database; - @NotBlank @Schema(example = "Air Quality") private String name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedDatabaseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedDatabaseDto.java index 3317d40aeebe1dfe1e320ef8c77a6a91af8f7e4c..2335ea39baf1a2e8f1461b56c844409f8e21b207 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedDatabaseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedDatabaseDto.java @@ -64,7 +64,6 @@ public class PrivilegedDatabaseDto extends PrivilegedObjectDto { @Schema(example = "true") private Boolean isSchemaPublic; - @ToString.Exclude @NotNull private PrivilegedContainerDto container; @@ -74,11 +73,9 @@ public class PrivilegedDatabaseDto extends PrivilegedObjectDto { private List<IdentifierDto> subsets; - @ToString.Exclude @NotNull private UserBriefDto contact; - @ToString.Exclude @NotNull private UserBriefDto owner; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java index 87a8805374a1e89e406dc8898394107eec5f9a95..bda575f45d05f21a29a7be3d9da6cdfe1511d855 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java @@ -31,7 +31,6 @@ public class PrivilegedViewDto extends PrivilegedObjectDto { private Long vdbid; @NotNull - @ToString.Exclude private PrivilegedDatabaseDto database; @NotBlank diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java index 1b2b1e03865f982d79d1a226990d6bd45bd07d10..36a13b348770945035292c8bbe32722688f8eea9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ExportDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java index a50c2d1bdf3e0cce964669dfe6bf779581c2b2b5..39cb6683a1cb2d5250054b8dd555bffbad929fad 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/ImportDto.java @@ -2,15 +2,15 @@ package at.tuwien.api.database.query; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java index 28f8b61a52cd63df6ad0a750cf9dad28ee04dba8..90a1af28bcf14d64d51eca1db1cc6b46760079fb 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java @@ -17,6 +17,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java index b26a8c3c4ef8dbd4144f373d8d5211f6f4b3ae5d..cd1659e73c6a1e0a13e220e4a83aaaf5b5aacc2f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java @@ -16,6 +16,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java index a8098191866149b699dc80f9d59ca49f0ed8e294..5bc3ac2054452f007c256917c8eaa6a3288f1a1a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryPersistDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java index 19fd6ffbaf7827b60f63f1a08bd9103363a40e26..876dd5dfdd3c3f6a1e199138dfa7a3bfadc6292f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SaveStatementDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.database.query; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java index 615948486cd07626d9701b03df99852df4cebb9c..29531012f1f2912cc7d7f0c326661cee868ec72d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java @@ -1,22 +1,18 @@ package at.tuwien.api.database.table; -import at.tuwien.api.database.table.columns.ColumnBriefDto; -import at.tuwien.api.user.UserBriefDto; -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.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.util.List; import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateDto.java index 602eef4e5dcd6ad6155df627afdea411ce1bc73e..7c3defcc0b69dc47e20c4e9aa9931fdfad1143b0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateDto.java @@ -4,11 +4,10 @@ import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Size; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.List; @@ -16,6 +15,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java index efc3842b2908a514d20ab5af5580c97afc6a163e..ec221ae5f0ac5f1e9063a1cfbfcbcc2813f6ff60 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableCreateRawQuery.java @@ -8,6 +8,7 @@ import java.sql.PreparedStatement; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java index 2370f45429c10e01b5de09ea3a2a8dd278e2c729..67087d438daedf60cd0236a8f5427310b06464e4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java @@ -4,7 +4,6 @@ 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.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -13,17 +12,16 @@ import jakarta.validation.constraints.Size; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class TableDto { @NotNull @@ -31,7 +29,6 @@ public class TableDto { @NotNull @JsonProperty("database_id") - @EqualsAndHashCode.Include private Long tdbid; @NotBlank @@ -41,7 +38,6 @@ public class TableDto { @NotBlank @JsonProperty("internal_name") @Schema(example = "air_quality") - @EqualsAndHashCode.Include private String internalName; @Schema diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java index 87dfbd2eef6b121f27febf12357821ce6a585327..35df29430ff652372bb11487ada42ae55c02367c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableHistoryDto.java @@ -2,9 +2,8 @@ package at.tuwien.api.database.table; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.time.Instant; @@ -12,6 +11,7 @@ import java.time.Instant; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java index ea4d33df5de7391fd4dd940e718c121fbce3dacf..de6ff7feb7f35eeeb82fa8b028409268a473a7ed 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableInsertRawQuery.java @@ -9,6 +9,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java index 8862723b9ca573a9b7356f207d145850d1c233af..6b5529a0a1d08f75b803575e944cc5e624177eca 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableStatisticDto.java @@ -12,6 +12,7 @@ import java.util.Map; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -35,6 +36,5 @@ public class TableStatisticDto { private Long avgRowLength; @NotNull - @ToString.Exclude private Map<String, ColumnStatisticDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java index eb626b0eaf806fab422ffb2c91f0cd38ac8e486c..6c3a946e1257dd2a9a90175a1904d88cf2f1a339 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDeleteDto.java @@ -1,8 +1,7 @@ package at.tuwien.api.database.table; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.Map; @@ -10,6 +9,7 @@ import java.util.Map; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java index a428cb572604815ae80ab9f47f28965a7a784a69..62f57434b67dfe69e95bd212afb795f004da87d7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleDto.java @@ -1,8 +1,7 @@ package at.tuwien.api.database.table; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.Map; @@ -10,6 +9,7 @@ import java.util.Map; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java index fee00469b127f71361fbfd88013c915038023fae..be50791b944db8eada4316ca6ee975dedf95a113 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TupleUpdateDto.java @@ -1,8 +1,7 @@ package at.tuwien.api.database.table; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.Map; @@ -10,6 +9,7 @@ import java.util.Map; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java index 938315457433287d353a1e5722719d53a776098c..4dee5f0837148f9c2d1095fdbe12d6ab664672ef 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnBriefDto.java @@ -2,15 +2,15 @@ package at.tuwien.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java index 2d0696abc044db7dbffe8ace7444df0b9f7127c4..ca9bb10569e7bbeb30dd4b8080d0adbbcd2fab75 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java @@ -2,11 +2,10 @@ package at.tuwien.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Size; -import lombok.*; - import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.List; @@ -14,6 +13,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java index 92092fca33d726616ccba63f08a4b4fefbdba1a2..1f8d3b046e7c6fc6512fc68e53095822a3513061 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java @@ -1,10 +1,7 @@ package at.tuwien.api.database.table.columns; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.columns.concepts.ConceptDto; -import at.tuwien.api.database.table.columns.concepts.UnitDto; -import com.fasterxml.jackson.annotation.JsonIgnore; +import at.tuwien.api.database.table.columns.concepts.ConceptBriefDto; +import at.tuwien.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; @@ -20,11 +17,11 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class ColumnDto { @NotNull @@ -40,7 +37,7 @@ public class ColumnDto { @NotNull @Schema(example = "0") - @JsonProperty("ordinal_position") + @JsonProperty("ord") private Integer ordinalPosition; @NotBlank @@ -52,7 +49,6 @@ public class ColumnDto { @Size(max = 64) @JsonProperty("internal_name") @Schema(example = "mdb_date") - @EqualsAndHashCode.Include private String internalName; @Schema @@ -65,7 +61,7 @@ public class ColumnDto { private Long length; @NotNull - @JsonProperty("column_type") + @JsonProperty("type") @Schema(example = "string") private ColumnTypeDto columnType; @@ -105,28 +101,14 @@ public class ColumnDto { @JsonProperty("std_dev") private BigDecimal stdDev; - private ConceptDto concept; + private ConceptBriefDto concept; - private UnitDto unit; + private UnitBriefDto unit; @Size(max = 2048) @Schema(example = "Column comment") private String description; - @ToString.Exclude - @JsonIgnore - @EqualsAndHashCode.Include - private TableDto table; - - @ToString.Exclude - @JsonIgnore - private transient List<ViewDto> views; - - @NotNull - @JsonProperty("is_public") - @Schema(example = "true") - private Boolean isPublic; - @NotNull @JsonProperty("is_null_allowed") @Schema(example = "false") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java index 3f7ec87f3e92bcbfec1b1d8492874f6a0dd354ef..a7d76a47b260b7eac7e6b2c39a7c768abedbbe3c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnStatisticDto.java @@ -6,11 +6,11 @@ import lombok.*; import lombok.extern.jackson.Jacksonized; import java.math.BigDecimal; -import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java index 77a38f70b46b521e2cf0b03bdba4aca8fe6b48a7..9c74981f1416740ee6e5679d1ea2ed3fbc59e2bc 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java new file mode 100644 index 0000000000000000000000000000000000000000..1e2b36dc66a2f75a846e0ee66cef2037bb8cfd8b --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptBriefDto.java @@ -0,0 +1,28 @@ +package at.tuwien.api.database.table.columns.concepts; + +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 ConceptBriefDto { + + @NotNull + private Long id; + + @NotBlank + private String uri; + + private String name; + + private String description; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java index df171a5ee45c2dd81af2454d9c6a564ed333cfca..da00e64e8362ed298ba2bb9e2e98a596af716431 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptDto.java @@ -1,21 +1,17 @@ package at.tuwien.api.database.table.columns.concepts; import at.tuwien.api.database.table.columns.ColumnBriefDto; -import com.fasterxml.jackson.annotation.JsonFormat; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - 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.time.Instant; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java index 159e07823ce48327a171d976b16e40db5f2fb8fe..b61d911ef9b3141954fe041fa18f8ee9d1362680 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ConceptSaveDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java new file mode 100644 index 0000000000000000000000000000000000000000..407f3708eb7a7fbe2b9746122b1f712858b8cf5e --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitBriefDto.java @@ -0,0 +1,27 @@ +package at.tuwien.api.database.table.columns.concepts; + +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 UnitBriefDto { + + @NotNull + private Long id; + + @NotBlank + private String uri; + + private String name; + + private String description; +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java index bd2975c0cc53162fab217c49f8a4a0001f6b047d..48c7180c067123ec4ea09b0eb1b6cd167c4c9d7b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitDto.java @@ -1,21 +1,17 @@ package at.tuwien.api.database.table.columns.concepts; import at.tuwien.api.database.table.columns.ColumnBriefDto; -import com.fasterxml.jackson.annotation.JsonFormat; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - 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.time.Instant; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java index 326efc48b545a0d1ae55d6d41dfc7256ccb2f162..530c7c8fbb806e8ffc2eac124f0bd6fec3321ea4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/UnitSaveDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java index a317b08b8afb1a5f69d30aa69ff5d68ddbce14d6..3d35a20b0c57ae76f2d5fb6c4843e4d46d43ffab 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java @@ -12,6 +12,7 @@ import java.util.Set; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java index 1644c95cdcf488425f5ee6fb795bdac432169d6f..8016de91316bb0a5cbac30fc4148ecc39acdc33b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java @@ -28,11 +28,9 @@ public class ForeignKeyDto { private List<ForeignKeyReferenceDto> references; @NotNull - @ToString.Exclude private TableBriefDto table; @NotNull - @ToString.Exclude @JsonProperty("referenced_table") private TableBriefDto referencedTable; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java index 111903d9265517e4b532c46a84983843619f0835..55fcc46ecf85fc097eeef7677b9d0c897c612aa3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java @@ -22,11 +22,9 @@ public class ForeignKeyReferenceDto { private ForeignKeyBriefDto foreignKey; @NotNull - @ToString.Exclude private ColumnBriefDto column; @NotNull - @ToString.Exclude @JsonProperty("referenced_column") private ColumnBriefDto referencedColumn; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java index 25ad3f5d175cc8aeb4d07011c2bc9829da7242a6..80df5d443b70146c2ce2cda6e96bbf75c1816e28 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java @@ -18,10 +18,8 @@ public class PrimaryKeyDto { private Long id; @NotNull - @ToString.Exclude private TableBriefDto table; @NotNull - @ToString.Exclude private ColumnBriefDto column; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java index 05de53784457602248105e8ccd7a6987db53dd51..2bcc9d6cf4fb4d130c398dc2ed0341af46f61df9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java @@ -27,10 +27,8 @@ public class UniqueDto { private String name; @NotNull - @ToString.Exclude private TableBriefDto table; @NotNull - @ToString.Exclude private List<ColumnDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/PrivilegedTableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/PrivilegedTableDto.java index 33fe8c4789c3054eed0d7aeb8997cc400da1125f..64b23f17c412c1042c0a1db9a040a67fcc612b39 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/PrivilegedTableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/internal/PrivilegedTableDto.java @@ -24,7 +24,7 @@ import java.util.List; @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@EqualsAndHashCode public class PrivilegedTableDto extends PrivilegedObjectDto { @NotNull @@ -32,7 +32,6 @@ public class PrivilegedTableDto extends PrivilegedObjectDto { @NotNull @JsonProperty("database_id") - @EqualsAndHashCode.Include private Long tdbid; @NotBlank @@ -42,7 +41,6 @@ public class PrivilegedTableDto extends PrivilegedObjectDto { @NotBlank @JsonProperty("internal_name") @Schema(example = "air_quality") - @EqualsAndHashCode.Include private String internalName; @Schema diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java index c58f152d40f1b24ca2a728460374406f9e217e1f..bb271f5ed6065595898f0a4f73b9758f66da2294 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/error/ApiErrorDto.java @@ -1,15 +1,15 @@ package at.tuwien.api.error; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; import org.springframework.http.HttpStatus; -import jakarta.validation.constraints.NotNull; - @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java index 42675c889e11660d8e98cb2e2fb2c229d2d6850f..9c166f869c5bcec81c1e67212616e03833fe64c7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/CreatorDto.java @@ -13,6 +13,7 @@ import org.springframework.data.annotation.Id; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java index 616074f23331a1ee0f329e756fe86cd2fe8998e9..55e6ff76214a8af82ec32991c62aa265909d75f6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDescriptionDto.java @@ -11,6 +11,7 @@ import org.springframework.data.annotation.Id; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java index bff087c5905b817df53f5b338d2cee0284dfa95e..87baf4870661e292dbb69d180cfb1be43ac15f16 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java @@ -2,7 +2,7 @@ package at.tuwien.api.identifier; import at.tuwien.api.database.LanguageTypeDto; import at.tuwien.api.database.LicenseDto; -import at.tuwien.api.user.UserDto; +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; @@ -13,11 +13,11 @@ import lombok.extern.jackson.Jacksonized; import java.time.Instant; import java.util.List; -import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -71,7 +71,6 @@ public class IdentifierDto { @Schema(description = "query hash in sha512") private String queryHash; - @NotNull @Schema(example = "2021-03-12T15:26:21Z") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant execution; @@ -92,7 +91,7 @@ public class IdentifierDto { private String publisher; @NotNull - private UserDto owner; + private UserBriefDto owner; @JsonProperty("publication_day") @Schema(example = "15") @@ -116,8 +115,4 @@ public class IdentifierDto { private IdentifierStatusTypeDto status; - @NotNull - @JsonProperty("created_by") - private UUID createdBy; - } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java index ba0cc5b6dd0ce367daf6f71a2f71646325e9b399..921ba3eb983840dee342071bfde0a75f478946b4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierFunderDto.java @@ -11,6 +11,7 @@ import org.springframework.data.annotation.Id; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java index 70d6006bc239f2a09829cdb62ffbce950a75c4da..9333a05ce961a403b84463a10abc86ddb2a2e86c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierTitleDto.java @@ -11,6 +11,7 @@ import org.springframework.data.annotation.Id; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java index 271333c49dcce9d0be8a16605c6dd89ad11f837e..74525bf711988a0690aeba9c403a44156885b0f3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/RelatedIdentifierDto.java @@ -16,6 +16,7 @@ import java.time.Instant; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java new file mode 100644 index 0000000000000000000000000000000000000000..6df8ce5e8f733313e9c9f2534e6cef03adb0d5e5 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateAttributesDto.java @@ -0,0 +1,19 @@ +package at.tuwien.api.keycloak; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class UserCreateAttributesDto { + + @JsonProperty("CUSTOM_ID") + private String ldapId; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java index fe4b69550259023b135bf2ae43a70c85c888cce0..2a80811b6247cd18fde5b3eadea1921b1ab2c3a9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java @@ -1,6 +1,5 @@ package at.tuwien.api.keycloak; -import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.*; @@ -36,4 +35,6 @@ public class UserCreateDto { private List<String> groups; + private UserCreateAttributesDto attributes; + } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java index 3cb0a86e738a994a829fa064a95c5db1ac90b3a3..e6aec082263ebe4ebe2789a683264d06df43cc9b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ldap/UserDto.java @@ -9,15 +9,14 @@ import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class UserDto { @NotNull - @EqualsAndHashCode.Include private UUID id; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java index 8143b18fb94f4d62d45339cf09845b72d3f3fcb6..e9c15c212e100f997e6c4afc6c585a4726e92feb 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/maintenance/BannerMessageDto.java @@ -13,6 +13,7 @@ import java.time.Instant; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java index 4520b692bf65862f8326378b95c045d997c484b0..c4ea89b005df0f5506e91b2bcc428c95a173bc7f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/OrcidDto.java @@ -9,6 +9,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java index 544754cedf09f14794693da981aa293cc8a73097..625611abd27a28864b310354936f9d167adee12f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/OrcidActivitiesSummaryDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java index 5b8b6a3957d03341b91506de9caf6be06089f18d..dea853b62bc3680e8bcefcedb50f85aa567b2c74 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/OrcidEmploymentsDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java index 5a4ace0158c436c43d05c6d64aa713f243bc8887..a82a88869bb076791a85e8a9a51f45afb8e3a937 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/OrcidAffiliationGroupDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java index df3c038abfce62b858f108303eb672a91ea50339..984dc8a6d07fe69b00a49636268e4334f3037678 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/OrcidEmploymentSummaryDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java index e10e72481eadc20423d718ebcc1da9c8a9ba4297..1377a73dba186cab8fafcda307643ae62144a601 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/OrcidSummaryDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java index 53c59b4d1a995c0017ae571e0be9afdc44ecc310..149af1b3e693c2bd2da2e2f3decb102ee878e2d0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/OrcidOrganizationDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @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/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java index 5d2e31c5235f3d1fd9fdb81f8d49896e751dbb83..c5ed53e37ff2ddab6a79e76465578d306ce50952 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/activities/employments/affiliation/group/summary/organization/disambiguated/OrcidDisambiguatedDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java index 31c7f9235f5565e3f8e375398ba6c093c61d2036..f7de2794d721f283514562dfd8abecd687c229e5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/OrcidPersonDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java index a36f9b044e2242d5349140a897be4d54ff9a06c3..44c2ac0e6bdcc58229b0189709adc20729697669 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidNameDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java index baad8b0b782eb373a978b6467c4125080bc62914..251a39c23c3cd8d7dd4eb013461b530e76305647 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/orcid/person/name/OrcidValueDto.java @@ -6,6 +6,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java index d0c0f54bd53b5e26822d27371d2adc8101e796f7..8e9407885ca4f7e31994836a5664025ce7d499bb 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/ror/RorDto.java @@ -6,6 +6,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java index 4a3436dabab5dd556b99e0d266dac8535979d353..b908b6e09e26ea5938b7eb0b44554db0a746d22e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyBriefDto.java @@ -10,6 +10,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java index 09099331ec7cb5a37fd2b3ce8604f59b97005d7b..686cd9f030c952ace5d85a0eecb3f049bcd1a2a9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/OntologyDto.java @@ -14,6 +14,7 @@ import java.time.Instant; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java index 309561b96680b500faf15e79e71dba6d38b92dcc..79ea8d6a5a511a5794df53c455dddd912678219e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/semantics/TableColumnEntityDto.java @@ -13,7 +13,7 @@ import lombok.extern.jackson.Jacksonized; @NoArgsConstructor @AllArgsConstructor @Jacksonized -@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@EqualsAndHashCode @ToString public class TableColumnEntityDto { @@ -33,7 +33,6 @@ public class TableColumnEntityDto { private Long columnId; @NotBlank - @EqualsAndHashCode.Include @Schema(example = "https://www.wikidata.org/entity/Q1686799") private String uri; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java index d68514d42fff45a0b0f025a622847b4886906e57..f545f6204187a66a1c8942cb5e8a3eef9d73ae65 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/ExchangeUpdatePermissionsDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java index 08a7ce10d6a8c118299b771f4225eac0500fc85c..07e0029a716b1d4414b1c10c71b4ad6bcb11ae4a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/GrantedAuthorityDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java index 713fbdb0437947a685a08060810b0f7a25c74f92..ef9bae650c9c8615c9f7c43198dd61285aa2ce41 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserAttributesDto.java @@ -9,6 +9,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java index 08ce389cbfae5b6017ac770f0982a0ca90f904d9..d245bbaf4c46584b9f0cd93fa7b43c2b31ef6333 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserBriefDto.java @@ -2,9 +2,8 @@ package at.tuwien.api.user; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.UUID; @@ -12,6 +11,7 @@ import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java index e72a0505ab63963281091714336ec2598f584359..cd5e8fd3e0cefe2f016261470b1236e9a3442b16 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDetailsDto.java @@ -1,17 +1,18 @@ package at.tuwien.api.user; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotNull; import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java index 00a866bfd2923cc1ae88abc8273cd2d4b912295e..343d582b55da3af324aa23fd31ef61d8e1cd564d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java @@ -2,9 +2,8 @@ package at.tuwien.api.user; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.UUID; @@ -12,15 +11,14 @@ import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class UserDto { @NotNull - @EqualsAndHashCode.Include @Schema(example = "1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4") private UUID id; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java index 0459cb96e8911efc6197abb3752e8bb09a0faa2f..caaf33249710f14c7c49540aa8dd2afe0a18e0c3 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserEmailDto.java @@ -1,15 +1,15 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java index ffc95c3f8a6a0858961e57c5da58f1b5efbddf40..5ebcbae7429c335c122c62e58644b739d8fc90ea 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserForgotDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.Email; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java index 5fe224ee77185d2c5601133fcd0e22ec6a2546b9..2b86672cc2704886a287912ff39c70eba63f1904 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserModifyPasswordDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java index bcd21ded0249886fa44ca3e06d8be0725be3c060..dcf53932840057f6916b8ac281eae9031a40677e 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserPasswordDto.java @@ -1,13 +1,13 @@ package at.tuwien.api.user; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java index 919c3b12aff302ef9d1b14a6d287c7108d4bb753..6cac59a904c529b1aa226b788bff427092e5bb1f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserResetDto.java @@ -1,13 +1,13 @@ package at.tuwien.api.user; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java index 06d7c83f26ffa29fcba90e8cb01993a96c185238..5667f38ec6c6f639981376292af5d16cda58b866 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserRolesDto.java @@ -1,8 +1,7 @@ package at.tuwien.api.user; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; import java.util.List; @@ -10,6 +9,7 @@ import java.util.List; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java index 17cd44442a0c83d53fd189cad5e216ae832050af..3f5b899df8777459e4df5faa86dccad01d6ac703 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserThemeSetDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotNull; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java index 7f536fba36202d9689ec96620df16dfcc22ab672..68d674a7c2287dbd747969d3ad58cdf303cd2bf6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java index f54d2c474999d1d4b3c613c94e761cc584f66034..99f1eab30af6dc537ae767adb4e5e8cc8a1f5048 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserUpdatePermissionsDto.java @@ -1,14 +1,14 @@ package at.tuwien.api.user; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - import jakarta.validation.constraints.NotBlank; +import lombok.*; import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java index 80d5d04d6db2ea80de5b1b64c8a9683b51a3dd69..fb40af09487d8b65a2efabb0cb18d46e317484bb 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/ExternalMetadataDto.java @@ -4,11 +4,11 @@ import at.tuwien.api.user.external.affiliation.ExternalAffiliationDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; -import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor public class ExternalMetadataDto { diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java index 0e56dea2a2ef7ac7427fa3d561b9efc791f93634..d8d30894bcb443a5bfb33426c01f3910bd4ee9b2 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/external/affiliation/ExternalAffiliationDto.java @@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/PrivilegedUserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/PrivilegedUserDto.java index b0600cfefd8b43b23445c9ccd0e7e418d820ea42..56e24cd81590261137cfa3d4f0f3c45399d80e70 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/PrivilegedUserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/PrivilegedUserDto.java @@ -15,15 +15,14 @@ import java.util.UUID; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized @ToString -@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class PrivilegedUserDto extends PrivilegedObjectDto { @NotNull - @EqualsAndHashCode.Include @Schema(example = "1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4") private UUID id; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java index a498dd4a3156c09664bac68b50278f421cd66d58..c89e795bd367739c5b9d371e73c0191fa6758842 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/internal/UpdateUserPasswordDto.java @@ -7,6 +7,7 @@ import lombok.extern.jackson.Jacksonized; @Getter @Setter @Builder +@EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/entities/pom.xml b/dbrepo-metadata-service/entities/pom.xml index 6a8f527f188040713c0f259fb9ade60e7ef5b4dd..5b1c1d0cf133fcfea9de76e37cc0462d318481b6 100644 --- a/dbrepo-metadata-service/entities/pom.xml +++ b/dbrepo-metadata-service/entities/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-entities</artifactId> <name>dbrepo-metadata-service-entity</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies/> diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java index bbd994fa7ec05d775ba8a7c2eebb1ece418d2726..1ecedc5e16cef533008a28db7d022acab336c8d7 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/Operator.java @@ -9,11 +9,11 @@ import static jakarta.persistence.GenerationType.IDENTITY; @Data @Entity @Builder +@EqualsAndHashCode @ToString @AllArgsConstructor @NoArgsConstructor @EntityListeners(AuditingEntityListener.class) -@EqualsAndHashCode @Table(name = "mdb_image_operators") public class Operator { diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java index f70fbd93a31d7566e878fd11f31945bc73689c49..d90a702db33c759a511480fa0e89c37efc2773fc 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java @@ -32,14 +32,12 @@ import static jakarta.persistence.GenerationType.IDENTITY; @UniqueConstraint(columnNames = {"cid", "internalName"}) }) @NamedQueries({ - @NamedQuery(name = "Database.findAllDesc", query = "select d from Database d order by d.created desc"), - @NamedQuery(name = "Database.findByInternalName", query = "select d from Database d where d.internalName = ?1"), - @NamedQuery(name = "Database.findAllOnlyIds", query = "select d.id from Database d order by d.created desc"), - @NamedQuery(name = "Database.findReadAccess", query = "select distinct d from Database d join DatabaseAccess a on a.hdbid = d.id and a.huserid = ?1"), - @NamedQuery(name = "Database.findWriteAccess", query = "select distinct d from Database d join DatabaseAccess a on a.hdbid = d.id and a.huserid = ?1 where a.type = 'WRITE_OWN' or a.type = 'WRITE_ALL'"), - @NamedQuery(name = "Database.findConfigureAccess", query = "select distinct d from Database d where d.ownedBy = ?1"), - @NamedQuery(name = "Database.findPublicOrMine", query = "select distinct d from Database d where d.id = ?1 and (d.isPublic = true or d.ownedBy = ?2)"), - @NamedQuery(name = "Database.findPublic", query = "select distinct d from Database d where d.isPublic = true and d.id = ?1"), + @NamedQuery(name = "Database.findAllDesc", query = "select distinct d from Database d 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"), }) public class Database implements Serializable { diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java index 079aac84c7d191f71d29657c6837a6ae9f545bab..6a2622be3e7137c97b68ab9ad91e24edd4fae293 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java @@ -33,6 +33,7 @@ public class DatabaseAccess { private UUID huserid; @ToString.Exclude + @EqualsAndHashCode.Exclude @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java index c732864969c23bf45e4c616bd0c154703615d286..fd87852c6ecce0e2e614a9c7dd05a5e41cfe2e16 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/user/User.java @@ -7,7 +7,6 @@ import lombok.extern.log4j.Log4j2; import org.hibernate.annotations.JdbcTypeCode; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import java.security.Principal; import java.util.List; import java.util.UUID; @@ -21,6 +20,9 @@ import java.util.UUID; @EqualsAndHashCode @EntityListeners(AuditingEntityListener.class) @Table(name = "mdb_users") +@NamedQueries({ + @NamedQuery(name = "User.findAllInternal", query = "select distinct u from User u where u.isInternal = true") +}) public class User { @Id @@ -50,6 +52,7 @@ public class User { private String language; @OneToMany(fetch = FetchType.LAZY) + @EqualsAndHashCode.Exclude @JoinColumns({ @JoinColumn(name = "user_id", referencedColumnName = "ID", insertable = false, updatable = false) }) @@ -61,4 +64,7 @@ public class User { @Column(name = "mariadb_password", nullable = false) private String mariadbPassword; + @Column(name = "is_internal", nullable = false, updatable = false) + private Boolean isInternal; + } diff --git a/dbrepo-metadata-service/oai/pom.xml b/dbrepo-metadata-service/oai/pom.xml index 32925ee9ff1c042a0edb5a22ebb1929f9ff63390..a3778f036317625e12a6b526a7f1fafadbe237f6 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-oai</artifactId> <name>dbrepo-metadata-service-oai</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies/> diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index 27dd83121f6b83d311872023b306be181ebd409d..2803d9b5f39ddd69f34151251083c35e8a46b406 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -11,7 +11,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> <name>dbrepo-metadata-service</name> - <version>1.6.0</version> + <version>1.6.1</version> <description>Service that manages the metadata</description> @@ -60,6 +60,8 @@ <aws-s3.version>2.25.23</aws-s3.version> <jackson.version>2.15.2</jackson.version> <minio.version>8.5.7</minio.version> + <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + </sonar.coverage.jacoco.xmlReportPaths> </properties> <dependencies> diff --git a/dbrepo-metadata-service/report/pom.xml b/dbrepo-metadata-service/report/pom.xml index f71cbfeb96f6307986b2ee87a5f9ba99f8cfd001..6234a844d2c89c01c7e3d200ce79397ac99eac37 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.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-report</artifactId> <name>dbrepo-metadata-service-report</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/pom.xml b/dbrepo-metadata-service/repositories/pom.xml index 480ba479be0f98ca6d7748a25545625cce000ecd..44fde031c181fa559abdbce4b81e59f76c5f4b48 100644 --- a/dbrepo-metadata-service/repositories/pom.xml +++ b/dbrepo-metadata-service/repositories/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-repositories</artifactId> <name>dbrepo-metadata-service-repositories</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index f63c387c9865079aca8eb8a3dedf74dcccdc3bba..c5482f70411433f5df08bd0281a60c75d132bf26 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -236,8 +236,6 @@ public interface MetadataMapper { }) DataCiteDoiRelatedIdentifier relatedIdentifierToDoiRelatedIdentifier(RelatedIdentifier relatedIdentifier); - Date instantToDate(Instant data); - @Mappings({ @Mapping(target = "givenNames", source = "person.name.givenNames.value"), @Mapping(target = "familyName", source = "person.name.familyName.value"), @@ -523,11 +521,17 @@ public interface MetadataMapper { .build(); } - default TableDto customTableToTableDto(Table data) { - return customTableToTableDto(data, true, true, true); + default DatabaseAccess userToWriteAllAccess(Database database, User user) { + return DatabaseAccess.builder() + .type(AccessType.WRITE_ALL) + .hdbid(database.getId()) + .database(database) + .huserid(user.getId()) + .user(user) + .build(); } - default TableDto customTableToTableDto(Table data, Boolean broker, Boolean statistic, Boolean schema) { + default TableDto customTableToTableDto(Table data) { final TableDto table = TableDto.builder() .id(data.getId()) .name(data.getName()) @@ -548,18 +552,14 @@ public interface MetadataMapper { .map(this::identifierToIdentifierDto) .toList())); } - if (broker) { - table.setQueueName(data.getQueueName()); - table.setQueueType("quorum"); - table.setRoutingKey("dbrepo." + data.getTdbid() + "." + data.getId()); - } - if (statistic) { - table.setAvgRowLength(data.getAvgRowLength()); - table.setMaxDataLength(data.getMaxDataLength()); - table.setDataLength(data.getDataLength()); - table.setNumRows(data.getNumRows()); - } - if (schema) { + table.setQueueName(data.getQueueName()); + table.setQueueType("quorum"); + table.setRoutingKey("dbrepo." + data.getTdbid() + "." + data.getId()); + table.setAvgRowLength(data.getAvgRowLength()); + table.setMaxDataLength(data.getMaxDataLength()); + table.setDataLength(data.getDataLength()); + table.setNumRows(data.getNumRows()); + if (table.getConstraints() != null) { table.getConstraints() .getPrimaryKey() .forEach(pk -> { @@ -594,12 +594,12 @@ public interface MetadataMapper { if (data.getConstraints().getChecks() == null || data.getConstraints().getChecks().isEmpty()) { table.getConstraints().setChecks(new LinkedHashSet<>()); } - if (data.getColumns() != null) { - table.setColumns(new LinkedList<>(data.getColumns() - .stream() - .map(this::tableColumnToColumnDto) - .toList())); - } + } + if (data.getColumns() != null) { + table.setColumns(new LinkedList<>(data.getColumns() + .stream() + .map(this::tableColumnToColumnDto) + .toList())); } return table; } @@ -719,10 +719,7 @@ public interface MetadataMapper { @Mappings({ @Mapping(target = "tableId", source = "table.id"), @Mapping(target = "databaseId", source = "table.database.id"), - @Mapping(target = "isPublic", source = "table.isSchemaPublic"), - @Mapping(target = "description", source = "description"), - @Mapping(target = "table", ignore = true), - @Mapping(target = "views", ignore = true) + @Mapping(target = "description", source = "description") }) ColumnDto tableColumnToColumnDto(TableColumn data); @@ -784,6 +781,7 @@ public interface MetadataMapper { @Mapping(target = "attributes.orcid", source = "orcid"), @Mapping(target = "attributes.affiliation", source = "affiliation"), @Mapping(target = "attributes.theme", source = "theme"), + @Mapping(target = "attributes.mariadbPassword", source = "mariadbPassword"), @Mapping(target = "name", expression = "java(userToFullName(data))"), @Mapping(target = "qualifiedName", expression = "java(userToQualifiedName(data))"), }) @@ -824,14 +822,10 @@ public interface MetadataMapper { .trim(); } - @Mappings({ - @Mapping(target = "database.views", ignore = true) - }) ViewDto viewToViewDto(View data); @Mappings({ @Mapping(target = "databaseId", source = "view.vdbid"), - @Mapping(target = "isPublic", source = "view.isPublic") }) ViewColumnDto viewColumnToViewColumnDto(ViewColumn data); @@ -858,18 +852,7 @@ public interface MetadataMapper { LanguageType languageTypeDtoToLanguageType(LanguageTypeDto data); - default Boolean onlyIsPublicOrOwner(Boolean isPublic, User caller, User owner, User databaseOwner) { - if (isPublic) { - return true; - } - /* private schema */ - if (caller == null) { - return false; - } - return owner.equals(caller) || databaseOwner.equals(caller); - } - - default DatabaseDto customDatabaseToDatabaseDto(Database data, User caller) { + default DatabaseDto customDatabaseToDatabaseDto(Database data) { if (data == null) { return null; } @@ -899,20 +882,19 @@ public interface MetadataMapper { if (data.getTables() != null) { database.setTables(new LinkedList<>(data.getTables() .stream() - .filter(t -> onlyIsPublicOrOwner(t.getIsSchemaPublic() || t.getIsPublic(), caller, t.getOwner(), t.getDatabase().getOwner())) .map(this::tableToTableBriefDto) .toList())); } if (data.getViews() != null) { database.setViews(new LinkedList<>(data.getViews() .stream() - .filter(v -> onlyIsPublicOrOwner(v.getIsSchemaPublic() || v.getIsPublic(), caller, v.getOwner(), v.getDatabase().getOwner())) .map(this::viewToViewBriefDto) .toList())); } if (data.getAccesses() != null) { database.setAccesses(new LinkedList<>(data.getAccesses() .stream() + .filter(a -> !a.getUser().getIsInternal()) .map(this::databaseAccessToDatabaseAccessDto) .toList())); } @@ -925,6 +907,9 @@ public interface MetadataMapper { return database; } + @Mappings({ + @Mapping(target = "ownerId", source = "owner.id") + }) DatabaseBriefDto databaseToDatabaseBriefDto(Database data); AccessType accessTypeDtoToAccessType(AccessTypeDto data); diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java index 3b962bccbb89bad6f6ad5d765860f48df10a0fb0..38a0a8044162cbf3abe9178de26fca4a21e7ee4c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java @@ -13,18 +13,14 @@ public interface DatabaseRepository extends JpaRepository<Database, Long> { List<Database> findAllDesc(); - List<Database> findReadAccess(UUID id); + List<Database> findAllPublicOrSchemaPublicDesc(); - List<Database> findWriteAccess(UUID id); + List<Database> findAllAtLestReadAccessDesc(UUID id); - List<Database> findConfigureAccess(UUID id); + List<Database> findAllPublicOrSchemaPublicOrReadAccessDesc(UUID id); - List<Long> findAllOnlyIds(); + List<Database> findAllPublicOrSchemaPublicOrReadAccessByInternalNameDesc(UUID id, String internalName); - Optional<Database> findPublicOrMine(Long databaseId, UUID id); - - Optional<Database> findPublic(Long databaseId); - - Optional<Database> findByInternalName(String internalName); + List<Database> findAllPublicOrSchemaPublicByInternalNameDesc(String internalName); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java index f21596858ac628560634d6449c5ec6aba3e43ce9..7415fb422c03882f7f71786b0edf756c7bd58159 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/UserRepository.java @@ -4,6 +4,7 @@ import at.tuwien.entities.user.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -12,6 +13,8 @@ public interface UserRepository extends JpaRepository<User, UUID> { Optional<User> findByUsername(String username); + List<User> findAllInternal(); + boolean existsByUsername(String username); boolean existsByEmail(String email); diff --git a/dbrepo-metadata-service/rest-service/pom.xml b/dbrepo-metadata-service/rest-service/pom.xml index 67b149976cd1bb218d2e995b89e6c3d8e81ced3a..233d2ac4658612ad06bccc5140bad70c08265ec5 100644 --- a/dbrepo-metadata-service/rest-service/pom.xml +++ b/dbrepo-metadata-service/rest-service/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-rest-service</artifactId> <name>dbrepo-metadata-service-rest</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java similarity index 54% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java index 4e517625ed8bc7d700c1815a8437675d17534d85..4779a6428e33bde6be581921a9d15bd81a25c5b6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java @@ -1,14 +1,17 @@ -package at.tuwien.utils; +package at.tuwien.endpoints; import at.tuwien.api.user.UserDetailsDto; +import at.tuwien.exception.UserNotFoundException; +import at.tuwien.service.UserService; import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.User; import java.security.Principal; import java.util.UUID; -public class UserUtil { +public abstract class AbstractEndpoint { - public static boolean hasRole(Principal principal, String role) { + public boolean hasRole(Principal principal, String role) { if (principal == null || role == null) { return false; } @@ -18,7 +21,7 @@ public class UserUtil { .anyMatch(a -> a.getAuthority().equals(role)); } - public static boolean isSystem(Principal principal) { + public boolean isSystem(Principal principal) { if (principal == null) { return false; } @@ -28,16 +31,18 @@ public class UserUtil { .anyMatch(a -> a.getAuthority().equals("system")); } - public static UUID getId(Principal principal) { + public UUID getId(Principal principal) { if (principal == null) { return null; } final Authentication authentication = (Authentication) principal; - final UserDetailsDto user = (UserDetailsDto) authentication.getPrincipal(); - if (user.getId() == null) { - return null; + if (authentication.getPrincipal() instanceof UserDetailsDto user) { + if (user.getId() == null) { + throw new IllegalArgumentException("Principal has no id"); + } + return UUID.fromString(user.getId()); } - return UUID.fromString(user.getId()); + throw new IllegalArgumentException("Unknown principal instance: " + authentication.getPrincipal().getClass()); } } 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/tuwien/endpoints/AccessEndpoint.java index 99e4d2e6b11d58fa31bd58effbd849a9696c16d1..f184ffc3372ac10e35f2d6686b0c79e2ecaca818 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/tuwien/endpoints/AccessEndpoint.java @@ -11,7 +11,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AccessService; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -35,7 +34,7 @@ import java.util.UUID; @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database/{databaseId}/access") -public class AccessEndpoint { +public class AccessEndpoint extends AbstractEndpoint { private final UserService userService; private final AccessService accessService; @@ -99,8 +98,7 @@ public class AccessEndpoint { log.debug("endpoint give access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, data.getType()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to create access: not owner"); throw new NotAllowedException("Failed to create access: not owner"); } @@ -162,12 +160,19 @@ public class AccessEndpoint { log.debug("endpoint modify database access, databaseId={}, userId={}, access.type={}, principal.name={}", databaseId, userId, data.getType(), principal.getName()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to update access: not owner"); throw new NotAllowedException("Failed to update access: not owner"); } + if (database.getOwner().getId().equals(userId)) { + log.error("Failed to update access: the owner must have write-all access"); + throw new NotAllowedException("Failed to update access: the owner must have write-all access"); + } 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"); + } accessService.find(database, user); accessService.update(database, user, data.getType()); return ResponseEntity.accepted() @@ -204,9 +209,8 @@ public class AccessEndpoint { UserNotFoundException, AccessNotFoundException, NotAllowedException { log.debug("endpoint get database access, databaseId={}, userId={}, principal.name={}", databaseId, userId, principal.getName()); - final User caller = userService.findByUsername(principal.getName()); - if (!userId.equals(caller.getId())) { - if (!UserUtil.hasRole(principal, "check-foreign-database-access")) { + if (!userId.equals(getId(principal))) { + if (!hasRole(principal, "check-foreign-database-access")) { log.error("Failed to find access: foreign user"); throw new NotAllowedException("Failed to find access: foreign user"); } @@ -261,12 +265,19 @@ public class AccessEndpoint { SearchServiceException, SearchServiceConnectionException { log.debug("endpoint revoke database access, databaseId={}, userId={}", databaseId, userId); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to revoke access: not owner"); throw new NotAllowedException("Failed to revoke access: not owner"); } + if (database.getOwner().getId().equals(userId)) { + log.error("Failed to revoke access: the owner must have write-all access"); + throw new NotAllowedException("Failed to revoke access: the owner must have write-all access"); + } final User user = userService.findById(userId); + if (user.getIsInternal()) { + log.error("Failed to revoke access: the internal user must have write-all access"); + throw new NotAllowedException("Failed to revoke access: the internal user must have write-all access"); + } accessService.find(database, user); accessService.delete(database, user); return ResponseEntity.accepted() 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/tuwien/endpoints/ConceptEndpoint.java index 44a592658ea3f8a512a07cbfe261b39192e3b1e4..acf6a31ca2a583a91ba9bf9e1e4e3c544342eb65 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/tuwien/endpoints/ConceptEndpoint.java @@ -14,7 +14,10 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -22,7 +25,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/concept") -public class ConceptEndpoint { +public class ConceptEndpoint extends AbstractEndpoint { private final ConceptService conceptService; private final MetadataMapper metadataMapper; @@ -47,13 +50,11 @@ public class ConceptEndpoint { }) public ResponseEntity<List<ConceptDto>> findAll() { log.debug("endpoint list concepts"); - final List<ConceptDto> dtos = conceptService.findAll() - .stream() - .map(metadataMapper::tableColumnConceptToConceptDto) - .toList(); - log.trace("Find all concepts resulted in dtos {}", dtos); return ResponseEntity.ok() - .body(dtos); + .body(conceptService.findAll() + .stream() + .map(metadataMapper::tableColumnConceptToConceptDto) + .toList()); } } 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/tuwien/endpoints/ContainerEndpoint.java index 7995b79bf62117f2f360375af08eb93e1d80eee5..3c506cfd0a910d10bba6401eebe5467d1c97e738 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/tuwien/endpoints/ContainerEndpoint.java @@ -10,7 +10,6 @@ import at.tuwien.exception.ContainerNotFoundException; import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.ContainerService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -40,7 +39,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @ControllerAdvice @RequestMapping(path = "/api/container") -public class ContainerEndpoint { +public class ContainerEndpoint extends AbstractEndpoint { private final MetadataMapper metadataMapper; private final ContainerService containerService; @@ -65,13 +64,11 @@ public class ContainerEndpoint { }) public ResponseEntity<List<ContainerBriefDto>> findAll(@RequestParam(required = false) Integer limit) { log.debug("endpoint find all containers, limit={}", limit); - final List<ContainerBriefDto> dtos = containerService.getAll(limit) - .stream() - .map(metadataMapper::containerToContainerBriefDto) - .collect(Collectors.toList()); - log.debug("find all containers resulted in {} container(s)", dtos.size()); return ResponseEntity.ok() - .body(dtos); + .body(containerService.getAll(limit) + .stream() + .map(metadataMapper::containerToContainerBriefDto) + .collect(Collectors.toList())); } @PostMapping @@ -111,11 +108,8 @@ public class ContainerEndpoint { public ResponseEntity<ContainerDto> create(@Valid @RequestBody ContainerCreateDto data) throws ImageNotFoundException, ContainerAlreadyExistsException { log.debug("endpoint create container, data={}", data); - final Container container = containerService.create(data); - final ContainerDto dto = metadataMapper.containerToContainerDto(container); - log.trace("create container resulted in container {}", dto); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.containerToContainerDto(containerService.create(data))); } @GetMapping("/{containerId}") @@ -140,10 +134,8 @@ public class ContainerEndpoint { throws ContainerNotFoundException { log.debug("endpoint find container, containerId={}", containerId); final Container container = containerService.find(containerId); - final ContainerDto dto = metadataMapper.containerToContainerDto(container); - log.trace("find container resulted in container {}", dto); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { log.trace("attach privileged credential information"); headers.set("X-Username", container.getPrivilegedUsername()); headers.set("X-Password", container.getPrivilegedPassword()); @@ -151,7 +143,7 @@ public class ContainerEndpoint { } return ResponseEntity.ok() .headers(headers) - .body(dto); + .body(metadataMapper.containerToContainerDto(container)); } @DeleteMapping("/{containerId}") @@ -175,10 +167,10 @@ public class ContainerEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<Void> delete(@NotNull @PathVariable("containerId") Long containerId) throws ContainerNotFoundException { + public ResponseEntity<Void> delete(@NotNull @PathVariable("containerId") Long containerId) + throws ContainerNotFoundException { log.debug("endpoint delete container, containerId={}", containerId); - final Container container = containerService.find(containerId); - containerService.remove(container); + containerService.remove(containerService.find(containerId)); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 29c27074d77253c5cecd6e4ea67afb07954e3bed..ad72fb0756f20fac58bc717c0da601f9b5bb1c74 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -5,11 +5,15 @@ 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.database.View; +import at.tuwien.entities.database.table.Table; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; +import at.tuwien.service.ContainerService; +import at.tuwien.service.DatabaseService; +import at.tuwien.service.StorageService; +import at.tuwien.service.UserService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -32,29 +36,25 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.security.Principal; -import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; +import java.util.Optional; @Log4j2 @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database") -public class DatabaseEndpoint { +public class DatabaseEndpoint extends AbstractEndpoint { private final UserService userService; - private final AccessService accessService; private final MetadataMapper databaseMapper; private final StorageService storageService; private final DatabaseService databaseService; private final ContainerService containerService; @Autowired - public DatabaseEndpoint(UserService userService, AccessService accessService, MetadataMapper databaseMapper, - StorageService storageService, DatabaseService databaseService, - ContainerService containerService) { + public DatabaseEndpoint(UserService userService, MetadataMapper databaseMapper, StorageService storageService, + DatabaseService databaseService, ContainerService containerService) { this.userService = userService; - this.accessService = accessService; this.databaseMapper = databaseMapper; this.storageService = storageService; this.databaseService = databaseService; @@ -75,28 +75,35 @@ public class DatabaseEndpoint { mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = DatabaseDto.class)))}), }) - public ResponseEntity<List<DatabaseBriefDto>> list(@RequestParam(name = "internal_name", required = false) String internalName) { + public ResponseEntity<List<DatabaseBriefDto>> list(@RequestParam(name = "internal_name", required = false) String internalName, + Principal principal) { log.debug("endpoint list databases, internalName={}", internalName); - List<DatabaseBriefDto> dtos = new LinkedList<>(); - if (internalName != null) { - try { - dtos = List.of(databaseMapper.databaseToDatabaseBriefDto(databaseService.findByInternalName(internalName))); - } catch (DatabaseNotFoundException e) { - /* ignore */ + final List<Database> databases; + if (principal != null) { + if (internalName != null) { + log.debug("filter request to contain only public databases or where user with id {} has at least read access that match internal name {}", getId(principal), internalName); + databases = databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(getId(principal), internalName); + } else { + log.debug("filter request to contain only databases where user with id {} has at least read access", getId(principal)); + databases = databaseService.findAllPublicOrSchemaPublicOrReadAccess(getId(principal)); } } else { - dtos = databaseService.findAll() - .stream() - .map(databaseMapper::databaseToDatabaseBriefDto) - .toList(); + if (internalName != null) { + log.debug("filter request to contain only public databases that match internal name {}", internalName); + databases = databaseService.findAllPublicOrSchemaPublicByInternalName(internalName); + } else { + log.debug("filter request to contain only public databases"); + databases = databaseService.findAllPublicOrSchemaPublic(); + } } - log.trace("list databases resulted in {} database(s)", dtos.size()); final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Count", "" + dtos.size()); + headers.set("X-Count", "" + databases.size()); headers.set("Access-Control-Expose-Headers", "X-Count"); return ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(dtos); + .body(databases.stream() + .map(databaseMapper::databaseToDatabaseBriefDto) + .toList()); } @PostMapping @@ -150,20 +157,19 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> create(@Valid @RequestBody DatabaseCreateDto data, @NotNull Principal principal) throws DataServiceException, - DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, - SearchServiceException, SearchServiceConnectionException, ContainerQuotaException { + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, + ContainerQuotaException { log.debug("endpoint create database, data.name={}", data.getName()); final Container container = containerService.find(data.getCid()); - final User caller = userService.findByUsername(principal.getName()); if (container.getDatabases().size() + 1 > container.getQuota()) { log.error("Failed to create database: quota of {} exceeded", container.getQuota()); throw new ContainerQuotaException("Failed to create database: quota of " + container.getQuota() + " exceeded"); } - final User user = userService.findByUsername(principal.getName()); - final Database database = databaseService.create(container, data, user); - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database, caller); + final User caller = userService.findById(getId(principal)); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.create(container, data, caller, userService.findAllInternalUsers()))); } @PutMapping("/{databaseId}/metadata/table") @@ -212,13 +218,12 @@ public class DatabaseEndpoint { TableNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to refresh database tables metadata: not owner"); throw new NotAllowedException("Failed to refresh tables metadata: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.updateTableMetadata(database), caller); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(databaseMapper.customDatabaseToDatabaseDto( + databaseService.updateTableMetadata(database))); } @PutMapping("/{databaseId}/metadata/view") @@ -261,13 +266,12 @@ public class DatabaseEndpoint { SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, ViewNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}, principal.name={}", databaseId, principal.getName()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to refresh database views metadata: not owner"); throw new NotAllowedException("Failed to refresh database views metadata: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.updateViewMetadata(database), caller); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(databaseMapper.customDatabaseToDatabaseDto( + databaseService.updateViewMetadata(database))); } @PutMapping("/{databaseId}/visibility") @@ -315,14 +319,13 @@ public class DatabaseEndpoint { NotAllowedException, SearchServiceException, SearchServiceConnectionException, UserNotFoundException { log.debug("endpoint modify database visibility, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().equals(caller)) { + 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 DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyVisibility(database, data), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyVisibility(database, data))); } @PutMapping("/{databaseId}/owner") @@ -371,15 +374,14 @@ public class DatabaseEndpoint { SearchServiceException, SearchServiceConnectionException { log.debug("endpoint transfer database, databaseId={}, transferDto.id={}", databaseId, data.getId()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); final User newOwner = userService.findById(data.getId()); - if (!database.getOwner().equals(caller)) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to transfer database: not owner"); throw new NotAllowedException("Failed to transfer database: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyOwner(database, newOwner), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyOwner(database, newOwner))); } @PutMapping("/{databaseId}/image") @@ -395,13 +397,13 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), - @ApiResponse(responseCode = "404", - description = "Database or user could not be found", + @ApiResponse(responseCode = "403", + description = "Modify of image is not permitted", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "403", - description = "Modify of image is not permitted", + @ApiResponse(responseCode = "404", + description = "Database could not be found", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -424,23 +426,21 @@ public class DatabaseEndpoint { public ResponseEntity<DatabaseDto> modifyImage(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody DatabaseModifyImageDto data, @NotNull Principal principal) throws NotAllowedException, - DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException, + DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, StorageUnavailableException, StorageNotFoundException { log.debug("endpoint modify database image, databaseId={}, data.key={}", databaseId, data.getKey()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to update database image: not owner"); throw new NotAllowedException("Failed to update database image: not owner"); } - final DatabaseDto dto; byte[] image = null; if (data.getKey() != null) { image = storageService.getBytes(data.getKey()); } - dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyImage(database, image), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyImage(database, image))); } @GetMapping("/{databaseId}/image") @@ -461,10 +461,9 @@ public class DatabaseEndpoint { public ResponseEntity<byte[]> findPreviewImage(@NotNull @PathVariable("databaseId") Long databaseId) throws DatabaseNotFoundException { log.debug("endpoint get database preview image, databaseId={}", databaseId); - final Database database = databaseService.findById(databaseId); return ResponseEntity.ok() .contentType(MediaType.parseMediaType("image/webp")) - .body(database.getImage()); + .body(databaseService.findById(databaseId).getImage()); } @GetMapping("/{databaseId}") @@ -482,6 +481,11 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to view database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", description = "Database, user or exchange could not be found", content = {@Content( @@ -500,27 +504,51 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, Principal principal) throws DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, + NotAllowedException { log.debug("endpoint find database, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User caller; if (principal != null) { - caller = userService.findByUsername(principal.getName()); + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getUser().getId().equals(getId(principal))) + .findFirst(); + if (!database.getIsPublic() && !database.getIsSchemaPublic() && optional.isEmpty() && !isSystem(principal)) { + log.error("Failed to find database: not public and no access found"); + throw new DatabaseNotFoundException("Failed to find database: not public and no access found"); + } + /* reduce metadata */ + database.setTables(database.getTables() + .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent()) + .toList()); + database.setViews(database.getViews() + .stream() + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent()) + .toList()); + 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 { - caller = null; - } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database, caller); - if (caller != null && database.getOwner().getId().equals(caller.getId())) { - log.debug("current logged-in user is also the owner: additionally load access list"); - /* only owner sees the access rights */ - final List<DatabaseAccess> accesses = accessService.list(database); - dto.setAccesses(accesses.stream() - .map(databaseMapper::databaseAccessToDatabaseAccessDto) - .collect(Collectors.toList())); - log.debug("found {} database accesses", accesses.size()); + 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.setTables(database.getTables() + .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic()) + .toList()); + database.setViews(database.getViews() + .stream() + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic()) + .toList()); + database.setAccesses(List.of()); } + final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", database.getContainer().getPrivilegedUsername()); headers.set("X-Password", database.getContainer().getPrivilegedPassword()); headers.set("X-Host", database.getContainer().getHost()); 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/tuwien/endpoints/IdentifierEndpoint.java index 31fcd6730551277b4eab2a8bdced3e42afbfbcb5..2830f9714a62cb7fea0b0cf616b4bd54eff8d340 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/tuwien/endpoints/IdentifierEndpoint.java @@ -12,10 +12,8 @@ import at.tuwien.entities.identifier.IdentifierStatusType; import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.entities.user.User; import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -29,7 +27,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -48,11 +45,9 @@ import java.util.regex.Pattern; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/identifier") -public class IdentifierEndpoint { +public class IdentifierEndpoint extends AbstractEndpoint { private final UserService userService; - private final ViewService viewService; - private final TableService tableService; private final AccessService accessService; private final EndpointConfig endpointConfig; private final MetadataMapper metadataMapper; @@ -60,17 +55,15 @@ public class IdentifierEndpoint { private final MetadataService metadataService; private final EndpointValidator endpointValidator; private final IdentifierService identifierService; - private final DataServiceGateway dataServiceGateway; + + private static final String CREATE_FOREIGN_IDENTIFIER_ROLE = "create-foreign-identifier"; @Autowired - public IdentifierEndpoint(UserService userService, ViewService viewService, TableService tableService, - AccessService accessService, EndpointConfig endpointConfig, MetadataMapper metadataMapper, - DatabaseService databaseService, MetadataService metadataService, - EndpointValidator endpointValidator, IdentifierService identifierService, - DataServiceGateway dataServiceGateway) { + public IdentifierEndpoint(UserService userService, AccessService accessService, EndpointConfig endpointConfig, + MetadataMapper metadataMapper, DatabaseService databaseService, + MetadataService metadataService, EndpointValidator endpointValidator, + IdentifierService identifierService) { this.userService = userService; - this.viewService = viewService; - this.tableService = tableService; this.accessService = accessService; this.endpointConfig = endpointConfig; this.metadataMapper = metadataMapper; @@ -78,7 +71,6 @@ public class IdentifierEndpoint { this.metadataService = metadataService; this.endpointValidator = endpointValidator; this.identifierService = identifierService; - this.dataServiceGateway = dataServiceGateway; } @GetMapping(produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json"}) @@ -119,25 +111,24 @@ public class IdentifierEndpoint { return ResponseEntity.ok(List.of()); } log.trace("found persistent identifiers {}", identifiers); - switch (accept) { - case "application/json": + return switch (accept) { + case "application/json" -> { log.trace("accept header matches json"); - final List<IdentifierBriefDto> resource1 = identifiers.stream() + yield ResponseEntity.ok(identifiers.stream() .map(metadataMapper::identifierToIdentifierBriefDto) - .toList(); - log.debug("find identifier resulted in identifiers {}", resource1); - return ResponseEntity.ok(resource1); - case "application/ld+json": + .toList()); + } + case "application/ld+json" -> { log.trace("accept header matches json-ld"); - final List<LdDatasetDto> resource2 = identifiers.stream() + yield ResponseEntity.ok(identifiers.stream() .map(i -> metadataMapper.identifierToLdDatasetDto(i, endpointConfig.getWebsiteUrl())) - .toList(); - log.debug("find identifier resulted in identifiers {}", resource2); - return ResponseEntity.ok(resource2); - default: + .toList()); + } + default -> { log.error("accept header {} is not supported", accept); throw new FormatNotAvailableException("Must provide either application/json or application/ld+json headers"); - } + } + }; } @GetMapping(value = "/{identifierId}", produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json", @@ -209,30 +200,20 @@ public class IdentifierEndpoint { switch (accept) { case "application/json": log.trace("accept header matches json"); - final IdentifierDto resource1 = metadataMapper.identifierToIdentifierDto(identifier); - log.debug("find identifier resulted in identifier {}", resource1); - return ResponseEntity.ok(resource1); + return ResponseEntity.ok(metadataMapper.identifierToIdentifierDto(identifier)); case "application/ld+json": log.trace("accept header matches json-ld"); - final LdDatasetDto resource2 = metadataMapper.identifierToLdDatasetDto(identifier, endpointConfig.getWebsiteUrl()); - log.debug("find identifier resulted in identifier {}", resource2); - log.debug("find identifier resulted in identifier {}", resource2); - return ResponseEntity.ok(resource2); + return ResponseEntity.ok(metadataMapper.identifierToLdDatasetDto(identifier, endpointConfig.getWebsiteUrl())); case "text/csv": log.trace("accept header matches csv"); if (identifier.getType().equals(IdentifierType.DATABASE)) { log.error("Failed to export dataset: identifier type is database"); throw new FormatNotAvailableException("Failed to export dataset: identifier type is database"); } - final InputStreamResource resource3; - resource3 = identifierService.exportResource(identifier); - log.debug("find identifier resulted in resource {}", resource3); - return ResponseEntity.ok(resource3); + return ResponseEntity.ok(identifierService.exportResource(identifier)); case "text/xml": log.trace("accept header matches xml"); - final InputStreamResource resource4 = identifierService.exportMetadata(identifier); - log.debug("find identifier resulted in resource {}", resource4); - return ResponseEntity.ok(resource4); + return ResponseEntity.ok(identifierService.exportMetadata(identifier)); } final Pattern regex = Pattern.compile("text\\/bibliography(; ?style=(apa|ieee|bibtex))?"); final Matcher matcher = regex.matcher(accept); @@ -348,9 +329,9 @@ public class IdentifierEndpoint { throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, DataServiceConnectionException, IdentifierNotFoundException, ExternalServiceException { log.debug("endpoint publish identifier, identifierId={}", identifierId); - final Identifier identifier = identifierService.find(identifierId); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.identifierToIdentifierDto(identifierService.publish(identifier))); + .body(metadataMapper.identifierToIdentifierDto( + identifierService.publish(identifierService.find(identifierId)))); } @PutMapping("/{identifierId}") @@ -402,10 +383,10 @@ public class IdentifierEndpoint { log.debug("endpoint save identifier, identifierId={}, data.id={}, principal.name={}", identifierId, data.getId(), principal.getName()); final Database database = databaseService.findById(data.getDatabaseId()); - final User caller = userService.findByUsername(principal.getName()); + final User caller = userService.findById(getId(principal)); final Identifier identifier = identifierService.find(identifierId); /* check owner */ - if (!identifier.getOwner().getId().equals(caller.getId()) && !UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!identifier.getOwner().getId().equals(getId(principal)) && !hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to save identifier: foreign user"); throw new NotAllowedException("Failed to save identifier: foreign user"); } @@ -419,7 +400,7 @@ public class IdentifierEndpoint { final DatabaseAccess access = accessService.find(database, caller); log.trace("found access: {}", access); } catch (AccessNotFoundException e) { - if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to save identifier: insufficient role"); throw new NotAllowedException("Failed to save identifier: insufficient role"); } @@ -501,12 +482,12 @@ public class IdentifierEndpoint { IdentifierNotFoundException, ViewNotFoundException, ExternalServiceException { log.debug("endpoint create identifier, data.databaseId={}", data.getDatabaseId()); final Database database = databaseService.findById(data.getDatabaseId()); - final User caller = userService.findByUsername(principal.getName()); + final User caller = userService.findById(getId(principal)); /* check access */ try { accessService.find(database, caller); } catch (AccessNotFoundException e) { - if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to create identifier: insufficient role"); throw new NotAllowedException("Failed to create identifier: insufficient role"); } @@ -532,8 +513,9 @@ public class IdentifierEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<ExternalMetadataDto> retrieve(@NotNull @Valid @RequestParam String url) + public ResponseEntity<ExternalMetadataDto> retrieve(@NotNull @Valid @RequestParam("url") String url) throws OrcidNotFoundException, RorNotFoundException, DoiNotFoundException, IdentifierNotSupportedException { + log.debug("endpoint retrieve identifier, url={}", url); return ResponseEntity.ok(metadataService.findByUrl(url)); } 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/tuwien/endpoints/ImageEndpoint.java index 2a9dd568703c03932d3a2f20a57bb49b19433fbc..2aaad860a8bbb70e4d7023b00587cc0ad70b7e94 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/tuwien/endpoints/ImageEndpoint.java @@ -37,7 +37,7 @@ import java.util.List; @CrossOrigin(origins = "*") @ControllerAdvice @RequestMapping(path = "/api/image") -public class ImageEndpoint { +public class ImageEndpoint extends AbstractEndpoint { private final MetadataMapper metadataMapper; private final ImageServiceImpl imageService; @@ -97,11 +97,9 @@ public class ImageEndpoint { @NotNull Principal principal) throws ImageAlreadyExistsException, ImageInvalidException { log.debug("endpoint create image, data={}, principal.name={}", data, principal.getName()); - final ContainerImage image = imageService.create(data, principal); - final ImageDto dto = metadataMapper.containerImageToImageDto(image); - log.trace("create image resulted in image {}", dto); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.containerImageToImageDto( + imageService.create(data, principal))); } @GetMapping("/{imageId}") @@ -122,12 +120,9 @@ public class ImageEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<ImageDto> findById(@NotNull @PathVariable("imageId") Long imageId) throws ImageNotFoundException { - log.debug("endpoint find image, id={}", imageId); - final ContainerImage image = imageService.find(imageId); - final ImageDto dto = metadataMapper.containerImageToImageDto(image); - log.trace("find image resulted in image {}", dto); + log.debug("endpoint find image, imageId={}", imageId); return ResponseEntity.ok() - .body(dto); + .body(metadataMapper.containerImageToImageDto(imageService.find(imageId))); } @PutMapping("/{imageId}") @@ -152,13 +147,10 @@ public class ImageEndpoint { public ResponseEntity<ImageDto> update(@NotNull @PathVariable("imageId") Long imageId, @RequestBody @Valid ImageChangeDto changeDto) throws ImageNotFoundException { - log.debug("endpoint update image, id={}, changeDto={}", imageId, changeDto); - ContainerImage image = imageService.find(imageId); - image = imageService.update(image, changeDto); - final ImageDto dto = metadataMapper.containerImageToImageDto(image); - log.trace("update image resulted in image {}", dto); + log.debug("endpoint update image, imageId={}, changeDto={}", imageId, changeDto); return ResponseEntity.accepted() - .body(dto); + .body(metadataMapper.containerImageToImageDto( + imageService.update(imageService.find(imageId), changeDto))); } @DeleteMapping("/{imageId}") @@ -179,9 +171,8 @@ public class ImageEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> delete(@NotNull @PathVariable("imageId") Long imageId) throws ImageNotFoundException { - log.debug("endpoint delete image, id={}", imageId); - final ContainerImage image = imageService.find(imageId); - imageService.delete(image); + log.debug("endpoint delete image, imageId={}", imageId); + imageService.delete(imageService.find(imageId)); return ResponseEntity.accepted() .build(); } 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/tuwien/endpoints/LicenseEndpoint.java index 75998b03a5c239661a9f7b3022263a00cd0bff4d..18d5e93ca26a824f1b445e39fb82213b0f7fe649 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/tuwien/endpoints/LicenseEndpoint.java @@ -21,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; -import java.util.stream.Collectors; @Log4j2 @RestController @@ -52,12 +51,11 @@ public class LicenseEndpoint { }) public ResponseEntity<List<LicenseDto>> list() { log.debug("endpoint list licenses"); - final List<LicenseDto> licenses = licenseService.findAll() - .stream() - .map(metadataMapper::licenseToLicenseDto) - .toList(); return ResponseEntity.status(HttpStatus.OK) - .body(licenses); + .body(licenseService.findAll() + .stream() + .map(metadataMapper::licenseToLicenseDto) + .toList()); } } 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/tuwien/endpoints/MessageEndpoint.java index 0a1cddf5dfddbb4559cc4b608952da94b58cb901..0aeeac9401c796b82060d363a5e1ed01e6ac0e61 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/tuwien/endpoints/MessageEndpoint.java @@ -56,20 +56,15 @@ public class MessageEndpoint { }) public ResponseEntity<List<BannerMessageDto>> list(@RequestParam(required = false) Boolean active) { log.debug("endpoint list messages, active={}", active); - List<BannerMessageDto> dtos; + final List<BannerMessage> messages; if (active != null && active) { - dtos = bannerMessageService.getActive() - .stream() - .map(metadataMapper::bannerMessageToBannerMessageDto) - .toList(); + messages = bannerMessageService.getActive(); } else { - dtos = bannerMessageService.findAll() - .stream() - .map(metadataMapper::bannerMessageToBannerMessageDto) - .toList(); + messages = bannerMessageService.findAll(); } - log.info("List messages resulted in {} message(s)", dtos.size()); - return ResponseEntity.ok(dtos); + return ResponseEntity.ok(messages.stream() + .map(metadataMapper::bannerMessageToBannerMessageDto) + .toList()); } @GetMapping("/message/{messageId}") @@ -91,8 +86,8 @@ public class MessageEndpoint { public ResponseEntity<BannerMessageDto> find(@NotNull @PathVariable("messageId") Long messageId) throws MessageNotFoundException { log.debug("endpoint find one maintenance message, messageId={}", messageId); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.find(messageId)); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.find(messageId))); } @PostMapping @@ -110,10 +105,9 @@ public class MessageEndpoint { }) public ResponseEntity<BannerMessageDto> create(@Valid @RequestBody BannerMessageCreateDto data) { log.debug("endpoint create maintenance message, data={}", data); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.create(data)); - log.trace("create maintenance message results in dto {}", dto); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.create(data))); } @PutMapping("/{messageId}") @@ -139,10 +133,9 @@ public class MessageEndpoint { throws MessageNotFoundException { log.debug("endpoint update maintenance message, messageId={}, data={}", messageId, data); final BannerMessage message = bannerMessageService.find(messageId); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.update(message, data)); - log.trace("update maintenance message results in dto {}", dto); - return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(dto); + return ResponseEntity.accepted() + .body(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.update(message, data))); } @DeleteMapping("/{messageId}") @@ -166,7 +159,7 @@ public class MessageEndpoint { log.debug("endpoint delete maintenance message, messageId={}", messageId); final BannerMessage message = bannerMessageService.find(messageId); bannerMessageService.delete(message); - return ResponseEntity.status(HttpStatus.ACCEPTED) + return ResponseEntity.accepted() .build(); } 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/tuwien/endpoints/MetadataEndpoint.java index fbfd40e6289ef20d20ae2ade97b08b9e47f96d96..8a36471816ee9a4d2a89e3fee2edcde59f7361ae 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/tuwien/endpoints/MetadataEndpoint.java @@ -29,7 +29,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/oai") -public class MetadataEndpoint { +public class MetadataEndpoint extends AbstractEndpoint { private final MetadataService metadataService; 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/tuwien/endpoints/OntologyEndpoint.java index cd17c7ac0b15d014769683dadc660a426986cd9e..7bc6bc037e75501bfd7de5006150550a7a42366b 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/tuwien/endpoints/OntologyEndpoint.java @@ -3,9 +3,11 @@ package at.tuwien.endpoints; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.semantics.*; import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; +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.mapper.SparqlMapper; import at.tuwien.service.EntityService; import at.tuwien.service.OntologyService; import io.micrometer.observation.annotation.Observed; @@ -32,7 +34,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/ontology") -public class OntologyEndpoint { +public class OntologyEndpoint extends AbstractEndpoint { private final EntityService entityService; private final MetadataMapper metadataMapper; @@ -59,11 +61,10 @@ public class OntologyEndpoint { }) public ResponseEntity<List<OntologyBriefDto>> findAll() { log.debug("endpoint find all ontologies"); - final List<OntologyBriefDto> dtos = ontologyService.findAll() + return ResponseEntity.ok(ontologyService.findAll() .stream() .map(metadataMapper::ontologyToOntologyBriefDto) - .toList(); - return ResponseEntity.ok(dtos); + .toList()); } @GetMapping("/{ontologyId}") @@ -85,8 +86,7 @@ public class OntologyEndpoint { public ResponseEntity<OntologyDto> find(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { log.debug("endpoint find all ontologies, ontologyId={}", ontologyId); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.find(ontologyId)); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(metadataMapper.ontologyToOntologyDto(ontologyService.find(ontologyId))); } @PostMapping @@ -104,10 +104,9 @@ public class OntologyEndpoint { }) public ResponseEntity<OntologyDto> create(@NotNull @Valid @RequestBody OntologyCreateDto data, @NotNull Principal principal) { - log.debug("endpoint create ontology, data={}", data); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.create(data, principal)); + log.debug("endpoint create ontology, data={}, principal.name={}", data, principal.getName()); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.ontologyToOntologyDto(ontologyService.create(data, principal))); } @PutMapping("/{ontologyId}") @@ -131,11 +130,10 @@ public class OntologyEndpoint { public ResponseEntity<OntologyDto> update(@NotNull @PathVariable("ontologyId") Long ontologyId, @NotNull @Valid @RequestBody OntologyModifyDto data) throws OntologyNotFoundException { - log.debug("endpoint update ontology, data={}", data); - final Ontology ontology = ontologyService.find(ontologyId); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.update(ontology, data)); + log.debug("endpoint update ontology, ontologyId={}, data={}", ontologyId, data); return ResponseEntity.accepted() - .body(dto); + .body(metadataMapper.ontologyToOntologyDto( + ontologyService.update(ontologyService.find(ontologyId), data))); } @DeleteMapping("/{ontologyId}") @@ -158,8 +156,7 @@ public class OntologyEndpoint { public ResponseEntity<Void> delete(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { log.debug("endpoint delete ontology, ontologyId={}", ontologyId); - final Ontology ontology = ontologyService.find(ontologyId); - ontologyService.delete(ontology); + ontologyService.delete(ontologyService.find(ontologyId)); return ResponseEntity.accepted() .build(); } @@ -217,15 +214,12 @@ public class OntologyEndpoint { throw new OntologyNotFoundException("Failed to find SPARQL endpoint for ontology with id " + ontology.getId()); } /* get */ - final List<EntityDto> dtos; if (uri != null) { - dtos = entityService.findByUri(uri); return ResponseEntity.ok() - .body(dtos); + .body(entityService.findByUri(uri)); } - dtos = entityService.findByLabel(ontology, label); return ResponseEntity.ok() - .body(dtos); + .body(entityService.findByLabel(ontology, label)); } } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 822581bb991786467123b7adde5e35c1e6cde6e2..9f4542fc023f8aaf336fc2de196d0c36ab93cea4 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -11,12 +11,9 @@ 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.entities.database.table.columns.TableColumn; -import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -46,7 +43,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/database/{databaseId}/table") -public class TableEndpoint { +public class TableEndpoint extends AbstractEndpoint { private final UserService userService; private final TableService tableService; @@ -73,7 +70,7 @@ public class TableEndpoint { @Transactional(readOnly = true) @Observed(name = "dbrepo_tables_findall") @Operation(summary = "List tables", - description = "Lists all tables known to the metadata database.", + description = "Lists all tables known to the metadata database. When a database has a hidden schema (i.e. when `is_schema_public` is `false`), then the user needs to have at least read access and the role `list-tables`.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -97,14 +94,13 @@ public class TableEndpoint { DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException { log.debug("endpoint list tables, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - endpointValidator.validateOnlyPrivateAccess(database, principal); - endpointValidator.validateOnlyPrivateHasRole(database, principal, "list-tables"); - final List<TableBriefDto> dto = database.getTables() + endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); + endpointValidator.validateOnlyPrivateSchemaHasRole(database, principal, "list-tables"); + return ResponseEntity.ok(database.getTables() .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic()) .map(metadataMapper::tableToTableBriefDto) - .collect(Collectors.toList()); - log.trace("list tables resulted in tables {}", dto); - return ResponseEntity.ok(dto); + .collect(Collectors.toList())); } @GetMapping("/{tableId}/suggest") @@ -154,7 +150,7 @@ public class TableEndpoint { principal); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - if (!table.getOwner().getUsername().equals(principal.getName())) { + if (!table.getOwner().getId().equals(getId(principal))) { log.error("Failed to analyse table semantics: not owner"); throw new NotAllowedException("Failed to analyse table semantics: not owner"); } @@ -207,7 +203,7 @@ public class TableEndpoint { principal.getName()); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - if (!table.getOwner().getUsername().equals(principal.getName())) { + if (!table.getOwner().getId().equals(getId(principal)) && !isSystem(principal)) { log.error("Failed to update table statistics: not owner"); throw new NotAllowedException("Failed to update table statistics: not owner"); } @@ -266,19 +262,14 @@ public class TableEndpoint { log.debug("endpoint update table, databaseId={}, tableId={}, columnId={}, principal.name={}", databaseId, tableId, columnId, principal.getName()); final Database database = databaseService.findById(databaseId); - final User user = userService.findByUsername(principal.getName()); final Table table = tableService.findById(database, tableId); - if (!UserUtil.hasRole(principal, "modify-foreign-table-column-semantics")) { - endpointValidator.validateOnlyAccess(table.getDatabase(), principal, true); - endpointValidator.validateOnlyOwnerOrWriteAll(table, user); + if (!hasRole(principal, "modify-foreign-table-column-semantics")) { + endpointValidator.validateOnlyAccess(database, principal, true); + endpointValidator.validateOnlyOwnerOrWriteAll(table, userService.findById(getId(principal))); } - TableColumn column = tableService.findColumnById(table, columnId); - column = tableService.update(column, updateDto); - log.info("Updated table semantics of table with id {}", tableId); - final ColumnDto columnDto = metadataMapper.tableColumnToColumnDto(column); - log.trace("find table data resulted in column {}", columnDto); return ResponseEntity.accepted() - .body(columnDto); + .body(metadataMapper.tableColumnToColumnDto(tableService.update( + tableService.findColumnById(table, columnId), updateDto))); } @GetMapping("/{tableId}/column/{columnId}/suggest") @@ -317,12 +308,10 @@ public class TableEndpoint { throws MalformedException, TableNotFoundException, DatabaseNotFoundException { log.debug("endpoint analyse table column semantics, databaseId={}, tableId={}, columnId={}, principal.name={}", databaseId, tableId, columnId, principal.getName()); - final Database database = databaseService.findById(databaseId); - final Table table = tableService.findById(database, tableId); - TableColumn column = tableService.findColumnById(table, columnId); - final List<TableColumnEntityDto> dtos = entityService.suggestByColumn(column); return ResponseEntity.ok() - .body(dtos); + .body(entityService.suggestByColumn( + tableService.findColumnById( + tableService.findById(databaseService.findById(databaseId), tableId), columnId))); } @PostMapping @@ -380,11 +369,9 @@ public class TableEndpoint { final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyAccess(database, principal, true); endpointValidator.validateColumnCreateConstraints(data); - final Table table = tableService.createTable(database, data, principal); - final TableDto dto = metadataMapper.customTableToTableDto(table); - log.info("Created table with id {}", dto.getId()); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.customTableToTableDto( + tableService.createTable(database, data, principal))); } @PutMapping("/{tableId}") @@ -436,21 +423,20 @@ public class TableEndpoint { databaseId, data.getIsPublic(), data.getIsSchemaPublic(), principal.getName()); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - if (!table.getOwner().getUsername().equals(principal.getName())) { + if (!table.getOwner().getId().equals(getId(principal))) { log.error("Failed to update table: not owner"); throw new NotAllowedException("Failed to update table: not owner"); } - final TableDto dto = metadataMapper.customTableToTableDto(tableService.updateTable(table, data)); - log.info("Updated table with id {}", dto.getId()); - return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(dto); + return ResponseEntity.accepted() + .body(metadataMapper.customTableToTableDto( + tableService.updateTable(table, data))); } @GetMapping("/{tableId}") @Transactional(readOnly = true) @Observed(name = "dbrepo_tables_find") @Operation(summary = "Find table", - description = "Finds a table with id. When the `system` role is present, the endpoint responds with additional connection metadata in the header.", + description = "Finds a table with id. When a table is hidden (i.e. when `is_public` is `false`), then the user needs to have at least read access and the role `find-table`. When the `system` role is present, the endpoint responds with additional connection metadata in the header.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -490,29 +476,32 @@ public class TableEndpoint { public ResponseEntity<TableDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, Principal principal) throws DataServiceException, - DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, QueueNotFoundException { + DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, QueueNotFoundException, + UserNotFoundException, NotAllowedException, AccessNotFoundException { log.debug("endpoint find table, databaseId={}, tableId={}", databaseId, tableId); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - boolean hasAccess = UserUtil.isSystem(principal); boolean isOwner = false; - try { - if (principal != null) { - final User user = userService.findByUsername(principal.getName()); - accessService.find(table.getDatabase(), user); - hasAccess = true; - isOwner = table.getOwner().getId().equals(user.getId()); + 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"); + } + } } - } catch (UserNotFoundException | AccessNotFoundException e) { - /* ignore */ } - final boolean includeSchema = UserUtil.isSystem(principal) || isOwner || table.getIsSchemaPublic(); - log.trace("user has access: {}", hasAccess); - log.trace("include schema in mapping: {}", includeSchema); - final TableDto dto = metadataMapper.customTableToTableDto(table, hasAccess, table.getDatabase().getIsPublic(), - includeSchema); + if (!table.getIsSchemaPublic() && !isOwner && !isSystem(principal)) { + log.debug("remove schema from table: {}.{}", database.getInternalName(), table.getInternalName()); + table.setColumns(List.of()); + table.setConstraints(null); + } final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); headers.set("X-Host", table.getDatabase().getContainer().getHost()); @@ -522,9 +511,9 @@ public class TableEndpoint { headers.set("X-Table", table.getInternalName()); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table"); } - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity.ok() .headers(headers) - .body(dto); + .body(metadataMapper.customTableToTableDto(table)); } @DeleteMapping("/{tableId}") @@ -573,7 +562,7 @@ public class TableEndpoint { final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); /* roles */ - if (!table.getOwner().getUsername().equals(principal.getName()) && !UserUtil.hasRole(principal, "delete-foreign-table")) { + if (!table.getOwner().getId().equals(getId(principal)) && !hasRole(principal, "delete-foreign-table")) { log.error("Failed to delete table: not owned by current user"); throw new NotAllowedException("Failed to delete table: not owned by current user"); } 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/tuwien/endpoints/UnitEndpoint.java index c992f151b5a32bafaf62a85a1a930ffbe7d0bdbe..45aef3645ba93cb1298c6da2e658656f645778ed 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/tuwien/endpoints/UnitEndpoint.java @@ -14,7 +14,10 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -22,7 +25,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/unit") -public class UnitEndpoint { +public class UnitEndpoint extends AbstractEndpoint { private final UnitService unitService; private final MetadataMapper metadataMapper; @@ -47,12 +50,11 @@ public class UnitEndpoint { }) public ResponseEntity<List<UnitDto>> findAll() { log.debug("endpoint list units"); - final List<UnitDto> dtos = unitService.findAll() - .stream() - .map(metadataMapper::tableColumnUnitToUnitDto) - .toList(); return ResponseEntity.ok() - .body(dtos); + .body(unitService.findAll() + .stream() + .map(metadataMapper::tableColumnUnitToUnitDto) + .toList()); } } 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/tuwien/endpoints/UserEndpoint.java index 151169c2446f2bc699cb108f56623fbb6a6a3fba..5a349ff3782f1c94a4aea6f4d609f3402437b9c0 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/tuwien/endpoints/UserEndpoint.java @@ -16,7 +16,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AuthenticationService; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -44,7 +43,7 @@ import java.util.UUID; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/user") -public class UserEndpoint { +public class UserEndpoint extends AbstractEndpoint { private final UserService userService; private final MetadataMapper userMapper; @@ -64,7 +63,7 @@ public class UserEndpoint { @Transactional(readOnly = true) @Observed(name = "dbrepo_users_list") @Operation(summary = "List users", - description = "Lists users known to the metadata database.") + description = "Lists users known to the metadata database. Internal users are omitted from the result list. If the optional query parameter `username` is present, the result list can be filtered by matching this exact username.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "List users", @@ -77,12 +76,17 @@ public class UserEndpoint { if (username == null) { return ResponseEntity.ok(userService.findAll() .stream() + .filter(user -> !user.getIsInternal()) .map(userMapper::userToUserBriefDto) .toList()); } + log.trace("filter by username: {}", username); try { - log.trace("filter by username: {}", username); - return ResponseEntity.ok(List.of(userMapper.userToUserBriefDto(userService.findByUsername(username)))); + final User user = userService.findByUsername(username); + if (user.getIsInternal()) { + return ResponseEntity.ok(List.of()); + } + return ResponseEntity.ok(List.of(userMapper.userToUserBriefDto(user))); } catch (UserNotFoundException e) { log.trace("filter by username {} failed: return empty list", username); return ResponseEntity.ok(List.of()); @@ -141,16 +145,15 @@ public class UserEndpoint { log.debug("endpoint create user, data.username={}", data.getUsername()); userService.validateUsernameNotExists(data.getUsername()); userService.validateEmailNotExists(data.getEmail()); - final User user = userService.create(data, authenticationService.create(data).getAttributes().getLdapId()[0]); - log.info("Created user with id: {}", user.getId()); return ResponseEntity.status(HttpStatus.CREATED) - .body(userMapper.userToUserDto(user)); + .body(userMapper.userToUserDto( + userService.create(data, authenticationService.create(data).getAttributes().getLdapId()[0]))); } @PostMapping("/token") @Observed(name = "dbrepo_user_token") @Operation(summary = "Create token", - description = "Creates a user token via the auth service.") + description = "Creates a user token via the Auth Service.") @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Obtained user token", @@ -193,7 +196,6 @@ public class UserEndpoint { AccountNotSetupException { log.debug("endpoint get token, data.username={}", data.getUsername()); /* check */ - final TokenDto token = authenticationService.obtainToken(data); try { userService.findByUsername(data.getUsername()); } catch (UserNotFoundException e) { @@ -213,7 +215,7 @@ public class UserEndpoint { log.info("Patched missing user information for user with username: {}", data.getUsername()); } return ResponseEntity.accepted() - .body(token); + .body(authenticationService.obtainToken(data)); } @PutMapping("/token") @@ -246,9 +248,8 @@ public class UserEndpoint { throws AuthServiceConnectionException, CredentialsInvalidException { log.debug("endpoint refresh token"); /* check */ - final TokenDto token = authenticationService.refreshToken(data.getRefreshToken()); return ResponseEntity.accepted() - .body(token); + .body(authenticationService.refreshToken(data.getRefreshToken())); } @GetMapping("/{userId}") @@ -256,7 +257,7 @@ public class UserEndpoint { @PreAuthorize("isAuthenticated()") @Observed(name = "dbrepo_user_find") @Operation(summary = "Get user", - description = "Gets user with id from the metadata database. Requires authentication.", + description = "Gets own user information from the metadata database. Requires authentication. Foreign user information can only be obtained if additional role `find-foreign-user` is present. Finding information about internal users results in a 404 error.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -281,21 +282,21 @@ public class UserEndpoint { log.debug("endpoint find a user, userId={}, principal.name={}", userId, principal.getName()); /* check */ final User user = userService.findById(userId); - if (!user.getUsername().equals(principal.getName())) { - if (!UserUtil.hasRole(principal, "find-foreign-user")) { - log.error("Failed to find user: foreign user"); - throw new NotAllowedException("Failed to find user: foreign user"); - } + if (!user.getId().equals(getId(principal)) && !hasRole(principal, "find-foreign-user")) { + log.error("Failed to find user: foreign user"); + throw new NotAllowedException("Failed to find user: foreign user"); + } + if (user.getIsInternal()) { + throw new UserNotFoundException("Failed to find user with username: " + user.getUsername()); } - final UserDto dto = userMapper.userToUserDto(user); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", user.getUsername()); headers.set("X-Password", user.getMariadbPassword()); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(dto); + .body(userMapper.userToUserDto(user)); } @PutMapping("/{userId}") @@ -333,13 +334,13 @@ public class UserEndpoint { UserNotFoundException, DatabaseNotFoundException { log.debug("endpoint modify a user, userId={}, data={}", userId, data); final User user = userService.findById(userId); - if (!user.getUsername().equals(principal.getName())) { + if (!user.getId().equals(getId(principal))) { log.error("Failed to modify user: not current user {}", user.getId()); throw new NotAllowedException("Failed to modify user: not current user " + user.getId()); } - final UserDto dto = userMapper.userToUserDto(userService.modify(user, data)); return ResponseEntity.accepted() - .body(dto); + .body(userMapper.userToUserDto( + userService.modify(user, data))); } @PutMapping("/{userId}/password") @@ -383,14 +384,14 @@ public class UserEndpoint { @NotNull Principal principal) throws NotAllowedException, AuthServiceException, AuthServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, DataServiceException, DataServiceConnectionException, CredentialsInvalidException { - log.debug("endpoint modify a user password, userId={}", userId); + log.debug("endpoint modify a user password, userId={}, principal.name={}", userId, principal.getName()); final User user = userService.findById(userId); if (!user.getUsername().equals(principal.getName())) { log.error("Failed to modify user password: not current user"); throw new NotAllowedException("Failed to modify user password: not current user"); } authenticationService.updatePassword(user, data); - for (Database database : databaseService.findAllAccess(userId)) { + for (Database database : databaseService.findAllAtLestReadAccess(userId)) { databaseService.updatePassword(database, user); } userService.updatePassword(user, data); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 012206289e19f654cb8154668aee2dac598b61b0..8a4a087da20e4578a40801ac670a7ed5a3826521 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -13,7 +13,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; import at.tuwien.service.ViewService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -42,7 +41,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/database/{databaseId}/view") -public class ViewEndpoint { +public class ViewEndpoint extends AbstractEndpoint { private final UserService userService; private final ViewService viewService; @@ -81,13 +80,16 @@ public class ViewEndpoint { DatabaseNotFoundException { log.debug("endpoint find all views, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User user = principal != null ? userService.findByUsername(principal.getName()) : null; - log.trace("find all views for database {}", database); - final List<ViewBriefDto> views = viewService.findAll(database, user) + final User caller; + if (principal != null) { + caller = userService.findById(getId(principal)); + } else { + caller = null; + } + return ResponseEntity.ok(viewService.findAll(database, caller) .stream() .map(metadataMapper::viewToViewBriefDto) - .collect(Collectors.toList()); - return ResponseEntity.ok(views); + .collect(Collectors.toList())); } @PostMapping @@ -141,17 +143,14 @@ public class ViewEndpoint { UserNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to create view: not the database owner"); throw new NotAllowedException("Failed to create view: not the database owner"); } log.trace("create view for database {}", database); - final View view; - view = viewService.create(database, caller, data); - final ViewBriefDto dto = metadataMapper.viewToViewBriefDto(view); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.viewToViewBriefDto( + viewService.create(database, userService.findById(getId(principal)), data))); } @GetMapping("/{viewId}") @@ -193,13 +192,13 @@ public class ViewEndpoint { final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { - headers.set("X-Username", view.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", view.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Host", view.getDatabase().getContainer().getHost()); - headers.set("X-Port", "" + view.getDatabase().getContainer().getPort()); - headers.set("X-Type", view.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("X-Database", view.getDatabase().getInternalName()); + if (isSystem(principal)) { + headers.set("X-Username", database.getContainer().getPrivilegedUsername()); + headers.set("X-Password", database.getContainer().getPrivilegedPassword()); + headers.set("X-Host", database.getContainer().getHost()); + headers.set("X-Port", "" + database.getContainer().getPort()); + headers.set("X-Type", database.getContainer().getImage().getJdbcMethod()); + headers.set("X-Database", database.getInternalName()); headers.set("X-View", view.getInternalName()); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View"); } @@ -253,10 +252,10 @@ public class ViewEndpoint { @NotNull @PathVariable("viewId") Long viewId, @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, UserNotFoundException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); - if (!database.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to delete view: not the database owner {}", database.getOwner().getId()); throw new NotAllowedException("Failed to delete view: not the database owner " + database.getOwner().getId()); } @@ -307,16 +306,17 @@ public class ViewEndpoint { @NotNull @Valid @RequestBody ViewUpdateDto data, @NotNull Principal principal) throws NotAllowedException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, UserNotFoundException { log.debug("endpoint update view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); - if (!database.getOwner().getUsername().equals(principal.getName()) && !view.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().getId().equals(getId(principal)) && !view.getOwner().getId().equals(getId(principal))) { 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"); } return ResponseEntity.accepted() - .body(metadataMapper.viewToViewDto(viewService.update(database, view, data))); + .body(metadataMapper.viewToViewDto( + viewService.update(database, view, data))); } } 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/tuwien/validation/EndpointValidator.java index 70f2e4e420eb104b7e76caaa702ed23850fe9565..1f7c391bd2ef63d49ed1acd5255409a1564af0ca 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/tuwien/validation/EndpointValidator.java @@ -5,6 +5,7 @@ import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; 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; @@ -13,7 +14,6 @@ import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import lombok.extern.log4j.Log4j2; import org.apache.commons.validator.GenericValidator; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +27,7 @@ import java.util.Optional; @Log4j2 @Component -public class EndpointValidator { +public class EndpointValidator extends AbstractEndpoint { public static final List<ColumnTypeDto> NEED_NOTHING = List.of(ColumnTypeDto.BOOL, ColumnTypeDto.SERIAL); public static final List<ColumnTypeDto> NEED_SIZE = List.of(ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY); @@ -43,7 +43,7 @@ public class EndpointValidator { this.accessService = accessService; } - public void validateOnlyPrivateAccess(Database database, Principal principal, boolean writeAccessOnly) + public void validateOnlyPrivateDataAccess(Database database, Principal principal, boolean writeAccessOnly) throws NotAllowedException, UserNotFoundException, AccessNotFoundException { if (database.getIsPublic()) { log.trace("database with id {} is public: no access needed", database.getId()); @@ -52,9 +52,23 @@ public class EndpointValidator { validateOnlyAccess(database, principal, writeAccessOnly); } - public void validateOnlyPrivateAccess(Database database, Principal principal) throws NotAllowedException, + public void validateOnlyPrivateSchemaAccess(Database database, Principal principal, boolean writeAccessOnly) + throws NotAllowedException, UserNotFoundException, AccessNotFoundException { + if (database.getIsSchemaPublic()) { + log.trace("database schema with id {} is public: no access needed", database.getId()); + return; + } + validateOnlyAccess(database, principal, writeAccessOnly); + } + + public void validateOnlyPrivateDataAccess(Database database, Principal principal) throws NotAllowedException, UserNotFoundException, AccessNotFoundException { - validateOnlyPrivateAccess(database, principal, false); + validateOnlyPrivateDataAccess(database, principal, false); + } + + public void validateOnlyPrivateSchemaAccess(Database database, Principal principal) throws NotAllowedException, + UserNotFoundException, AccessNotFoundException { + validateOnlyPrivateSchemaAccess(database, principal, false); } public void validateOnlyAccess(Database database, Principal principal, boolean writeAccessOnly) @@ -62,8 +76,10 @@ public class EndpointValidator { if (principal == null) { throw new NotAllowedException("No principal provided"); } - final User user = userService.findByUsername(principal.getName()); - final DatabaseAccess access = accessService.find(database, user); + if (isSystem(principal)) { + return; + } + final DatabaseAccess access = accessService.find(database, userService.findById(getId(principal))); log.trace("found access: {}", access); if (writeAccessOnly && !(access.getType().equals(AccessType.WRITE_OWN) || access.getType().equals(AccessType.WRITE_ALL))) { log.error("Access not allowed: no write access"); @@ -167,7 +183,7 @@ public class EndpointValidator { } public boolean validateOnlyMineOrWriteAccessOrHasRole(User owner, Principal principal, DatabaseAccess access, String role) { - if (UserUtil.hasRole(principal, role)) { + if (hasRole(principal, role)) { log.debug("validation passed: role {} present", role); return true; } @@ -222,7 +238,7 @@ public class EndpointValidator { throw new NotAllowedException("Access not allowed: insufficient access (neither owner nor write-all access)"); } - public void validateOnlyPrivateHasRole(Database database, Principal principal, String role) + public void validateOnlyPrivateDataHasRole(Database database, Principal principal, String role) throws NotAllowedException { if (database.getIsPublic()) { log.trace("database with id {} is public: no access needed", database.getId()); @@ -234,7 +250,26 @@ public class EndpointValidator { throw new NotAllowedException("Access not allowed: no authorization provided"); } log.trace("principal: {}", principal.getName()); - if (!UserUtil.hasRole(principal, role)) { + if (!hasRole(principal, role)) { + log.error("Access not allowed: role {} missing", role); + throw new NotAllowedException("Access not allowed: role " + role + " missing"); + } + log.trace("principal has role '{}': access granted", role); + } + + public void validateOnlyPrivateSchemaHasRole(Database database, Principal principal, String role) + throws NotAllowedException { + if (database.getIsSchemaPublic()) { + log.trace("database with id {} has public schema: no access needed", database.getId()); + return; + } + log.trace("database with id {} has private schema", database.getId()); + if (principal == null) { + log.error("Access not allowed: no authorization provided"); + throw new NotAllowedException("Access not allowed: no authorization provided"); + } + log.trace("principal: {}", principal.getName()); + if (!hasRole(principal, role)) { log.error("Access not allowed: role {} missing", role); throw new NotAllowedException("Access not allowed: role " + role + " missing"); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java index b788fd206b962c89644d2f0e6802b1a15282627a..11d64faf8b9562ff42ab2120d5f6fa151710d462 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java @@ -110,15 +110,12 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(containerService.find(CONTAINER_1_ID)) .thenReturn(CONTAINER_1); - when(databaseService.create(CONTAINER_1, request, USER_1)) - .thenReturn(DATABASE_1); - doNothing() - .when(messageQueueService) - .setVirtualHostPermissions(USER_1); - when(keycloakGateway.findByUsername(USER_1_USERNAME)) - .thenReturn(USER_1_KEYCLOAK_DTO); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); + when(userService.findAllInternalUsers()) + .thenReturn(List.of(USER_LOCAL)); + when(databaseService.create(CONTAINER_1, request, USER_1, List.of(USER_LOCAL))) + .thenReturn(DATABASE_1); /* test */ create_generic(request, USER_1_PRINCIPAL, USER_1); @@ -136,7 +133,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(containerService.find(CONTAINER_4_ID)) .thenReturn(CONTAINER_4); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -174,7 +171,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); when(databaseService.updateTableMetadata(any(Database.class))) .thenReturn(DATABASE_1); @@ -195,7 +192,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); when(databaseService.updateTableMetadata(any(Database.class))) .thenReturn(DATABASE_1); @@ -215,7 +212,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); when(databaseService.updateViewMetadata(any(Database.class))) .thenReturn(DATABASE_1); @@ -233,7 +230,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); /* test */ @@ -249,7 +246,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -265,7 +262,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -276,51 +273,68 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void list_anonymous_succeeds() throws DatabaseNotFoundException { + public void list_anonymous_succeeds() throws DatabaseNotFoundException, UserNotFoundException { - /* pre-condition */ - assertFalse(DATABASE_1_PUBLIC); + /* mock */ + when(databaseService.findAllPublicOrSchemaPublic()) + .thenReturn(List.of(DATABASE_1)); /* test */ - list_generic(List.of(DATABASE_1), null); + list_generic(null, null, 1); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRole_succeeds() throws DatabaseNotFoundException { + public void list_hasRole_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); + /* mock */ + when(databaseService.findAllPublicOrSchemaPublicOrReadAccess(any(UUID.class))) + .thenReturn(List.of(DATABASE_3)); + /* test */ - list_generic(List.of(DATABASE_3), null); + list_generic(null, USER_1_PRINCIPAL, 1); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleForeign_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleForeign_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); + /* mock */ + when(databaseService.findAllPublicOrSchemaPublicOrReadAccess(USER_1_ID)) + .thenReturn(List.of(DATABASE_3)); + /* test */ - list_generic(List.of(DATABASE_3), null); + list_generic(null, USER_1_PRINCIPAL, 1); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilter_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleFilter_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + + /* mock */ + when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, DATABASE_3_INTERNALNAME)) + .thenReturn(List.of(DATABASE_3)); /* test */ - list_generic(List.of(DATABASE_3), DATABASE_3_INTERNALNAME); + list_generic(DATABASE_3_INTERNALNAME, USER_1_PRINCIPAL, 1); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilterNoResult_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleFilterNoResult_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + + /* mock */ + when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, "i_do_not_exist")) + .thenReturn(List.of()); /* test */ - list_generic(List.of(), "i_do_not_exist"); + list_generic("i_do_not_exist", USER_1_PRINCIPAL, 0); } @Test @@ -348,7 +362,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(keycloakGateway.findByUsername(USER_1_USERNAME)) .thenReturn(USER_1_KEYCLOAK_DTO); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -376,7 +390,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .build(); /* mock */ - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); /* test */ @@ -408,7 +422,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_3_ID)) .thenReturn(DATABASE_3); - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); /* test */ @@ -429,7 +443,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); when(storageService.getBytes(request.getKey())) .thenReturn(new byte[]{1, 2, 3, 4, 5}); @@ -450,7 +464,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -480,7 +494,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); when(userService.findById(USER_4_ID)) .thenReturn(USER_4); @@ -505,7 +519,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1); when(keycloakGateway.findByUsername(USER_1_USERNAME)) .thenReturn(USER_1_KEYCLOAK_DTO); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); when(userService.findById(USER_4_ID)) .thenReturn(USER_4); @@ -536,11 +550,12 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_anonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + public void findById_anonymous_fails() { /* test */ - findById_generic(DATABASE_1_ID, DATABASE_1, null); + assertThrows(NotAllowedException.class, () -> { + findById_generic(DATABASE_1_ID, DATABASE_1, null); + }); } @Test @@ -556,7 +571,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_hasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -568,7 +583,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_hasRoleForeign_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -580,7 +595,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_ownerSeesAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* mock */ when(accessService.list(DATABASE_1)) @@ -643,28 +658,15 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void list_generic(List<Database> databases, String internalName) throws DatabaseNotFoundException { - - /* mock */ - when(databaseService.findAll()) - .thenReturn(databases); - if (internalName != null) { - if (!databases.isEmpty()) { - when(databaseService.findByInternalName(internalName)) - .thenReturn(databases.get(0)); - } else { - doThrow(DatabaseNotFoundException.class) - .when(databaseService) - .findByInternalName(internalName); - } - } + public void list_generic(String internalName, Principal principal, Integer expectedSize) + throws DatabaseNotFoundException, UserNotFoundException { /* test */ - final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName); + final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); final List<DatabaseBriefDto> body = response.getBody(); - assertEquals(databases.size(), body.size()); + assertEquals(expectedSize, body.size()); } public void create_generic(DatabaseCreateDto data, Principal principal, User user) throws DataServiceException, @@ -709,7 +711,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public DatabaseDto findById_generic(Long databaseId, Database database, Principal principal) throws DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, - DataServiceException, UserNotFoundException { + DataServiceException, UserNotFoundException, NotAllowedException { /* 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/tuwien/endpoints/IdentifierEndpointUnitTest.java index ce560cb646342f627a3e78d09a11f77a59c1223f..74a252c5a63572e569a1e7b8379637e2d34dc03d 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/tuwien/endpoints/IdentifierEndpointUnitTest.java @@ -1089,7 +1089,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { throws UserNotFoundException { /* mock */ - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); /* test */ @@ -1163,7 +1163,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); when(accessService.find(DATABASE_1, USER_1)) .thenReturn(DATABASE_1_USER_1_READ_ACCESS); @@ -1185,7 +1185,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_1_USERNAME)) + when(userService.findById(USER_1_ID)) .thenReturn(USER_1); doThrow(AccessNotFoundException.class) .when(accessService) @@ -1209,7 +1209,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(DATABASE_1_ID)) .thenReturn(DATABASE_1); - when(userService.findByUsername(USER_2_USERNAME)) + when(userService.findById(USER_2_ID)) .thenReturn(USER_2); doThrow(AccessNotFoundException.class) .when(accessService) @@ -1270,7 +1270,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { } when(identifierService.find(identifier.getId())) .thenReturn(identifier); - when(userService.findByUsername(principal.getName())) + when(userService.findById(user.getId())) .thenReturn(user); when(databaseService.findById(databaseId)) .thenReturn(database); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index dcc10f61a70ef663f0b4427c60f1acefba8f58ed..ef06d7f37fd01373df24be3c27f95919850b9fae 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -101,11 +101,21 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void list_publicAnonymous_succeeds() throws NotAllowedException, UserNotFoundException, + public void list_publicDataPrivateSchemaAnonymous_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_list(DATABASE_3_ID, DATABASE_3, null, null, null); + }); + } + + @Test + @WithAnonymousUser + public void list_publicDataPublicSchemaAnonymous_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ - generic_list(DATABASE_3_ID, DATABASE_3, null, null, null); + generic_list(DATABASE_4_ID, DATABASE_4, null, null, null); } @Test @@ -132,10 +142,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void list_publicNoRole_succeeds() throws NotAllowedException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException { + public void list_publicDataPrivateSchemaNoRole_fails() { /* test */ - generic_list(DATABASE_3_ID, DATABASE_3, USER_4_PRINCIPAL, USER_4, null); + assertThrows(NotAllowedException.class, () -> { + generic_list(DATABASE_3_ID, DATABASE_3, USER_4_PRINCIPAL, USER_4, null); + }); } @Test @@ -511,12 +523,24 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_publicAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + public void findById_publicDatabasePrivateDataPrivateSchemaAnonymous_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { /* test */ - generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); + final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); + final TableDto body = response.getBody(); + assertNull(body.getConstraints()); + assertEquals(List.of(), body.getColumns()); + } + + @Test + @WithAnonymousUser + public void findById_publicDataPublicSchemaAnonymous_succeeds() throws DataServiceException, + DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, + QueueNotFoundException, UserNotFoundException, NotAllowedException { + + /* test */ + generic_findById(DATABASE_4_ID, DATABASE_4, TABLE_9_ID, TABLE_9, null, null, null); } @Test @@ -543,7 +567,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") public void findById_publicHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + UserNotFoundException, NotAllowedException { /* 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); @@ -556,7 +580,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_4_USERNAME) public void findById_publicNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + UserNotFoundException, NotAllowedException { /* test */ generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, null); @@ -898,12 +922,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_privateAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + public void findById_privateDatabasePrivateDataPublicSchemaAnonymous_fails() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { /* test */ - generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, null, null, null); + generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, null, null, null); } @Test @@ -930,7 +954,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") public void findById_privateHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + UserNotFoundException, NotAllowedException { /* 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); @@ -941,9 +965,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_privateNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException { + public void findById_privateDatabasePrivateDataPrivateSchemaNoRole_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { /* test */ generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL, USER_4, null); @@ -980,13 +1004,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-foreign-table"}) + @WithMockUser(username = USER_5_USERNAME, authorities = {"delete-foreign-table"}) public void delete_foreign_succeeds() throws NotAllowedException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, DataServiceException { /* test */ - generic_delete(USER_2_PRINCIPAL, TABLE_1); + generic_delete(USER_5_PRINCIPAL, TABLE_1); } @Test @@ -1132,7 +1156,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ if (principal != null) { - when(userService.findByUsername(principal.getName())) + when(userService.findById(user.getId())) .thenReturn(user); } if (database != null) { @@ -1160,7 +1184,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { Table table, Principal principal, User user, DatabaseAccess access) throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, - QueueNotFoundException, UserNotFoundException { + QueueNotFoundException, UserNotFoundException, NotAllowedException { /* mock */ if (database != null) { @@ -1180,7 +1204,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .findById(any(Database.class), eq(tableId)); } if (principal != null) { - when(userService.findByUsername(principal.getName())) + when(userService.findById(user.getId())) .thenReturn(user); when(accessService.find(any(Database.class), eq(user))) .thenReturn(access); @@ -1231,7 +1255,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } if (principal != null) { log.trace("mock user {}", user); - when(userService.findByUsername(principal.getName())) + when(userService.findById(user.getId())) .thenReturn(user); } if (access != null) { 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/tuwien/endpoints/UserEndpointUnitTest.java index 54cef2ca4b1e08b2feacc94cc00781687a5e8881..be0ea28c496d9c3bd65df14f8a312af5c9003069 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/tuwien/endpoints/UserEndpointUnitTest.java @@ -192,7 +192,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .build(); /* test */ @@ -208,7 +208,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .build(); /* test */ @@ -224,7 +224,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .build(); /* test */ @@ -240,7 +240,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .build(); /* test */ @@ -512,7 +512,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { doNothing() .when(userService) .updatePassword(USER_1, data); - when(databaseService.findAllAccess(USER_1_ID)) + when(databaseService.findAllAtLestReadAccess(USER_1_ID)) .thenReturn(List.of(DATABASE_1)); doNothing() .when(databaseService) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index ccd8b067de4d002a5f358f47734b85f86ff6cfc8..2815dd6c0557a31490dff959bcff7f60e559b805 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -214,9 +214,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-database-view"}) - public void delete_publicOwner_succeeds() throws NotAllowedException, DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, - SearchServiceException, SearchServiceConnectionException, ViewNotFoundException { + public void delete_publicOwner_succeeds() throws NotAllowedException, DataServiceException, UserNotFoundException, + DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, ViewNotFoundException, + SearchServiceException, SearchServiceConnectionException { /* 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); @@ -372,7 +372,7 @@ 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 { + SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { /* 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 +411,7 @@ 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 { + SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { /* test */ update_generic(USER_1_PRINCIPAL); @@ -429,7 +429,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { when(databaseService.findById(databaseId)) .thenReturn(database); if (principal != null) { - when(userService.findByUsername(user.getUsername())) + when(userService.findById(userId)) .thenReturn(user); } if (access != null) { @@ -471,7 +471,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { when(databaseService.findById(databaseId)) .thenReturn(database); if (principal != null) { - when(userService.findByUsername(principal.getName())) + when(userService.findById(userId)) .thenReturn(user); } if (access != null) { @@ -511,7 +511,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { .thenThrow(AccessNotFoundException.class); } if (principal != null) { - when(userService.findByUsername(principal.getName())) + when(userService.findById(userId)) .thenReturn(user); when(viewService.findById(any(Database.class), anyLong())) .thenReturn(VIEW_1); @@ -531,7 +531,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void delete_generic(Long databaseId, Database database, Long viewId, View view, Principal principal, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, - SearchServiceException, SearchServiceConnectionException, ViewNotFoundException { + SearchServiceException, SearchServiceConnectionException, ViewNotFoundException, UserNotFoundException { /* mock */ when(databaseService.findById(databaseId)) @@ -556,7 +556,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void update_generic(Principal principal) throws SearchServiceException, NotAllowedException, DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, - ViewNotFoundException { + ViewNotFoundException, UserNotFoundException { final ViewUpdateDto request = ViewUpdateDto.builder() .isPublic(true) .isSchemaPublic(true) 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/tuwien/gateway/BrokerServiceGatewayUnitTest.java index fc2a9c2c220c4fa601138ee9ee8333d3cd67f493..32a8c8b1907c816d4000e544b2ec0e9d7e8a01fc 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/tuwien/gateway/BrokerServiceGatewayUnitTest.java @@ -113,7 +113,7 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { @Test public void grantVirtualHostPermission_invalidResponseCode2_fails() { - final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<Void> mock = ResponseEntity.accepted() .build(); /* mock */ 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/tuwien/gateway/DataServiceGatewayUnitTest.java index 698f7ed524c13bbb3d9fbe5fca37003419f51a4c..daeb1c1a96340323c85ca15080a3bc9d2685823e 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/tuwien/gateway/DataServiceGatewayUnitTest.java @@ -116,7 +116,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -184,7 +184,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -322,7 +322,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -502,7 +502,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -653,7 +653,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ 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/tuwien/gateway/SearchServiceGatewayUnitTest.java index aa1c9d4f056f61680aeb341f2cebafdbe262a2b5..b1ce21d4e5e8315b08087dc0d85712509a07973e 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/tuwien/gateway/SearchServiceGatewayUnitTest.java @@ -37,7 +37,7 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { @Test public void update_succeeds() throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { - final ResponseEntity<DatabaseDto> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<DatabaseDto> mock = ResponseEntity.accepted() .build(); /* mock */ @@ -109,7 +109,7 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { @Test public void delete_succeeds() throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { - final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<Void> mock = ResponseEntity.accepted() .build(); /* mock */ 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/tuwien/mapper/MetadataMapperUnitTest.java index fb574f35cae9dd3f3e10ae53be29d2d2b87aa8ff..9b778e67fb3243e238053972add0f3522c07b9d6 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/tuwien/mapper/MetadataMapperUnitTest.java @@ -1,15 +1,15 @@ package at.tuwien.mapper; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.identifier.IdentifierTypeDto; import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.identifier.*; +import at.tuwien.entities.identifier.Identifier; +import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -24,7 +24,6 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.List; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -73,49 +72,6 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(IdentifierType.DATABASE, metadataMapper.identifierTypeDtoToIdentifierType(IdentifierTypeDto.DATABASE)); } - @Test - public void identifierCreateDtoToIdentifier_succeeds() { - - /* test */ - final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_1_CREATE_DTO); - assertNotNull(response.getTitles()); - 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_TITLE_1_LANG, title0.getLanguage()); - assertEquals(IDENTIFIER_1_TITLE_1_TYPE, title0.getTitleType()); - final IdentifierTitle title1 = titles.get(1); - assertEquals(IDENTIFIER_1_TITLE_2_TITLE, title1.getTitle()); - assertEquals(IDENTIFIER_1_TITLE_2_LANG, title1.getLanguage()); - assertEquals(IDENTIFIER_1_TITLE_2_TYPE, title1.getTitleType()); - assertNotNull(response.getDescriptions()); - assertEquals(1, response.getDescriptions().size()); - final List<IdentifierDescription> descriptions = response.getDescriptions(); - final IdentifierDescription description0 = descriptions.get(0); - assertNull(description0.getId()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION, description0.getDescription()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_LANG, description0.getLanguage()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_TYPE, description0.getDescriptionType()); - assertNotNull(response.getCreators()); - assertEquals(1, response.getCreators().size()); - final Creator creator0 = response.getCreators().get(0); - assertNotNull(creator0); - assertNull(creator0.getId()); - assertEquals(IDENTIFIER_1_CREATOR_1_FIRSTNAME, creator0.getFirstname()); - assertEquals(IDENTIFIER_1_CREATOR_1_LASTNAME, creator0.getLastname()); - assertEquals(IDENTIFIER_1_CREATOR_1_NAME, creator0.getCreatorName()); - assertEquals(IDENTIFIER_1_CREATOR_1_ORCID, creator0.getNameIdentifier()); - assertEquals(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE, creator0.getNameIdentifierScheme()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION, creator0.getAffiliation()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER, creator0.getAffiliationIdentifier()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME, creator0.getAffiliationIdentifierScheme()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI, creator0.getAffiliationIdentifierSchemeUri()); - assertNotNull(response.getFunders()); - assertEquals(1, response.getFunders().size()); - assertNull(response.getRelatedIdentifiers()); /* mapstruct strategy for empty values is to set null */ - } - @Test public void identifierCreateDtoToIdentifier_withDoi_succeeds() { @@ -142,73 +98,6 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(IDENTIFIER_2_TYPE, response.getType()); } - @Test - public void identifierCreateDtoToIdentifier_view_succeeds() { - - /* test */ - final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_3_CREATE_DTO); - assertNull(response.getDatabase()); - assertNull(response.getQueryId()); - assertNull(response.getTableId()); - assertEquals(IDENTIFIER_3_VIEW_ID, response.getViewId()); - assertNull(response.getDoi()); - assertEquals(IDENTIFIER_3_TYPE, response.getType()); - } - - @Test - public void customDatabaseToDatabaseDto_succeeds() { - - /* test */ - final DatabaseDto response = metadataMapper.customDatabaseToDatabaseDto(DATABASE_1, USER_1); - assertEquals(DATABASE_1_ID, response.getId()); - assertNotNull(response.getContact()); - assertEquals(USER_1_ID, response.getContact().getId()); - assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); - assertEquals(DATABASE_1_SCHEMA_PUBLIC, response.getIsSchemaPublic()); - /* identifiers formatted */ - assertEquals(4, response.getIdentifiers().size()); - final IdentifierBriefDto identifier1 = response.getIdentifiers().get(0); - assertEquals(DATABASE_1_ID, identifier1.getDatabaseId()); - final IdentifierBriefDto identifier2 = response.getIdentifiers().get(1); - assertEquals(DATABASE_1_ID, identifier2.getDatabaseId()); - final IdentifierBriefDto identifier3 = response.getIdentifiers().get(2); - assertEquals(DATABASE_1_ID, identifier3.getDatabaseId()); - final IdentifierBriefDto identifier4 = response.getIdentifiers().get(3); - assertEquals(DATABASE_1_ID, identifier4.getDatabaseId()); - /* Table 1 formatted */ - final TableBriefDto table0 = response.getTables().get(0); - assertEquals(TABLE_1_ID, table0.getId()); - assertEquals(TABLE_1_NAME, table0.getName()); - assertEquals(TABLE_1_INTERNAL_NAME, table0.getInternalName()); - assertEquals(TABLE_1_DESCRIPTION, table0.getDescription()); - assertEquals(DATABASE_1_ID, table0.getDatabaseId()); - assertEquals(TABLE_1_SCHEMA_PUBLIC, table0.getIsSchemaPublic()); - /* Table 2 formatted */ - final TableBriefDto table1 = response.getTables().get(1); - assertEquals(TABLE_2_ID, table1.getId()); - assertEquals(TABLE_2_NAME, table1.getName()); - assertEquals(TABLE_2_INTERNALNAME, table1.getInternalName()); - assertEquals(TABLE_2_DESCRIPTION, table1.getDescription()); - assertEquals(DATABASE_1_ID, table1.getDatabaseId()); - assertEquals(TABLE_2_SCHEMA_PUBLIC, table1.getIsSchemaPublic()); - /* Table 3 formatted */ - final TableBriefDto table2 = response.getTables().get(2); - assertEquals(TABLE_3_ID, table2.getId()); - assertEquals(TABLE_3_NAME, table2.getName()); - assertEquals(TABLE_3_INTERNALNAME, table2.getInternalName()); - assertEquals(TABLE_3_DESCRIPTION, table2.getDescription()); - assertEquals(DATABASE_1_ID, table2.getDatabaseId()); - assertEquals(TABLE_3_SCHEMA_PUBLIC, table2.getIsSchemaPublic()); - /* Table 4 formatted */ - final TableBriefDto table3 = response.getTables().get(3); - assertEquals(TABLE_4_ID, table3.getId()); - assertEquals(TABLE_4_NAME, table3.getName()); - assertEquals(TABLE_4_INTERNALNAME, table3.getInternalName()); - assertEquals(TABLE_4_DESCRIPTION, table3.getDescription()); - assertEquals(DATABASE_1_ID, table3.getDatabaseId()); - assertEquals(TABLE_4_SCHEMA_PUBLIC, table3.getIsSchemaPublic()); - } - public static Stream<Arguments> nameToInternalName_parameters() { return Stream.of( Arguments.arguments("dash_minus", "OE/NO-027", "oe_no_027"), @@ -235,61 +124,104 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { } @Test - public void userEquals_identity_succeeds() { + public void userToUserBriefDto_succeeds() { /* test */ - assertEquals(USER_1_DTO, USER_1_DTO); + final UserBriefDto response = metadataMapper.userToUserBriefDto(USER_1); + assertEquals(USER_1_NAME, response.getName()); + assertEquals(USER_1_NAME + " — @" + USER_1_USERNAME, response.getQualifiedName()); } @Test - public void userEquals_similar_succeeds() { - final UserDto tmp = UserDto.builder() - .id(USER_1_ID) - .build(); + public void userToUserDto_succeeds() { /* test */ - assertEquals(USER_1_DTO, tmp); + assertEquals(USER_1_DTO, metadataMapper.userToUserDto(USER_1)); + assertEquals(USER_2_DTO, metadataMapper.userToUserDto(USER_2)); + assertEquals(USER_3_DTO, metadataMapper.userToUserDto(USER_3)); + assertEquals(USER_4_DTO, metadataMapper.userToUserDto(USER_4)); + assertEquals(USER_5_DTO, metadataMapper.userToUserDto(USER_5)); } @Test - public void userToUserBriefDto_succeeds() { + public void identifierToIdentifierDto_succeeds() { /* test */ - final UserBriefDto response = metadataMapper.userToUserBriefDto(USER_1); - assertEquals(USER_1_NAME, response.getName()); - assertEquals(USER_1_NAME + " — @" + USER_1_USERNAME, response.getQualifiedName()); + assertEquals(IDENTIFIER_1_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_1)); + assertEquals(IDENTIFIER_2_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_2)); + assertEquals(IDENTIFIER_3_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_3)); + assertEquals(IDENTIFIER_4_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_4)); + assertEquals(IDENTIFIER_5_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_5)); + assertEquals(IDENTIFIER_6_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_6)); + assertEquals(IDENTIFIER_7_DTO, metadataMapper.identifierToIdentifierDto(IDENTIFIER_7)); } @Test - public void userToUserDto_succeeds() { + public void viewToViewDto_succeeds() { /* test */ - final UserDto response = metadataMapper.userToUserDto(USER_1); - assertEquals(USER_1_NAME, response.getName()); - assertEquals(USER_1_NAME + " — @" + USER_1_USERNAME, response.getQualifiedName()); + assertEquals(VIEW_1_DTO, metadataMapper.viewToViewDto(VIEW_1)); + assertEquals(VIEW_2_DTO, metadataMapper.viewToViewDto(VIEW_2)); + assertEquals(VIEW_3_DTO, metadataMapper.viewToViewDto(VIEW_3)); + assertEquals(VIEW_4_DTO, metadataMapper.viewToViewDto(VIEW_4)); + assertEquals(VIEW_5_DTO, metadataMapper.viewToViewDto(VIEW_5)); } @Test - public void viewToViewDto_succeeds() { + public void tableToTableBriefDto_succeeds() { + + /* test */ + assertEquals(TABLE_1_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_1)); + assertEquals(TABLE_2_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_2)); + assertEquals(TABLE_3_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_3)); + assertEquals(TABLE_4_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_4)); + assertEquals(TABLE_5_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_5)); + assertEquals(TABLE_6_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_6)); + assertEquals(TABLE_7_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_7)); + assertEquals(TABLE_8_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_8)); + assertEquals(TABLE_9_BRIEF_DTO, metadataMapper.tableToTableBriefDto(TABLE_9)); + } + + @Test + public void containerToContainerBriefDto_succeeds() { + + /* test */ + assertEquals(CONTAINER_1_BRIEF_DTO, metadataMapper.containerToContainerBriefDto(CONTAINER_1)); + } + + @Test + public void bannerMessageToBannerMessageDto_succeeds() { + + /* test */ + assertEquals(BANNER_MESSAGE_1_DTO, metadataMapper.bannerMessageToBannerMessageDto(BANNER_MESSAGE_1)); + } + + @Test + public void containerImageToImageBriefDto_succeeds() { + + /* test */ + assertEquals(IMAGE_1_BRIEF_DTO, metadataMapper.containerImageToImageBriefDto(IMAGE_1)); + } + + @Test + public void containerImageToImageDto_succeeds() { + + /* test */ + assertEquals(IMAGE_1_DTO, metadataMapper.containerImageToImageDto(IMAGE_1)); + } + + @Test + public void ontologyToOntologyBriefDto_succeeds() { + + /* test */ + assertEquals(ONTOLOGY_1_BRIEF_DTO, metadataMapper.ontologyToOntologyBriefDto(ONTOLOGY_1)); + } + + @Test + public void ontologyToOntologyDto_succeeds() { /* test */ - final ViewDto response = metadataMapper.viewToViewDto(VIEW_1); - assertEquals(VIEW_1_ID, response.getId()); - assertEquals(VIEW_1_DATABASE_ID, response.getVdbid()); - assertEquals(VIEW_1_NAME, response.getName()); - assertEquals(VIEW_1_INTERNAL_NAME, response.getInternalName()); - assertNotNull(response.getDatabase()); - assertEquals(VIEW_1_DATABASE_ID, response.getDatabase().getId()); - assertEquals(VIEW_1_QUERY, response.getQuery()); - assertEquals(VIEW_1_QUERY_HASH, response.getQueryHash()); - assertNotNull(response.getIdentifiers()); - assertEquals(1, response.getIdentifiers().size()); - final IdentifierDto identifier0 = response.getIdentifiers().get(0); - assertEquals(IDENTIFIER_3_ID, identifier0.getId()); - assertEquals(VIEW_1_DATABASE_ID, identifier0.getDatabaseId()); - assertEquals(VIEW_1_ID, identifier0.getViewId()); - assertEquals(VIEW_1_QUERY, identifier0.getQuery()); - assertEquals(VIEW_1_QUERY_HASH, identifier0.getQueryHash()); + assertEquals(ONTOLOGY_1_DTO, metadataMapper.ontologyToOntologyDto(ONTOLOGY_1)); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java index 3f69453649dac695a7939ffe2881eb02d855c79d..eec5aebf4bea668164c51bae655c074cb306e4c2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java @@ -1,5 +1,6 @@ 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; @@ -8,6 +9,8 @@ import at.tuwien.repository.ContainerRepository; import at.tuwien.repository.DatabaseRepository; import at.tuwien.repository.LicenseRepository; import at.tuwien.repository.UserRepository; +import at.tuwien.service.AuthenticationService; +import at.tuwien.service.UserService; import at.tuwien.test.AbstractUnitTest; import at.tuwien.utils.KeycloakUtils; import dasniko.testcontainers.keycloak.KeycloakContainer; @@ -18,7 +21,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -28,10 +30,8 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import java.util.List; -import java.util.Optional; -import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 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.header; @@ -65,8 +65,11 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest @Autowired private DatabaseRepository databaseRepository; + @Autowired + private AuthenticationService authenticationService; + @Container - private static KeycloakContainer keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:24.0") + private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) .withImagePullPolicy(PullPolicy.alwaysPull()) .withAdminUsername("admin") .withAdminPassword("admin") @@ -88,10 +91,11 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest databaseRepository.save(DATABASE_1); /* keycloak */ keycloakUtils.deleteUser(USER_1_USERNAME); + keycloakUtils.deleteUser(USER_LOCAL_ADMIN_USERNAME); } @Test - public void findById_database_basicUser_fails() throws Exception { + public void findById_database_basicUser_succeeds() throws Exception { /* mock */ keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); @@ -108,11 +112,11 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest @Test public void findById_database_basicAdmin_succeeds() throws Exception { - /* mock */ - keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + /* pre condition */ + keycloakGateway.createUser(USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST); /* test */ - this.mockMvc.perform(get("/api/database/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + this.mockMvc.perform(get("/api/database/1").with(httpBasic(USER_LOCAL_ADMIN_USERNAME, USER_LOCAL_ADMIN_PASSWORD))) .andDo(print()) .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) @@ -123,11 +127,14 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest } @Test - @WithMockUser(username = "admin", authorities = {"system"}) public void findById_database_bearerAdmin_succeeds() throws Exception { + /* pre condition */ + keycloakGateway.createUser(USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST); + final TokenDto jwt = authenticationService.obtainToken(USER_LOCAL_ADMIN_LOGIN_REQUEST_DTO); + /* test */ - this.mockMvc.perform(get("/api/database/1")) + this.mockMvc.perform(get("/api/database/1").header("Authorization", "Bearer " + jwt.getAccessToken())) .andDo(print()) .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) @@ -138,51 +145,15 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest } @Test - public void findById_table_basicUser_fails() throws Exception { - - /* mock */ - keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); - - /* test */ - this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) - .andDo(print()) - .andExpect(header().doesNotExist("X-Username")) - .andExpect(header().doesNotExist("X-Password")) - .andExpect(header().doesNotExist("X-Host")) - .andExpect(header().doesNotExist("X-Port")) - .andExpect(header().doesNotExist("X-Type")) - .andExpect(header().doesNotExist("X-Database")) - .andExpect(header().doesNotExist("X-Table")) - .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) - .andExpect(status().isOk()); - } - - @Test - public void findById_table_basicAdmin_succeeds() throws Exception { + public void findById_table_bearerAdmin_succeeds() throws Exception { - /* mock */ - keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + /* pre condition */ + keycloakGateway.createUser(USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST); + final TokenDto jwt = authenticationService.obtainToken(USER_LOCAL_ADMIN_LOGIN_REQUEST_DTO); - /* test */ - this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) - .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("X-Host", CONTAINER_1_HOST)) - .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) - .andExpect(header().string("X-Type", IMAGE_1_JDBC)) - .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) - .andExpect(header().string("X-Table", TABLE_1_INTERNAL_NAME)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table")) - .andExpect(status().isOk()); - } - - @Test - @WithMockUser(username = "admin", authorities = {"system"}) - public void findById_table_bearerAdmin_succeeds() throws Exception { /* test */ - this.mockMvc.perform(get("/api/database/1/table/1")) + this.mockMvc.perform(get("/api/database/1/table/1").header("Authorization", "Bearer " + jwt.getAccessToken())) .andDo(print()) .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) @@ -196,13 +167,13 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest } @Test - public void findById_view_basicUser_fails() throws Exception { + public void findById_table_basicUser_succeeds() throws Exception { /* mock */ keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); /* test */ - this.mockMvc.perform(get("/api/database/1/view/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) .andExpect(header().doesNotExist("X-Username")) .andExpect(header().doesNotExist("X-Password")) @@ -210,37 +181,19 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest .andExpect(header().doesNotExist("X-Port")) .andExpect(header().doesNotExist("X-Type")) .andExpect(header().doesNotExist("X-Database")) - .andExpect(header().doesNotExist("X-View")) + .andExpect(header().doesNotExist("X-Table")) .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } @Test - public void findById_view_basicAdmin_succeeds() throws Exception { + public void findById_table_basicAdmin_succeeds() throws Exception { /* mock */ - keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); - - /* test */ - this.mockMvc.perform(get("/api/database/1/view/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) - .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("X-Host", CONTAINER_1_HOST)) - .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) - .andExpect(header().string("X-Type", IMAGE_1_JDBC)) - .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) - .andExpect(header().string("X-View", VIEW_1_INTERNAL_NAME)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View")) - .andExpect(status().isOk()); - } - - @Test - @WithMockUser(username = "admin", authorities = {"system"}) - public void findById_view_bearerAdmin_succeeds() throws Exception { + keycloakGateway.createUser(USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST); /* test */ - this.mockMvc.perform(get("/api/database/1/view/1")) + this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_LOCAL_ADMIN_USERNAME, USER_LOCAL_ADMIN_PASSWORD))) .andDo(print()) .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) @@ -248,51 +201,43 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) .andExpect(header().string("X-Type", IMAGE_1_JDBC)) .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) - .andExpect(header().string("X-View", VIEW_1_INTERNAL_NAME)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View")) + .andExpect(header().string("X-Table", TABLE_1_INTERNAL_NAME)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table")) .andExpect(status().isOk()); } @Test - public void findById_container_basicUser_fails() throws Exception { + public void findById_view_basicUser_succeeds() throws Exception { /* mock */ keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); /* test */ - this.mockMvc.perform(get("/api/container/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + this.mockMvc.perform(get("/api/database/1/view/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) .andExpect(header().doesNotExist("X-Username")) .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("X-Host")) + .andExpect(header().doesNotExist("X-Port")) + .andExpect(header().doesNotExist("X-Type")) + .andExpect(header().doesNotExist("X-Database")) + .andExpect(header().doesNotExist("X-View")) .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } @Test - public void findById_container_basicAdmin_succeeds() throws Exception { + public void findById_container_basicUser_succeeds() throws Exception { /* mock */ - keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); /* test */ this.mockMvc.perform(get("/api/container/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) - .andExpect(status().isOk()); - } - - @Test - @WithMockUser(username = "admin", authorities = {"system"}) - public void findById_container_bearerAdmin_succeeds() throws Exception { - - /* test */ - this.mockMvc.perform(get("/api/container/1")) - .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) + .andExpect(header().doesNotExist("X-Username")) + .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .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/tuwien/mvc/IdentifierEndpointMvcTest.java index e4cdcdbdd884a3a1f28f0a20a244824f6ac3702c..2594eb70b1240d7ba39c866e2ee8c900cf191ea7 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/tuwien/mvc/IdentifierEndpointMvcTest.java @@ -42,7 +42,7 @@ public class IdentifierEndpointMvcTest extends AbstractUnitTest { .thenReturn(ORCID_1_DTO); /* test */ - this.mockMvc.perform(get("/api/identifier/retrieve?url=http://orcid.org/" + USER_1_ORCID_UNCOMPRESSED) + this.mockMvc.perform(get("/api/identifier/retrieve?url=" + USER_1_ORCID_URL) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(content().string(FileUtils.getContentsAsString(new File("src/test/resources/json/ext_orcid_jdoe.json")))) 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/tuwien/mvc/PrometheusEndpointMvcTest.java index 578f6276c791ab8465b46f115acc05ace1b7e948..5ae4aad0187cc52749416bdb3208d3ff678d5285 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/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -202,7 +202,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* mock */ try { - databaseEndpoint.list(null); + databaseEndpoint.list(null, null); } 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/tuwien/service/AccessServiceUnitTest.java index 54015177aaff7d3e52a98b5c2db7103a8c272fc1..c647cdbd7403b5f5c742953fd9978e0c8d98ab06 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/tuwien/service/AccessServiceUnitTest.java @@ -81,7 +81,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .thenReturn(ResponseEntity.status(HttpStatus.CREATED) .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -228,10 +228,10 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -301,7 +301,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.BadRequest.class) .when(searchServiceRestTemplate) @@ -320,7 +320,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.Unauthorized.class) .when(searchServiceRestTemplate) @@ -339,7 +339,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.NotFound.class) .when(searchServiceRestTemplate) @@ -358,7 +358,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpServerErrorException.InternalServerError.class) .when(searchServiceRestTemplate) @@ -380,10 +380,10 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -441,7 +441,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.BadRequest.class) .when(searchServiceRestTemplate) @@ -462,7 +462,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.Unauthorized.class) .when(searchServiceRestTemplate) @@ -483,7 +483,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.NotFound.class) .when(searchServiceRestTemplate) @@ -504,7 +504,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpServerErrorException.InternalServerError.class) .when(searchServiceRestTemplate) 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/tuwien/service/DatabaseServicePersistenceTest.java index bda2fc0ee5b103393a14b32b4244018c242d3f5a..9c91084f77cdac6c554cb11ea847bbb447185283 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/tuwien/service/DatabaseServicePersistenceTest.java @@ -1,5 +1,6 @@ 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; @@ -64,11 +65,42 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void findByInternalName_succeeds() throws DatabaseNotFoundException { + public void findAllPublicOrSchemaPublicByInternalName_succeeds() { /* test */ - final Database response = databaseService.findByInternalName(DATABASE_1_INTERNALNAME); - assertEquals(DATABASE_1, response); + final List<Database> response = databaseService.findAllPublicOrSchemaPublicByInternalName(DATABASE_3_INTERNALNAME); + assertEquals(1, response.size()); + assertEquals(DATABASE_3, response.get(0)); + } + + @Test + @Transactional(readOnly = true) + 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); + assertEquals(0, response.size()); + } + + @Test + @Transactional(readOnly = true) + public void findAllAtLestReadAccess_privateAccess_succeeds() { + + /* test */ + final List<Database> response = databaseService.findAllAtLestReadAccess(USER_2_ID); + assertEquals(3, response.size()); + assertEquals(DATABASE_4, response.get(0)); + assertEquals(DATABASE_2, response.get(1)); + assertEquals(DATABASE_1, response.get(2)); } } 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/tuwien/service/DatabaseServiceUnitTest.java index 7815c4ae69a98c5dfd5171e1c83cd9fdb6de0a72..1b6570abd821337fe032bead021cf9d5a4b9fc8c 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/tuwien/service/DatabaseServiceUnitTest.java @@ -87,25 +87,12 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { }); } - @Test - public void findByInternalName_notFound_fails() { - - /* mock */ - when(databaseRepository.findByInternalName(DATABASE_1_INTERNALNAME)) - .thenReturn(Optional.empty()); - - /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - databaseService.findByInternalName(DATABASE_1_INTERNALNAME); - }); - } - @Test public void updatePassword_succeeds() throws DataServiceException, DatabaseNotFoundException, DataServiceConnectionException { /* mock */ - when(databaseRepository.findReadAccess(USER_1_ID)) + when(databaseRepository.findAllAtLestReadAccessDesc(USER_1_ID)) .thenReturn(List.of(DATABASE_1)); doNothing() .when(dataServiceGateway) @@ -535,7 +522,7 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1); /* test */ - final Database response = databaseService.create(CONTAINER_1, DATABASE_1_CREATE, USER_1); + final Database response = databaseService.create(CONTAINER_1, DATABASE_1_CREATE, USER_1, List.of(USER_LOCAL)); assertTrue(response.getInternalName().startsWith(DATABASE_1_INTERNALNAME)); assertNotNull(response.getContainer()); assertNotNull(response.getTables()); 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/tuwien/utils/KeycloakUtils.java index 49694e6fd1dc49eb0f4bc8df35f1b6cd4965bf5e..f5ad18b694081ed50b879d6690e2a85748b3bece 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/tuwien/utils/KeycloakUtils.java @@ -1,18 +1,13 @@ package at.tuwien.utils; -import at.tuwien.api.keycloak.RoleRepresentationDto; -import at.tuwien.exception.*; +import at.tuwien.exception.AuthServiceConnectionException; +import at.tuwien.exception.AuthServiceException; +import at.tuwien.exception.UserNotFoundException; import at.tuwien.gateway.KeycloakGateway; -import at.tuwien.gateway.impl.KeycloakGatewayImpl; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.*; import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; -import java.util.List; import java.util.UUID; @Log4j2 @@ -28,8 +23,7 @@ public class KeycloakUtils { this.keycloakGateway = keycloakGateway; } - public void deleteUser(String username) throws AuthServiceException, AuthServiceConnectionException, - CredentialsInvalidException { + public void deleteUser(String username) throws AuthServiceException, AuthServiceConnectionException { try { final UUID userId = keycloakGateway.findByUsername(username).getId(); keycloakGateway.deleteUser(userId); 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/tuwien/validator/EndpointValidatorUnitTest.java index 29718b0962c76b8b1ad01ef003de092459d92714..342a9e328ecc8e69abe7bfedf1827bdc7777fff3 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/tuwien/validator/EndpointValidatorUnitTest.java @@ -324,20 +324,38 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { } @Test - public void validateOnlyPrivateHasRole_privatePrincipalMissing_fails() { + public void validateOnlyPrivateDataHasRole_privatePrincipalMissing_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - endpointValidator.validateOnlyPrivateHasRole(DATABASE_1, null, "list-tables"); + endpointValidator.validateOnlyPrivateDataHasRole(DATABASE_1, null, "list-tables"); }); } @Test - public void validateOnlyPrivateHasRole_privateRoleMissing_fails() { + public void validateOnlyPrivateDataHasRole_privateRoleMissing_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { - endpointValidator.validateOnlyPrivateHasRole(DATABASE_1, USER_4_PRINCIPAL, "list-tables"); + endpointValidator.validateOnlyPrivateDataHasRole(DATABASE_1, USER_4_PRINCIPAL, "list-tables"); + }); + } + + @Test + public void validateOnlyPrivateSchemaHasRole_privatePrincipalMissing_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + endpointValidator.validateOnlyPrivateSchemaHasRole(DATABASE_1, null, "list-tables"); + }); + } + + @Test + public void validateOnlyPrivateSchemaHasRole_privateRoleMissing_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + endpointValidator.validateOnlyPrivateSchemaHasRole(DATABASE_1, USER_4_PRINCIPAL, "list-tables"); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json b/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json index 588053e15fa6d5872c4cb83da42d71859b5f7a64..7ee28b34a4f2d662bb43979930732dec74da8a63 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json +++ b/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json @@ -37,6 +37,7 @@ "editUsernameAllowed" : false, "bruteForceProtected" : false, "permanentLockout" : false, + "maxTemporaryLockouts" : 0, "maxFailureWaitSeconds" : 900, "minimumQuickLoginWaitSeconds" : 60, "waitIncrementSeconds" : 60, @@ -1096,34 +1097,34 @@ "id" : "f2ce17fe-7b15-47a4-bbf8-86f415298fa9", "name" : "data-stewards", "path" : "/data-stewards", + "subGroups" : [ ], "attributes" : { }, "realmRoles" : [ "default-data-steward-roles" ], - "clientRoles" : { }, - "subGroups" : [ ] + "clientRoles" : { } }, { "id" : "124d9888-0b6e-46aa-8225-077dcedaf16e", "name" : "developers", "path" : "/developers", + "subGroups" : [ ], "attributes" : { }, "realmRoles" : [ "default-developer-roles" ], - "clientRoles" : { }, - "subGroups" : [ ] + "clientRoles" : { } }, { "id" : "f467c38e-9041-4faa-ae0b-39cec65ff4db", "name" : "researchers", "path" : "/researchers", + "subGroups" : [ ], "attributes" : { }, "realmRoles" : [ "default-researcher-roles" ], - "clientRoles" : { }, - "subGroups" : [ ] + "clientRoles" : { } }, { "id" : "2b9f94b4-d434-4a98-8eab-25678cfee983", "name" : "system", "path" : "/system", + "subGroups" : [ ], "attributes" : { }, "realmRoles" : [ "default-system-roles" ], - "clientRoles" : { }, - "subGroups" : [ ] + "clientRoles" : { } } ], "defaultRole" : { "id" : "abd2d9ee-ebc4-4d0a-839e-6b588a6d442a", @@ -1142,7 +1143,8 @@ "otpPolicyLookAheadWindow" : 1, "otpPolicyPeriod" : 30, "otpPolicyCodeReusable" : false, - "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName" ], + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, "webAuthnPolicyRpEntityName" : "keycloak", "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], "webAuthnPolicyRpId" : "", @@ -1153,6 +1155,7 @@ "webAuthnPolicyCreateTimeout" : 0, "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], "webAuthnPolicyPasswordlessRpId" : "", @@ -1163,6 +1166,7 @@ "webAuthnPolicyPasswordlessCreateTimeout" : 0, "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], "scopeMappings" : [ { "clientScope" : "rabbitmq.tag:administrator", "roles" : [ "escalated-broker-handling" ] @@ -1365,19 +1369,20 @@ "access.tokenResponse.claim" : "false" } }, { - "id" : "030a1cd9-53d1-4a62-a375-94d50a2dc6fc", + "id" : "0b4c644f-0cf0-4794-8395-d5d83009dabe", "name" : "uid", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { - "aggregate.attrs" : "false", - "multivalued" : "false", + "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "LDAP_ID", + "user.attribute" : "CUSTOM_ID", "id.token.claim" : "true", + "lightweight.claim" : "false", "access.token.claim" : "true", - "claim.name" : "uid" + "claim.name" : "uid", + "jsonType.label" : "String" } } ], "defaultClientScopes" : [ "roles", "attributes" ], @@ -2074,6 +2079,7 @@ "browserSecurityHeaders" : { "contentSecurityPolicyReportOnly" : "", "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", "xRobotsTag" : "none", "xFrameOptions" : "SAMEORIGIN", "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", @@ -2107,23 +2113,6 @@ "config" : { "allow-default-scopes" : [ "true" ] } - }, { - "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "f565cb47-3bcf-4078-8f94-eb4179c375b8", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } }, { "id" : "0efa669d-1017-4b4a-82e1-c2eaf72de2c9", "name" : "Allowed Client Scopes", @@ -2141,25 +2130,73 @@ "subComponents" : { }, "config" : { } }, { - "id" : "104ec5a9-025b-4c44-8ac0-82d22887ca3e", + "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", "name" : "Allowed Protocol Mapper Types", "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", + "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-address-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "saml-role-list-mapper" ] } }, { - "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", + "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "f565cb47-3bcf-4078-8f94-eb4179c375b8", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "104ec5a9-025b-4c44-8ac0-82d22887ca3e", "name" : "Allowed Protocol Mapper Types", "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper" ] + } + } ], + "org.keycloak.userprofile.UserProfileProvider" : [ { + "id" : "fb763636-e1ea-49c7-adca-ea105cdec4ad", + "providerId" : "declarative-user-profile", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper" ] + "kc.user.profile.config" : [ "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}],\"unmanagedAttributePolicy\":\"ENABLED\"}" ] } } ], "org.keycloak.keys.KeyProvider" : [ { + "id" : "2f53ccf3-37b0-4d34-83e7-ed497499ee51", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEA3b1tNLfcjFLUw9UShVDNf+ZD8sQqb4YBaIXcSJTX/zDQUPiCp176BBGI3s4VplDArnOW+LumozmKogeoHEnGEIDW8ovgK5uMU9tSA2p0qqGBUMOdR8YATTIfCJe7qGiiuGa3WZy3sQLM70SuRzx02YU8gvUcvl2Js4KyqAziOUX/w3Wa59H9jjGNUXYyqaPWJp73eHzbVYWySzyLG22mVlcUtBx5siL5T2/Xu0p9z4l7/bapwwmOVi1ZrcHjbEAwdGEiSMGI/uWqAF+r1BRpmJLR7HNXcL3eK4/56VYLaiwSejfyYeRFMITEn/UxGYhcXZ5xMUUCG0TxjBhLYpTBuwIDAQABAoIBAA4dwebcxkrH99Poa8+WkiE7JgaS9sahx9OBI2xwJANoIU2TpzGuNLQZ76uLgB+rPWZTD9Xm5a1iJjwOyQ9/937TzPCk91D0tpgcusRikb8jx/6TGB9acL4kBjYUVCCHr3BA2G75MKKGtJ2OMvAbCQSosZj+r2VDwYFEPUkV2jheE5JHSBkwyIRrus3JCwu8gu5fyCg9z8ljcxJxI5HIsi4v8Z21aCw/cLj7h5cMt44wCjQz4rOfYNBEFeHDtlfR1QtWKgjm4ZHHJbKrzf9b2kQXclziceEbSM0tYbROEXKi+s0Zc+z3HEG89vv0vfN400clmzzIAijKY6gg3pPRWdECgYEA+lnWYbSlXDMNYx6RBXm1RnlMUYIm4oy4/9ljgnoGJ6WCn3SjFkgaDtiKfGIG1BSB85r04pAPANgcWHf5tWDnq0ARvBVG0BX2bKd++7B3D4d3CRYKCwm88SslJXv9dfHVhq4+zViFPiUWwT20A72jCuUCvL88y5fh/YBecfdh+jECgYEA4r5RD0NB9dMaeg5/jk/GEHIo4Z9KLc6FrSoOFo2xFkPOy1sgDpDOiNtypuWvniO7k7Ose3DS3hlfTMsKzIW/CgQJ20+Y4cvBWDaOsRxfjj7w3d+jH5OSJdKKSzTrgLKc9ZhlRzVXy0J0hipIA6HG5kdVdLXmh85ITmf1CbJhE6sCgYBjPVeBNbXTHZ2x6/z62aslO5IoQVqetb/kE82hfDOSZcao5Ph9Lam+ttH2ynkAevykj4mBgi+gWwqpey2uW7KaLPSaxShj9kDQA3mP1fzsV/u0y1rB02Nlin/YIxVvOqU1FT9p8SwoXVVu1sHUNck62VtDbN9xqUx5S/ikXrclEQKBgQCoTssOwEcK+Vty9KYcdfy4onTUHZBLdjxl8Iyqkxy7QTQUYRznkvesQPDXEDGO+kk3dyx2KKZt9Hl4IFNww2quPZcvcuMx4DQxjbXXpA8OIIxcta95NepLJwA+mRai3nKCH1A2TlNP7pFeMa5o+8IPly3Ix2lKr4Wepa4PN5i1pwKBgCZ1QP6XAOERl9NznNmU0rXVcvYNP4PIIfQWfvGsldZ4QKkmjjAGiS0/oYqdWs+UDRZyCRChaVjDXO9fk0PEG5OGKAj9nyiYCT/M8xtJ3UeP5ffZZvJ/vnye3QdDIo1e38ZzsWwJHmLYw7fRqY9W5Vxo0Vsy22U3CJY70KTxVdTy" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICmzCCAYMCBgGG3GWycDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZkYnJlcG8wHhcNMjMwMzEzMTkxMzE3WhcNMzMwMzEzMTkxNDU3WjARMQ8wDQYDVQQDDAZkYnJlcG8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdvW00t9yMUtTD1RKFUM1/5kPyxCpvhgFohdxIlNf/MNBQ+IKnXvoEEYjezhWmUMCuc5b4u6ajOYqiB6gcScYQgNbyi+Arm4xT21IDanSqoYFQw51HxgBNMh8Il7uoaKK4ZrdZnLexAszvRK5HPHTZhTyC9Ry+XYmzgrKoDOI5Rf/DdZrn0f2OMY1RdjKpo9Ymnvd4fNtVhbJLPIsbbaZWVxS0HHmyIvlPb9e7Sn3PiXv9tqnDCY5WLVmtweNsQDB0YSJIwYj+5aoAX6vUFGmYktHsc1dwvd4rj/npVgtqLBJ6N/Jh5EUwhMSf9TEZiFxdnnExRQIbRPGMGEtilMG7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAK3kQ1VkQrzvSWvmXmazmNoA1ZiPzRDs1XhGUWxgsxzgPylr3dGBuqQbKvgnLUBQLSqlJHpI4fZflHswu1qrvVZYtekPcGef4WhcKAu2i1RwxrKa6RJQ1tRbrLuVYCzPv5p/DWgltWVn88aoLnqQn0SK/0PB/o4a4Cm7Kq2ZzCr1dACBr06LvOHsc7249OySmbG4HH+pLK6jVURhZ9VaObqAHe2FJBVVoIzURbdiRRURqumrIvbnpeaU1aFyg6ED5wTnXvmMPmVPt9F79mcB33bASO5wyu00X8t1hyN2Show2l2vxLACGUzVkTQt15s7uDLKE7qLmKSR3EuSGXWv3wA=" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "230cb681-9ceb-4b1b-8a4c-929a11b08de0", + "name" : "hmac-generated-hs512", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "8a489935-9a95-459b-9059-59b438ef0fa8" ], + "secret" : [ "xSCVgBlrLPWoF54gKQdR7BqXlfNaCD43xtS_ZgQRC0tGNAbqhy2Q9y8LdD2IR7K__8VGaDGYtyZayopgTebhDBb4gHDjDOBX7flhFYRrm0G3aTIuCIyFG-bPULwmyP_oHeC6tjwdQhqx5G0tE2mQQqPC9dDZuUA5I7QREIGK8cI" ], + "priority" : [ "100" ], + "algorithm" : [ "HS512" ] + } + }, { "id" : "28ca0b6d-b2e2-4785-b04b-2391e6344e30", "name" : "aes-generated", "providerId" : "aes-generated", @@ -2175,23 +2212,11 @@ "providerId" : "hmac-generated", "subComponents" : { }, "config" : { - "kid" : [ "c8500166-5cc4-4085-ad0f-853c3b0b0233" ], - "secret" : [ "TI3xg__G2Qy8C47DracpYir2X4ItQZSrhgr5KSlwRNISDbBqZ-ky3OcAyokSXMcpweSOaCPvbivpvzJNklUBvw" ], + "kid" : [ "5034d264-cb50-4006-a59e-2ce636eb5f38" ], + "secret" : [ "ToVIw-a4IE-Yp9JpP8ztb8NAICYO8CT3tUiDPT6DdiBcgzKJ9Ym9vspxGVdmPceX3mAgbnGLAcTx1PkInSVrbZs-tX9QXFwdlyGbewhKiNpH8wEg32Wk4GuUDpTv8JCsymgWyQBY681jvIMv05eCoK2QWpqCzcgP828KM5peCzo" ], "priority" : [ "100" ], "algorithm" : [ "HS256" ] } - }, { - "id" : "2f53ccf3-37b0-4d34-83e7-ed497499ee51", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEA3b1tNLfcjFLUw9UShVDNf+ZD8sQqb4YBaIXcSJTX/zDQUPiCp176BBGI3s4VplDArnOW+LumozmKogeoHEnGEIDW8ovgK5uMU9tSA2p0qqGBUMOdR8YATTIfCJe7qGiiuGa3WZy3sQLM70SuRzx02YU8gvUcvl2Js4KyqAziOUX/w3Wa59H9jjGNUXYyqaPWJp73eHzbVYWySzyLG22mVlcUtBx5siL5T2/Xu0p9z4l7/bapwwmOVi1ZrcHjbEAwdGEiSMGI/uWqAF+r1BRpmJLR7HNXcL3eK4/56VYLaiwSejfyYeRFMITEn/UxGYhcXZ5xMUUCG0TxjBhLYpTBuwIDAQABAoIBAA4dwebcxkrH99Poa8+WkiE7JgaS9sahx9OBI2xwJANoIU2TpzGuNLQZ76uLgB+rPWZTD9Xm5a1iJjwOyQ9/937TzPCk91D0tpgcusRikb8jx/6TGB9acL4kBjYUVCCHr3BA2G75MKKGtJ2OMvAbCQSosZj+r2VDwYFEPUkV2jheE5JHSBkwyIRrus3JCwu8gu5fyCg9z8ljcxJxI5HIsi4v8Z21aCw/cLj7h5cMt44wCjQz4rOfYNBEFeHDtlfR1QtWKgjm4ZHHJbKrzf9b2kQXclziceEbSM0tYbROEXKi+s0Zc+z3HEG89vv0vfN400clmzzIAijKY6gg3pPRWdECgYEA+lnWYbSlXDMNYx6RBXm1RnlMUYIm4oy4/9ljgnoGJ6WCn3SjFkgaDtiKfGIG1BSB85r04pAPANgcWHf5tWDnq0ARvBVG0BX2bKd++7B3D4d3CRYKCwm88SslJXv9dfHVhq4+zViFPiUWwT20A72jCuUCvL88y5fh/YBecfdh+jECgYEA4r5RD0NB9dMaeg5/jk/GEHIo4Z9KLc6FrSoOFo2xFkPOy1sgDpDOiNtypuWvniO7k7Ose3DS3hlfTMsKzIW/CgQJ20+Y4cvBWDaOsRxfjj7w3d+jH5OSJdKKSzTrgLKc9ZhlRzVXy0J0hipIA6HG5kdVdLXmh85ITmf1CbJhE6sCgYBjPVeBNbXTHZ2x6/z62aslO5IoQVqetb/kE82hfDOSZcao5Ph9Lam+ttH2ynkAevykj4mBgi+gWwqpey2uW7KaLPSaxShj9kDQA3mP1fzsV/u0y1rB02Nlin/YIxVvOqU1FT9p8SwoXVVu1sHUNck62VtDbN9xqUx5S/ikXrclEQKBgQCoTssOwEcK+Vty9KYcdfy4onTUHZBLdjxl8Iyqkxy7QTQUYRznkvesQPDXEDGO+kk3dyx2KKZt9Hl4IFNww2quPZcvcuMx4DQxjbXXpA8OIIxcta95NepLJwA+mRai3nKCH1A2TlNP7pFeMa5o+8IPly3Ix2lKr4Wepa4PN5i1pwKBgCZ1QP6XAOERl9NznNmU0rXVcvYNP4PIIfQWfvGsldZ4QKkmjjAGiS0/oYqdWs+UDRZyCRChaVjDXO9fk0PEG5OGKAj9nyiYCT/M8xtJ3UeP5ffZZvJ/vnye3QdDIo1e38ZzsWwJHmLYw7fRqY9W5Vxo0Vsy22U3CJY70KTxVdTy" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICmzCCAYMCBgGG3GWycDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZkYnJlcG8wHhcNMjMwMzEzMTkxMzE3WhcNMzMwMzEzMTkxNDU3WjARMQ8wDQYDVQQDDAZkYnJlcG8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdvW00t9yMUtTD1RKFUM1/5kPyxCpvhgFohdxIlNf/MNBQ+IKnXvoEEYjezhWmUMCuc5b4u6ajOYqiB6gcScYQgNbyi+Arm4xT21IDanSqoYFQw51HxgBNMh8Il7uoaKK4ZrdZnLexAszvRK5HPHTZhTyC9Ry+XYmzgrKoDOI5Rf/DdZrn0f2OMY1RdjKpo9Ymnvd4fNtVhbJLPIsbbaZWVxS0HHmyIvlPb9e7Sn3PiXv9tqnDCY5WLVmtweNsQDB0YSJIwYj+5aoAX6vUFGmYktHsc1dwvd4rj/npVgtqLBJ6N/Jh5EUwhMSf9TEZiFxdnnExRQIbRPGMGEtilMG7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAK3kQ1VkQrzvSWvmXmazmNoA1ZiPzRDs1XhGUWxgsxzgPylr3dGBuqQbKvgnLUBQLSqlJHpI4fZflHswu1qrvVZYtekPcGef4WhcKAu2i1RwxrKa6RJQ1tRbrLuVYCzPv5p/DWgltWVn88aoLnqQn0SK/0PB/o4a4Cm7Kq2ZzCr1dACBr06LvOHsc7249OySmbG4HH+pLK6jVURhZ9VaObqAHe2FJBVVoIzURbdiRRURqumrIvbnpeaU1aFyg6ED5wTnXvmMPmVPt9F79mcB33bASO5wyu00X8t1hyN2Show2l2vxLACGUzVkTQt15s7uDLKE7qLmKSR3EuSGXWv3wA=" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] - } }, { "id" : "2293ff99-3c6d-46d1-8635-5e679d5b134a", "name" : "rsa-generated", @@ -2229,35 +2254,6 @@ "flowAlias" : "Verify Existing Account by Re-authentication", "userSetupAllowed" : false } ] - }, { - "id" : "bc0b483f-4a3f-4c15-bf65-b26f5320e6c9", - "alias" : "Authentication Options", - "description" : "Authentication options.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "basic-auth", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "basic-auth-otp", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] }, { "id" : "a690c715-fbae-4c20-b680-bd4010718761", "alias" : "Browser - Conditional OTP", @@ -2574,28 +2570,6 @@ "flowAlias" : "Browser - Conditional OTP", "userSetupAllowed" : false } ] - }, { - "id" : "b8f1f963-6813-4875-bae8-ce48a813763b", - "alias" : "http challenge", - "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "no-cookie-redirect", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Authentication Options", - "userSetupAllowed" : false - } ] }, { "id" : "4c983c77-241f-41c5-8b8a-e2cd6fc08914", "alias" : "registration", @@ -2626,13 +2600,6 @@ "priority" : 20, "autheticatorFlow" : false, "userSetupAllowed" : false - }, { - "authenticator" : "registration-profile-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false }, { "authenticator" : "registration-password-action", "authenticatorFlow" : false, @@ -2777,6 +2744,14 @@ "defaultAction" : false, "priority" : 80, "config" : { } + }, { + "alias" : "delete_credential", + "name" : "Delete Credential", + "providerId" : "delete_credential", + "enabled" : true, + "defaultAction" : false, + "priority" : 100, + "config" : { } }, { "alias" : "update_user_locale", "name" : "Update User Locale", @@ -2792,6 +2767,7 @@ "resetCredentialsFlow" : "reset credentials", "clientAuthenticationFlow" : "clients", "dockerAuthenticationFlow" : "docker auth", + "firstBrokerLoginFlow" : "first broker login", "attributes" : { "cibaBackchannelTokenDeliveryMode" : "poll", "cibaAuthRequestedUserHint" : "login_hint", @@ -2811,7 +2787,7 @@ "clientSessionMaxLifespan" : "0", "shortVerificationUri" : "" }, - "keycloakVersion" : "21.0.2", + "keycloakVersion" : "24.0.5", "userManagedAccessAllowed" : false, "clientProfiles" : { "profiles" : [ ] diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql new file mode 100644 index 0000000000000000000000000000000000000000..d02e1945506e5d66bb17dd10582f81814b940ad1 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql @@ -0,0 +1,11 @@ +CREATE +DATABASE weather_at; +USE +weather_at; + +CREATE TABLE weather_location +( + location VARCHAR(255) PRIMARY KEY, + lat DOUBLE PRECISION NULL, + lng DOUBLE PRECISION NULL +) WITH SYSTEM VERSIONING COMMENT 'Weather location'; \ No newline at end of file diff --git a/dbrepo-metadata-service/services/pom.xml b/dbrepo-metadata-service/services/pom.xml index bb101e9af6539a35e1c761f708392057e48afeea..2961f680d12220dbfbf6c91a7cf64797ff213bf3 100644 --- a/dbrepo-metadata-service/services/pom.xml +++ b/dbrepo-metadata-service/services/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-services</artifactId> <name>dbrepo-metadata-service-services</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java index 35e55797ebffb688f801bfcf64163d3a4a630049..35dd5fe2b6b4f54b882d20c5685c57847dfc2c1d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java @@ -73,6 +73,7 @@ public class AuthTokenFilter extends OncePerRequestFilter { final JWTVerifier verifier = verification.build(); final DecodedJWT jwt = verifier.verify(token); final RealmAccessDto realmAccess = jwt.getClaim("realm_access").as(RealmAccessDto.class); + log.trace("token contains uid: {}", jwt.getClaim("uid").asString()); return UserDetailsDto.builder() .id(jwt.getClaim("uid").asString()) .username(jwt.getClaim("preferred_username").asString()) diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index 80fdd15f1daff7625508eb8d46d9b54332a5150f..b9fea2b54b1c242f58dbc0cd578e9dff328ba49c 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -32,6 +32,7 @@ public class BasicAuthenticationProvider implements AuthenticationManager { try { final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); + log.debug("set basic auth principal: {}", userDetails); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } catch (ServletException | CredentialsInvalidException | AccountNotSetupException | AuthServiceConnectionException e) { 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 index d7c036049b84cfe9d028fa60fa532aa6ba00dc75..3000ece11e91cc2b58f2edcfac85f6a0f8a60528 100644 --- 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 @@ -21,20 +21,31 @@ public interface DatabaseService { */ List<Database> findAll(); + List<Database> findAllPublicOrSchemaPublic(); + + 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> findAllAccess(UUID userId); + List<Database> findAllPublicOrSchemaPublicOrReadAccess(UUID userId); /** * @param internalName The database internal name. - * @return The database if found. - * @throws DatabaseNotFoundException The database was not found. + * @return The databases if found. */ - Database findByInternalName(String internalName) throws DatabaseNotFoundException; + List<Database> findAllPublicOrSchemaPublicByInternalName(String internalName); /** * Find a database by id, only used in the authentication service @@ -51,12 +62,13 @@ public interface DatabaseService { * @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, DatabaseCreateDto createDto, User user) throws UserNotFoundException, + Database create(Container container, DatabaseCreateDto createDto, User user, List<User> internalUsers) throws UserNotFoundException, ContainerNotFoundException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java index 8e7c715ad06d434bfdb947136546f686e91835ad..6416da9b803d93f633f13223127a978954dd6e5d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java @@ -1,9 +1,12 @@ package at.tuwien.service; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.*; +import at.tuwien.api.user.UserPasswordDto; +import at.tuwien.api.user.UserUpdateDto; import at.tuwien.entities.user.User; -import at.tuwien.exception.*; +import at.tuwien.exception.EmailExistsException; +import at.tuwien.exception.UserExistsException; +import at.tuwien.exception.UserNotFoundException; import java.util.List; import java.util.UUID; @@ -26,6 +29,8 @@ public interface UserService { */ User findByUsername(String username) throws UserNotFoundException; + List<User> findAllInternalUsers(); + /** * Finds a specific user in the metadata database by given id. * 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/tuwien/service/impl/AccessServiceImpl.java index a0f45fb34f3c3762a8da630c622d9aa23d327af3..1c302c206871234da50f2cc9de234d7c94a84d66 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java @@ -51,7 +51,7 @@ public class AccessServiceImpl implements AccessService { public DatabaseAccess find(Database database, User user) throws AccessNotFoundException { final Optional<DatabaseAccess> optional = database.getAccesses() .stream() - .filter(a -> a.getUser().getUsername().equals(user.getUsername())) + .filter(a -> a.getHuserid().equals(user.getId())) .findFirst(); if (optional.isEmpty()) { log.error("Failed to find database access for database with id: {}", database.getId()); @@ -94,7 +94,7 @@ public class AccessServiceImpl implements AccessService { /* update in metadata database */ final Optional<DatabaseAccess> optional = database.getAccesses() .stream() - .filter(a -> a.getUser().getId().equals(user.getId())) + .filter(a -> a.getHuserid().equals(user.getId())) .findFirst(); if (optional.isEmpty()) { log.error("Failed to update access for user with id: {}", user.getId()); @@ -116,7 +116,8 @@ public class AccessServiceImpl implements AccessService { /* delete in data database */ dataServiceGateway.deleteAccess(database.getId(), user.getId()); /* delete in metadata database */ - database.getAccesses().remove(find(database, user)); + database.getAccesses() + .remove(find(database, user)); databaseRepository.save(database); /* update in search service */ searchServiceGateway.update(databaseService.findById(database.getId())); 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/tuwien/service/impl/DatabaseServiceImpl.java index f3f4cccc5d5d8742d4c35d12b982001e0cfbb431..7415ded56a8a2a926742ef3b44b025f7fb535baa 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -8,7 +8,9 @@ import at.tuwien.api.database.internal.CreateDatabaseDto; 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.*; +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; @@ -57,19 +59,28 @@ public class DatabaseServiceImpl implements DatabaseService { } @Override - public List<Database> findAllAccess(UUID userId) { - return databaseRepository.findReadAccess(userId); + public List<Database> findAllPublicOrSchemaPublic() { + return databaseRepository.findAllPublicOrSchemaPublicDesc(); } @Override - public Database findByInternalName(String internalName) throws DatabaseNotFoundException { - log.trace("find database by internal name: {}", internalName); - final Optional<Database> database = databaseRepository.findByInternalName(internalName); - if (database.isEmpty()) { - log.error("Failed to find database with internal name {} in metadata database", internalName); - throw new DatabaseNotFoundException("Failed to find database in metadata database"); - } - return database.get(); + public List<Database> findAllPublicOrSchemaPublicOrReadAccessByInternalName(UUID userId, String internalName) { + 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); + } + + @Override + public List<Database> findAllPublicOrSchemaPublicByInternalName(String internalName) { + return databaseRepository.findAllPublicOrSchemaPublicByInternalNameDesc(internalName); } @Override @@ -85,9 +96,9 @@ public class DatabaseServiceImpl implements DatabaseService { @Override @Transactional - public Database create(Container container, DatabaseCreateDto data, User user) throws UserNotFoundException, - ContainerNotFoundException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException { + public Database create(Container container, DatabaseCreateDto data, User user, List<User> internalUsers) + throws UserNotFoundException, ContainerNotFoundException, DataServiceException, SearchServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceConnectionException { final Database entity = Database.builder() .isPublic(data.getIsPublic()) .isSchemaPublic(data.getIsSchemaPublic()) @@ -119,13 +130,11 @@ public class DatabaseServiceImpl implements DatabaseService { /* create in metadata database */ final Database entity1 = databaseRepository.save(entity); entity1.getAccesses() - .add(DatabaseAccess.builder() - .type(AccessType.WRITE_ALL) - .hdbid(entity1.getId()) - .database(entity1) - .huserid(user.getId()) - .user(user) - .build()); + .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); @@ -137,7 +146,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Transactional(readOnly = true) public void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException { - final List<Database> databases = databaseRepository.findReadAccess(user.getId()) + final List<Database> databases = databaseRepository.findAllAtLestReadAccessDesc(user.getId()) .stream() .distinct() .toList(); 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/tuwien/service/impl/IdentifierServiceImpl.java index 8706e18bbc7719b7d8beec8c36a33834b4397471..39e4824706a6d89a3588c6748c46ee2c3935b63e 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java @@ -187,41 +187,41 @@ public class IdentifierServiceImpl implements IdentifierService { identifier.setCreators(new LinkedList<>(data.getCreators() .stream() .map(metadataMapper::creatorCreateDtoToCreator) - .peek(c -> c.setIdentifier(identifier)) .toList())); - log.debug("set {} creator(s)", identifier.getCreators().size()); + identifier.getCreators() + .forEach(c -> c.setIdentifier(identifier)); } if (data.getRelatedIdentifiers() != null) { identifier.setRelatedIdentifiers(new LinkedList<>(data.getRelatedIdentifiers() .stream() .map(metadataMapper::relatedIdentifierCreateDtoToRelatedIdentifier) - .peek(r -> r.setIdentifier(identifier)) .toList())); - log.debug("set {} related identifier(s)", identifier.getRelatedIdentifiers().size()); + identifier.getRelatedIdentifiers() + .forEach(r -> r.setIdentifier(identifier)); } if (data.getTitles() != null) { identifier.setTitles(new LinkedList<>(data.getTitles() .stream() .map(metadataMapper::identifierCreateTitleDtoToIdentifierTitle) - .peek(t -> t.setIdentifier(identifier)) .toList())); - log.debug("set {} title(s)", identifier.getTitles().size()); + identifier.getTitles() + .forEach(t -> t.setIdentifier(identifier)); } if (data.getDescriptions() != null) { identifier.setDescriptions(new LinkedList<>(data.getDescriptions() .stream() .map(metadataMapper::identifierCreateDescriptionDtoToIdentifierDescription) - .peek(d -> d.setIdentifier(identifier)) .toList())); - log.debug("set {} description(s)", identifier.getDescriptions().size()); + identifier.getDescriptions() + .forEach(d -> d.setIdentifier(identifier)); } if (data.getFunders() != null) { identifier.setFunders(new LinkedList<>(data.getFunders() .stream() .map(metadataMapper::identifierFunderSaveDtoToIdentifierFunder) - .peek(d -> d.setIdentifier(identifier)) .toList())); - log.debug("set {} funder(s)", identifier.getFunders().size()); + identifier.getFunders() + .forEach(f -> f.setIdentifier(identifier)); } return save(identifier); } @@ -238,45 +238,44 @@ public class IdentifierServiceImpl implements IdentifierService { identifier.setStatus(IdentifierStatusType.DRAFT); /* create in metadata database */ if (data.getCreators() != null) { - identifier.setCreators(new LinkedList<>(data.getCreators() + identifier.setCreators(data.getCreators() .stream() .map(metadataMapper::creatorCreateDtoToCreator) - .peek(c -> c.setIdentifier(identifier)) - .toList())); - log.debug("set {} creator(s)", identifier.getCreators().size()); + .toList()); + identifier.getCreators() + .forEach(c -> c.setIdentifier(identifier)); } if (data.getRelatedIdentifiers() != null) { - identifier.setRelatedIdentifiers(new LinkedList<>(data.getRelatedIdentifiers() + identifier.setRelatedIdentifiers(data.getRelatedIdentifiers() .stream() .map(metadataMapper::relatedIdentifierCreateDtoToRelatedIdentifier) - .peek(r -> r.setIdentifier(identifier)) - .toList())); - log.debug("set {} related identifier(s)", identifier.getRelatedIdentifiers().size()); + .toList()); + identifier.getRelatedIdentifiers() + .forEach(r -> r.setIdentifier(identifier)); } if (data.getTitles() != null) { - identifier.setTitles(null); - identifier.setTitles(new LinkedList<>(data.getTitles() + identifier.setTitles(data.getTitles() .stream() .map(metadataMapper::identifierCreateTitleDtoToIdentifierTitle) - .peek(t -> t.setIdentifier(identifier)) - .toList())); - log.debug("set {} title(s)", identifier.getTitles().size()); + .toList()); + identifier.getTitles() + .forEach(t -> t.setIdentifier(identifier)); } if (data.getDescriptions() != null) { - identifier.setDescriptions(new LinkedList<>(data.getDescriptions() + identifier.setDescriptions(data.getDescriptions() .stream() .map(metadataMapper::identifierCreateDescriptionDtoToIdentifierDescription) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} description(s)", identifier.getDescriptions().size()); + .toList()); + identifier.getDescriptions() + .forEach(d -> d.setIdentifier(identifier)); } if (data.getFunders() != null) { - identifier.setFunders(new LinkedList<>(data.getFunders() + identifier.setFunders(data.getFunders() .stream() .map(metadataMapper::identifierFunderSaveDtoToIdentifierFunder) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} funder(s)", identifier.getFunders().size()); + .toList()); + identifier.getFunders() + .forEach(f -> f.setIdentifier(identifier)); } return save(identifier); } 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/tuwien/service/impl/UserServiceImpl.java index 7e07b68d1c965ed42261ab508273770be50a6454..6f9f43aeda934ecd7065ead11077ad529597e118 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java @@ -1,9 +1,13 @@ package at.tuwien.service.impl; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.*; +import at.tuwien.api.user.UserPasswordDto; +import at.tuwien.api.user.UserUpdateDto; +import at.tuwien.config.KeycloakConfig; import at.tuwien.entities.user.User; -import at.tuwien.exception.*; +import at.tuwien.exception.EmailExistsException; +import at.tuwien.exception.UserExistsException; +import at.tuwien.exception.UserNotFoundException; import at.tuwien.repository.UserRepository; import at.tuwien.service.UserService; import lombok.extern.log4j.Log4j2; @@ -20,10 +24,12 @@ import java.util.UUID; @Service public class UserServiceImpl implements UserService { + private final KeycloakConfig keycloakConfig; private final UserRepository userRepository; @Autowired - public UserServiceImpl(UserRepository userRepository) { + public UserServiceImpl(KeycloakConfig keycloakConfig, UserRepository userRepository) { + this.keycloakConfig = keycloakConfig; this.userRepository = userRepository; } @@ -36,18 +42,23 @@ public class UserServiceImpl implements UserService { public User findByUsername(String username) throws UserNotFoundException { final Optional<User> optional = userRepository.findByUsername(username); if (optional.isEmpty()) { - log.error("Failed to find user with username {}", username); - throw new UserNotFoundException("Failed to find user with username " + username); + log.error("Failed to find user with username: {}", username); + throw new UserNotFoundException("Failed to find user with username: " + username); } return optional.get(); } + @Override + public List<User> findAllInternalUsers() { + return userRepository.findAllInternal(); + } + @Override public User findById(UUID id) throws UserNotFoundException { final Optional<User> optional = userRepository.findById(id); if (optional.isEmpty()) { - log.error("Failed to find user with id {}", id); - throw new UserNotFoundException("Failed to find user with id " + id); + log.error("Failed to find user with id: {}", id); + throw new UserNotFoundException("Failed to find user with id: " + id); } return optional.get(); } @@ -62,10 +73,11 @@ public class UserServiceImpl implements UserService { .theme("light") .mariadbPassword(getMariaDbPassword(data.getPassword())) .language("en") + .isInternal(false) .build(); /* create at metadata database */ final User user = userRepository.save(entity); - log.info("Created user with id {}", user.getId()); + log.info("Created user with id: {}", user.getId()); return user; } @@ -79,7 +91,7 @@ public class UserServiceImpl implements UserService { user.setLanguage(data.getLanguage()); /* create at metadata database */ user = userRepository.save(user); - log.info("Modified user with id {}", user.getId()); + log.info("Modified user with id: {}", user.getId()); return user; } @@ -88,7 +100,7 @@ public class UserServiceImpl implements UserService { user.setMariadbPassword(getMariaDbPassword(data.getPassword())); /* update at metadata database */ userRepository.save(user); - log.info("Updated password of user with id {}", user.getId()); + log.info("Updated password of user with id: {}", user.getId()); } @Override diff --git a/dbrepo-metadata-service/test/pom.xml b/dbrepo-metadata-service/test/pom.xml index cdb1783c840fcf2e088e5a7d8f29bc67a3d5693d..c58104714adaebc14cfb1c3b5e268e807d8c8e29 100644 --- a/dbrepo-metadata-service/test/pom.xml +++ b/dbrepo-metadata-service/test/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.6.0</version> + <version>1.6.1</version> </parent> <artifactId>dbrepo-metadata-service-test</artifactId> <name>dbrepo-metadata-service-test</name> - <version>1.6.0</version> + <version>1.6.1</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index 887c61501b3b4c40bfaebcfb11f8b9fc95be6adb..91936adaf8f27c87dbd4019b4ee6ce8a67e118a5 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -11,6 +11,7 @@ import java.util.List; public abstract class AbstractUnitTest extends BaseTest { public void genesis() { + IMAGE_1_DTO.setOperators(IMAGE_1_OPERATORS_DTO); CONTAINER_1_PRIVILEGED_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))); @@ -31,7 +32,8 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1_COLUMNS.get(0).setConcept(null); DATABASE_1.setOwner(USER_1); DATABASE_1.setSubsets(new LinkedList<>()); - DATABASE_1.setIsPublic(false); + 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_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))); @@ -41,7 +43,7 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); TABLE_1_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); - VIEW_1_DTO.setDatabase(DATABASE_1_DTO); + 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); @@ -49,6 +51,7 @@ public abstract class AbstractUnitTest extends BaseTest { 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_PRIVILEGED_DTO.setContainer(CONTAINER_1_PRIVILEGED_DTO); DATABASE_1_PRIVILEGED_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))); DATABASE_1_PRIVILEGED_DTO.setTables(new LinkedList<>(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO))); DATABASE_1_PRIVILEGED_DTO.setViews(new LinkedList<>(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO))); @@ -138,6 +141,11 @@ public abstract class AbstractUnitTest extends BaseTest { VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO); IDENTIFIER_6.setDatabase(DATABASE_3); /* DATABASE 4 */ + 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); 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))); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 5e5b653852782dd6fab81dd39d1d7e5762396bfa..368b1d182c3b4d4289426673804bab23ccd8c0e1 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -10,10 +10,7 @@ import at.tuwien.api.auth.RefreshTokenRequestDto; import at.tuwien.api.auth.SignupRequestDto; import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.container.ContainerDto; -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.container.image.*; import at.tuwien.api.container.internal.PrivilegedContainerDto; import at.tuwien.api.database.*; import at.tuwien.api.database.internal.CreateDatabaseDto; @@ -26,10 +23,7 @@ import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.TableStatisticDto; import at.tuwien.api.database.table.columns.*; -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.columns.concepts.*; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; import at.tuwien.api.database.table.constraints.foreign.*; @@ -40,11 +34,9 @@ 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.CredentialDto; -import at.tuwien.api.keycloak.CredentialTypeDto; -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.keycloak.UserCreateDto; +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; @@ -57,9 +49,9 @@ import at.tuwien.api.orcid.activities.employments.affiliation.group.summary.orga 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.EntityDto; -import at.tuwien.api.semantics.OntologyCreateDto; -import at.tuwien.api.semantics.OntologyModifyDto; +import at.tuwien.api.semantics.*; +import at.tuwien.api.user.UserAttributesDto; +import at.tuwien.api.user.UserDto; import at.tuwien.api.user.*; import at.tuwien.api.user.internal.PrivilegedUserDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; @@ -111,8 +103,8 @@ import static java.time.temporal.ChronoUnit.MINUTES; /** * Database 1 (Private Data, Private Schema, User 1) -> Container 1 * <ul> - * <li>Table 1</li> - * <li>Table 2</li> + * <li>Table 1 (Private Data, Private Schema)</li> + * <li>Table 2 (Private Data, Public Schema)</li> * <li>Table 3</li> * <li>Table 4</li> * <li>Query 1</li> @@ -147,7 +139,9 @@ import static java.time.temporal.ChronoUnit.MINUTES; * </ul> * <p> * Database 4 (Public Data, Public Schema, User 4) -> Container 4 - * <li>Identifier 7 (Database=4)</li> + * <li>Table 9</li> + * <li>Identifier 7</li> + * <li>Query 7</li> * <ul> * </ul> * <br /> @@ -163,6 +157,8 @@ public abstract class BaseTest { public final static String MARIADB_IMAGE = "mariadb:11.3.2"; + public final static String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak:24.0"; + public final static String[] DEFAULT_SEMANTICS_HANDLING = new String[]{"default-semantics-handling", "create-semantic-unit", "execute-semantic-query", "table-semantic-analyse", "create-semantic-concept"}; @@ -194,8 +190,8 @@ public abstract class BaseTest { "modify-identifier-metadata", "update-foreign-identifier", "create-foreign-identifier"}; public final static String[] DEFAULT_QUERY_HANDLING = new String[]{"default-query-handling", "view-table-data", - "execute-query", "view-table-history", "list-database-views", "list-queries", "view-database-view-data", - "export-query-data", "find-query", "create-database-view", "delete-database-view", "delete-table-data", + "execute-query", "view-table-history", "list-database-views", "view-database-view-data", + "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 final static String[] ESCALATED_QUERY_HANDLING = new String[]{"escalated-query-handling"}; @@ -283,9 +279,12 @@ public abstract class BaseTest { .type(AccessTypeDto.WRITE_ALL) .build(); + public final static String TOKEN_ACCESS_TOKEN = "ey.yee.skrr"; + public final static String TOKEN_ACCESS_SCOPE = "openid"; + public final static TokenDto TOKEN_DTO = TokenDto.builder() - .accessToken("ey.yee.skrr") - .scope("openid") + .accessToken(TOKEN_ACCESS_TOKEN) + .scope(TOKEN_ACCESS_SCOPE) .build(); public final static RefreshTokenRequestDto REFRESH_TOKEN_REQUEST_DTO = RefreshTokenRequestDto.builder() @@ -311,6 +310,13 @@ public abstract class BaseTest { .description(CONCEPT_1_DESCRIPTION) .build(); + public final static 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 final static TableColumnConcept CONCEPT_1 = TableColumnConcept.builder() .id(CONCEPT_1_ID) .uri(CONCEPT_1_URI) @@ -344,6 +350,13 @@ public abstract class BaseTest { .description(CONCEPT_2_DESCRIPTION) .build(); + public final static 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 final static TableColumnConcept CONCEPT_2 = TableColumnConcept.builder() .id(CONCEPT_2_ID) .uri(CONCEPT_2_URI) @@ -371,6 +384,13 @@ public abstract class BaseTest { .description(UNIT_1_DESCRIPTION) .build(); + public final static 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 final static TableColumnUnit UNIT_1 = TableColumnUnit.builder() .id(UNIT_1_ID) .uri(UNIT_1_URI) @@ -404,6 +424,13 @@ public abstract class BaseTest { .description(UNIT_2_DESCRIPTION) .build(); + public final static 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 final static TableColumnUnit UNIT_2 = TableColumnUnit.builder() .id(UNIT_2_ID) .uri(UNIT_2_URI) @@ -421,11 +448,19 @@ public abstract class BaseTest { @SuppressWarnings("java:S2068") 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; public final static String USER_LOCAL_ADMIN_EMAIL = "admin@local"; @SuppressWarnings("java:S2068") public final static String USER_LOCAL_ADMIN_MARIADB_PASSWORD = "*440BA4FD1A87A0999647DB67C0EE258198B247BA"; + public final static LoginRequestDto USER_LOCAL_ADMIN_LOGIN_REQUEST_DTO = LoginRequestDto.builder() + .username(USER_LOCAL_ADMIN_USERNAME) + .password(USER_LOCAL_ADMIN_PASSWORD) + .build(); + public final static UserDetails USER_LOCAL_ADMIN_DETAILS = UserDetailsDto.builder() + .id(String.valueOf(USER_LOCAL_ADMIN_ID)) .username(USER_LOCAL_ADMIN_USERNAME) .password(USER_LOCAL_ADMIN_PASSWORD) .authorities(AUTHORITY_DEFAULT_LOCAL_ADMIN_AUTHORITIES) @@ -437,13 +472,14 @@ public abstract class BaseTest { .email(USER_LOCAL_ADMIN_EMAIL) .mariadbPassword(USER_LOCAL_ADMIN_MARIADB_PASSWORD) .theme(USER_LOCAL_ADMIN_THEME) + .isInternal(USER_LOCAL_ADMIN_IS_INTERNAL) .build(); public final static Principal USER_LOCAL_ADMIN_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_LOCAL_ADMIN_DETAILS, USER_LOCAL_ADMIN_PASSWORD, USER_LOCAL_ADMIN_DETAILS.getAuthorities()); public final static UUID USER_1_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); - public final static UUID USER_1_LDAP_ID = UUID.fromString("8e541e05-f45c-4d40-ba1b-0e62f04ba3f8"); + public final static UUID USER_1_LDAP_ID = UUID.fromString("cd5bab0d-7799-4069-85fb-c5d738572a0b"); public final static String USER_1_EMAIL = "john.doe@example.com"; public final static String USER_1_USERNAME = "junit1"; @SuppressWarnings("java:S2068") @@ -454,18 +490,17 @@ public abstract class BaseTest { 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_USERNAME + " — " + USER_1_FIRSTNAME + " " + USER_1_LASTNAME; + 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 = "000000034216302X"; - public final static String USER_1_ORCID_UNCOMPRESSED = "0000-0003-4216-302X"; - public final static String USER_1_ORCID_URL = "https://orcid.org/" + USER_1_ORCID_UNCOMPRESSED; + public final static String USER_1_ORCID_URL = "https://orcid.org/0000-0003-4216-302X"; public final static String USER_1_TITLES_BEFORE = "Dr."; public final static String USER_1_TITLES_AFTER = "MSc BSc"; public final static Boolean USER_1_VERIFIED = false; public final static Boolean USER_1_TOTP = false; public final static Long USER_1_NOT_BEFORE = 0L; 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) */; @@ -479,7 +514,7 @@ public abstract class BaseTest { public final static UserAttributesDto USER_1_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_1_THEME) - .orcid(USER_1_ORCID_UNCOMPRESSED) + .orcid(USER_1_ORCID_URL) .affiliation(USER_1_AFFILIATION) .mariadbPassword(USER_1_DATABASE_PASSWORD) .language(USER_1_LANGUAGE) @@ -491,19 +526,31 @@ public abstract class BaseTest { .value(USER_1_PASSWORD) .build(); + public final static CredentialDto USER_LOCAL_KEYCLOAK_CREDENTIAL_1 = CredentialDto.builder() + .type(CredentialTypeDto.PASSWORD) + .temporary(false) + .value(USER_LOCAL_ADMIN_PASSWORD) + .build(); + public final static UserCreateDto USER_1_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() .username(USER_1_USERNAME) .email(USER_1_EMAIL) .enabled(USER_1_ENABLED) - .credentials(List.of(USER_1_KEYCLOAK_CREDENTIAL_1)) + .credentials(new LinkedList<>(List.of(USER_1_KEYCLOAK_CREDENTIAL_1))) + .attributes(UserCreateAttributesDto.builder() + .ldapId(String.valueOf(USER_1_ID)) + .build()) .build(); - public final static UserCreateDto USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST = UserCreateDto.builder() - .username(USER_1_USERNAME) - .email(USER_1_EMAIL) - .enabled(USER_1_ENABLED) - .credentials(List.of(USER_1_KEYCLOAK_CREDENTIAL_1)) - .groups(List.of("system")) + public final static UserCreateDto USER_LOCAL_KEYCLOAK_SIGNUP_REQUEST = UserCreateDto.builder() + .username(USER_LOCAL_ADMIN_USERNAME) + .email(USER_LOCAL_ADMIN_EMAIL) + .enabled(USER_LOCAL_ADMIN_ENABLED) + .credentials(new LinkedList<>(List.of(USER_LOCAL_KEYCLOAK_CREDENTIAL_1))) + .groups(new LinkedList<>(List.of("system"))) + .attributes(UserCreateAttributesDto.builder() + .ldapId(String.valueOf(USER_LOCAL_ADMIN_ID)) + .build()) .build(); public final static PrivilegedUserDto USER_1_PRIVILEGED_DTO = PrivilegedUserDto.builder() @@ -524,10 +571,11 @@ public abstract class BaseTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .theme(USER_1_THEME) .mariadbPassword(USER_1_DATABASE_PASSWORD) .language(USER_1_LANGUAGE) + .isInternal(USER_1_IS_INTERNAL) .build(); public final static UserDto USER_1_DTO = UserDto.builder() @@ -544,7 +592,7 @@ public abstract class BaseTest { .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) .affiliation(USER_1_AFFILIATION) - .orcid(USER_1_ORCID) + .orcid(USER_1_ORCID_URL) .theme(USER_1_THEME) .language(USER_1_LANGUAGE) .build(); @@ -573,6 +621,7 @@ public abstract class BaseTest { .lastname(USER_1_LASTNAME) .name(USER_1_NAME) .qualifiedName(USER_1_QUALIFIED_NAME) + .orcid(USER_1_ORCID_URL) .build(); public final static UserDetails USER_1_DETAILS = UserDetailsDto.builder() @@ -598,6 +647,7 @@ public abstract class BaseTest { .build(); public final static UUID USER_2_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); + public final static UUID USER_2_LDAP_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); public final static String USER_2_EMAIL = "jane.doe@example.com"; public final static String USER_2_USERNAME = "junit2"; public final static String USER_2_FIRSTNAME = "Jane"; @@ -609,11 +659,12 @@ public abstract class BaseTest { public final static String USER_2_PASSWORD = "junit2"; @SuppressWarnings("java:S2068") public final static String USER_2_DATABASE_PASSWORD = "*9AA70A8B0EEFAFCB5BED5BDEF6EE264D5DA915AE" /* junit2 */; - public final static String USER_2_QUALIFIED_NAME = "@" + USER_2_USERNAME + " — " + USER_2_FIRSTNAME + " " + USER_2_LASTNAME; + public final static String USER_2_QUALIFIED_NAME = USER_2_FIRSTNAME + " " + USER_2_LASTNAME + " — @" + USER_2_USERNAME; public final static Boolean USER_2_VERIFIED = true; public final static Boolean USER_2_TOTP = false; public final static Long USER_2_NOT_BEFORE = 0L; public final static Boolean USER_2_ENABLED = true; + 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 final static Instant USER_2_CREATED = Instant.ofEpochSecond(1677399528L) /* 2023-02-26 08:18:48 (UTC) */; @@ -639,6 +690,7 @@ public abstract class BaseTest { .theme(USER_2_THEME) .mariadbPassword(USER_2_DATABASE_PASSWORD) .language(USER_2_LANGUAGE) + .isInternal(USER_2_IS_INTERNAL) .build(); public final static UserDto USER_2_DTO = UserDto.builder() @@ -657,6 +709,7 @@ public abstract class BaseTest { .firstname(USER_2_FIRSTNAME) .lastname(USER_2_LASTNAME) .name(USER_2_NAME) + .orcid(USER_2_ORCID_URL) .qualifiedName(USER_2_QUALIFIED_NAME) .build(); @@ -671,7 +724,7 @@ public abstract class BaseTest { .username(USER_2_USERNAME) .email(USER_2_EMAIL) .password(USER_2_PASSWORD) - .authorities(AUTHORITY_DEFAULT_DEVELOPER_AUTHORITIES) + .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); public final static at.tuwien.api.keycloak.UserDto USER_2_KEYCLOAK_DTO = at.tuwien.api.keycloak.UserDto.builder() @@ -703,6 +756,7 @@ public abstract class BaseTest { USER_2_PASSWORD, USER_2_DETAILS.getAuthorities()); public final static UUID USER_3_ID = UUID.fromString("7b080e33-d8db-4276-9d53-47208e657006"); + public final static UUID USER_3_LDAP_ID = UUID.fromString("7b080e33-d8db-4276-9d53-47208e657006"); public final static String USER_3_USERNAME = "junit3"; public final static String USER_3_FIRSTNAME = "System"; public final static String USER_3_LASTNAME = "System"; @@ -715,11 +769,12 @@ public abstract class BaseTest { public final static String USER_3_PASSWORD = "password"; @SuppressWarnings("java:S2068") public final static String USER_3_DATABASE_PASSWORD = "*D65FCA043964B63E849DD6334699ECB065905DA4" /* junit3 */; - public final static String USER_3_QUALIFIED_NAME = "@" + USER_3_USERNAME + " — " + USER_3_FIRSTNAME + " " + USER_3_LASTNAME; + public final static String USER_3_QUALIFIED_NAME = USER_3_FIRSTNAME + " " + USER_3_LASTNAME + " — @" + USER_3_USERNAME; public final static Boolean USER_3_VERIFIED = true; public final static Boolean USER_3_TOTP = false; public final static Long USER_3_NOT_BEFORE = 0L; public final static Boolean USER_3_ENABLED = true; + public final static Boolean USER_3_IS_INTERNAL = false; public final static String USER_3_THEME = "light"; public final static Instant USER_3_CREATED = Instant.ofEpochSecond(1677399559L) /* 2023-02-26 08:19:19 (UTC) */; public final static UUID USER_3_REALM_ID = REALM_DBREPO_ID; @@ -741,6 +796,7 @@ public abstract class BaseTest { .orcid(USER_3_ORCID_URL) .theme(USER_3_THEME) .mariadbPassword(USER_3_DATABASE_PASSWORD) + .isInternal(USER_3_IS_INTERNAL) .build(); public final static UserDto USER_3_DTO = UserDto.builder() @@ -749,6 +805,8 @@ public abstract class BaseTest { .firstname(USER_3_FIRSTNAME) .lastname(USER_3_LASTNAME) .name(USER_3_NAME) + .qualifiedName(USER_3_QUALIFIED_NAME) + .attributes(USER_3_ATTRIBUTES_DTO) .build(); public final static UserBriefDto USER_3_BRIEF_DTO = UserBriefDto.builder() @@ -757,6 +815,7 @@ public abstract class BaseTest { .firstname(USER_3_FIRSTNAME) .lastname(USER_3_LASTNAME) .name(USER_3_NAME) + .qualifiedName(USER_3_QUALIFIED_NAME) .build(); public final static UserDetails USER_3_DETAILS = UserDetailsDto.builder() @@ -764,7 +823,7 @@ public abstract class BaseTest { .username(USER_3_USERNAME) .email(USER_3_EMAIL) .password(USER_3_PASSWORD) - .authorities(AUTHORITY_DEFAULT_DATA_STEWARD_AUTHORITIES) + .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) .build(); public final static at.tuwien.api.keycloak.UserDto USER_3_KEYCLOAK_DTO = at.tuwien.api.keycloak.UserDto.builder() @@ -796,6 +855,7 @@ public abstract class BaseTest { .build(); public final static UUID USER_4_ID = UUID.fromString("791d58c5-bfab-4520-b4fc-b44d4ab9feb0"); + public final static UUID USER_4_LDAP_ID = UUID.fromString("791d58c5-bfab-4520-b4fc-b44d4ab9feb0"); public final static String USER_4_USERNAME = "junit4"; public final static String USER_4_FIRSTNAME = "JUnit"; public final static String USER_4_LASTNAME = "4"; @@ -806,10 +866,11 @@ public abstract class BaseTest { public final static String USER_4_PASSWORD = "junit4"; @SuppressWarnings("java:S2068") public final static String USER_4_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit4 */; - public final static String USER_4_QUALIFIED_NAME = "@" + USER_4_USERNAME + " — " + USER_4_FIRSTNAME + " " + USER_4_LASTNAME; + public final static String USER_4_QUALIFIED_NAME = USER_4_FIRSTNAME + " " + USER_4_LASTNAME + " — @" + USER_4_USERNAME; public final static String USER_4_EMAIL = "junit4@ossdip.at"; public final static Boolean USER_4_VERIFIED = true; public final static Boolean USER_4_ENABLED = true; + public final static Boolean USER_4_IS_INTERNAL = false; public final static String USER_4_THEME = "light"; public final static Instant USER_4_CREATED = Instant.ofEpochSecond(1677399592L) /* 2023-02-26 08:19:52 (UTC) */; public final static UUID USER_4_REALM_ID = REALM_DBREPO_ID; @@ -831,6 +892,7 @@ public abstract class BaseTest { .orcid(USER_4_ORCID_URL) .theme(USER_4_THEME) .mariadbPassword(USER_4_DATABASE_PASSWORD) + .isInternal(USER_4_IS_INTERNAL) .build(); public final static UserDto USER_4_DTO = UserDto.builder() @@ -838,7 +900,9 @@ public abstract class BaseTest { .username(USER_4_USERNAME) .firstname(USER_4_FIRSTNAME) .lastname(USER_4_LASTNAME) + .name(USER_4_NAME) .attributes(USER_4_ATTRIBUTES_DTO) + .qualifiedName(USER_4_QUALIFIED_NAME) .build(); public final static UserBriefDto USER_4_BRIEF_DTO = UserBriefDto.builder() @@ -846,6 +910,8 @@ public abstract class BaseTest { .username(USER_4_USERNAME) .firstname(USER_4_FIRSTNAME) .lastname(USER_4_LASTNAME) + .name(USER_4_NAME) + .qualifiedName(USER_4_QUALIFIED_NAME) .build(); public final static UserDetails USER_4_DETAILS = UserDetailsDto.builder() @@ -871,20 +937,22 @@ public abstract class BaseTest { .build(); public final static UUID USER_5_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); - public final static String USER_5_USERNAME = "system"; - public final static String USER_5_FIRSTNAME = "System"; - public final static String USER_5_LASTNAME = "System"; - public final static String USER_5_NAME = "System System"; + public final static UUID USER_5_LDAP_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"; public final static String USER_5_ORCID = null; @SuppressWarnings("java:S2068") public final static String USER_5_PASSWORD = "junit5"; @SuppressWarnings("java:S2068") public final static String USER_5_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit5 */; - public final static String USER_5_QUALIFIED_NAME = "@" + USER_5_USERNAME + " — " + USER_5_FIRSTNAME + " " + USER_5_LASTNAME; + public final static String USER_5_QUALIFIED_NAME = USER_5_FIRSTNAME + " " + USER_5_LASTNAME + " — @" + USER_5_USERNAME; public final static String USER_5_EMAIL = "system@ossdip.at"; public final static Boolean USER_5_VERIFIED = true; public final static Boolean USER_5_ENABLED = true; + public final static Boolean USER_5_IS_INTERNAL = false; public final static String USER_5_THEME = "dark"; public final static Instant USER_5_CREATED = Instant.ofEpochSecond(1677399592L) /* 2023-02-26 08:19:52 (UTC) */; public final static UUID USER_5_REALM_ID = REALM_DBREPO_ID; @@ -900,6 +968,7 @@ public abstract class BaseTest { .username(USER_5_USERNAME) .firstname(USER_5_FIRSTNAME) .lastname(USER_5_LASTNAME) + .name(USER_5_NAME) .qualifiedName(USER_5_QUALIFIED_NAME) .attributes(USER_5_ATTRIBUTES_DTO) .build(); @@ -928,7 +997,7 @@ public abstract class BaseTest { .username(USER_5_USERNAME) .email(USER_5_EMAIL) .password(USER_5_PASSWORD) - .authorities(AUTHORITY_DEFAULT_RESEARCHER_AUTHORITIES) + .authorities(AUTHORITY_DEFAULT_DEVELOPER_AUTHORITIES) .build(); public final static Principal USER_5_PRINCIPAL = new UsernamePasswordAuthenticationToken(USER_5_DETAILS, @@ -943,6 +1012,7 @@ public abstract class BaseTest { .affiliation(USER_5_AFFILIATION) .theme(USER_5_THEME) .mariadbPassword(USER_5_DATABASE_PASSWORD) + .isInternal(USER_5_IS_INTERNAL) .build(); public final static UUID USER_6_ID = UUID.fromString("28ff851d-d7bc-4422-959c-edd7a5b15630"); @@ -959,6 +1029,7 @@ public abstract class BaseTest { public final static String USER_6_EMAIL = "system@ossdip.at"; 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 Boolean USER_6_THEME_DARK = false; public final static Instant USER_6_CREATED = Instant.ofEpochSecond(1677399592L) /* 2023-02-26 08:19:52 (UTC) */; public final static UUID USER_6_REALM_ID = REALM_DBREPO_ID; @@ -1019,6 +1090,7 @@ public abstract class BaseTest { .driverClass(IMAGE_1_DRIVER) .defaultPort(IMAGE_1_PORT) .isDefault(IMAGE_1_IS_DEFAULT) + .operators(new LinkedList<>()) /* IMAGE_1_OPERATORS */ .build(); public final static ImageDto IMAGE_1_DTO = ImageDto.builder() @@ -1031,6 +1103,7 @@ public abstract class BaseTest { .driverClass(IMAGE_1_DRIVER) .defaultPort(IMAGE_1_PORT) .isDefault(IMAGE_1_IS_DEFAULT) + .operators(null) .build(); public final static ImageBriefDto IMAGE_1_BRIEF_DTO = ImageBriefDto.builder() @@ -1041,14 +1114,27 @@ public abstract class BaseTest { .jdbcMethod(IMAGE_1_JDBC) .build(); - public final static List<Operator> IMAGE_1_OPERATORS = List.of( + public final static Long IMAGE_1_OPERATORS_1_ID = 1L; + 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 List<Operator> IMAGE_1_OPERATORS = new LinkedList<>(List.of( Operator.builder() - .id(1L) + .id(IMAGE_1_OPERATORS_1_ID) .image(IMAGE_1) - .displayName("XOR") - .value("XOR") - .documentation("https://mariadb.com/kb/en/xor/") - .build()); + .displayName(IMAGE_1_OPERATORS_1_DISPLAY_NAME) + .value(IMAGE_1_OPERATORS_1_VALUE) + .documentation(IMAGE_1_OPERATORS_1_DOCUMENTATION) + .build())); + + public final static 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) + .value(IMAGE_1_OPERATORS_1_VALUE) + .documentation(IMAGE_1_OPERATORS_1_DOCUMENTATION) + .build())); public final static Long CONTAINER_1_ID = 1L; public final static ContainerImage CONTAINER_1_IMAGE = IMAGE_1; @@ -1136,7 +1222,7 @@ public abstract class BaseTest { .host(CONTAINER_2_HOST) .port(CONTAINER_2_PORT) .quota(CONTAINER_2_QUOTA) - .databases(List.of()) + .databases(new LinkedList<>(List.of())) .privilegedUsername(CONTAINER_2_PRIVILEGED_USERNAME) .privilegedPassword(CONTAINER_2_PRIVILEGED_PASSWORD) .build(); @@ -1190,7 +1276,7 @@ public abstract class BaseTest { .host(CONTAINER_3_HOST) .port(CONTAINER_3_PORT) .quota(CONTAINER_3_QUOTA) - .databases(List.of()) + .databases(new LinkedList<>(List.of())) .privilegedUsername(CONTAINER_3_PRIVILEGED_USERNAME) .privilegedPassword(CONTAINER_3_PRIVILEGED_PASSWORD) .build(); @@ -1294,10 +1380,6 @@ public abstract class BaseTest { 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 final static UUID DATABASE_3_OWNER = USER_3_ID; - public final static UUID DATABASE_3_CREATOR_ID = USER_3_ID; - public final static User DATABASE_3_CREATOR = USER_3; - public final static UserDto DATABASE_3_CREATOR_DTO = USER_3_DTO; - public final static UserDto DATABASE_3_OWNER_DTO = USER_3_DTO; public final static DatabaseDto DATABASE_3_DTO = DatabaseDto.builder() .id(DATABASE_3_ID) @@ -1427,13 +1509,13 @@ public abstract class BaseTest { .name("col13") .type(ColumnTypeDto.ENUM) .nullAllowed(true) - .enums(List.of("val1", "val2")) + .enums(new LinkedList<>(List.of("val1", "val2"))) .build(), ColumnCreateDto.builder() .name("col14") .type(ColumnTypeDto.SET) .nullAllowed(true) - .sets(List.of("val1", "val2")) + .sets(new LinkedList<>(List.of("val1", "val2"))) .build(), ColumnCreateDto.builder() .name("col15") @@ -1600,12 +1682,11 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_1_COLUMNS_DTO = List.of(ColumnDto.builder() .id(1L) - .table(TABLE_1_DTO) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(0) .name("id") .internalName("id") - .ordinalPosition(0) .columnType(ColumnTypeDto.SERIAL) .isNullAllowed(false) .enums(null) @@ -1613,12 +1694,11 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(2L) - .table(TABLE_1_DTO) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(1) .name("Date") .internalName("date") - .ordinalPosition(1) .columnType(ColumnTypeDto.DATE) .isNullAllowed(true) .enums(null) @@ -1626,12 +1706,11 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(3L) - .table(TABLE_1_DTO) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(2) .name("Location") .internalName("location") - .ordinalPosition(2) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(true) @@ -1640,12 +1719,11 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(4L) - .table(TABLE_1_DTO) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(3) .name("MinTemp") .internalName("mintemp") - .ordinalPosition(3) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -1655,17 +1733,16 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(5L) - .table(TABLE_1_DTO) .tableId(TABLE_1_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(4) .name("Rainfall") .internalName("rainfall") - .ordinalPosition(4) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) - .concept(CONCEPT_1_DTO) - .unit(UNIT_1_DTO) + .concept(CONCEPT_1_BRIEF_DTO) + .unit(UNIT_1_BRIEF_DTO) .isNullAllowed(true) .enums(null) .sets(null) @@ -1673,6 +1750,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_1_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_1_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_1_INTERNAL_NAME) .isVersioned(TABLE_1_VERSIONED) .isPublic(TABLE_1_IS_PUBLIC) @@ -1713,7 +1791,7 @@ public abstract class BaseTest { public final static String TABLE_2_INTERNALNAME = "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 = false; + public final static Boolean TABLE_2_SCHEMA_PUBLIC = true; public final static Boolean TABLE_2_PROCESSED_CONSTRAINTS = true; public final static String TABLE_2_DESCRIPTION = "Weather location"; public final static String TABLE_2_QUEUE_NAME = TABLE_2_INTERNALNAME; @@ -1793,6 +1871,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_2_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_2_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_2_INTERNALNAME) .isVersioned(TABLE_2_VERSIONED) .isPublic(TABLE_2_IS_PUBLIC) @@ -1864,6 +1943,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_3_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_3_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_3_INTERNALNAME) .isVersioned(TABLE_3_VERSIONED) .isPublic(TABLE_3_IS_PUBLIC) @@ -1886,8 +1966,9 @@ public abstract class BaseTest { .uniques(new LinkedList<>()) .foreignKeys(List.of(ForeignKeyCreateDto.builder() .referencedTable("weather_location") - .columns(List.of("fahrzeug")) - .referencedColumns(List.of("doesnotexist")).build())) + .columns(new LinkedList<>(List.of("fahrzeug"))) + .referencedColumns(new LinkedList<>(List.of("doesnotexist"))) + .build())) .build(); public final static TableCreateDto TABLE_3_CREATE_DTO = TableCreateDto.builder() @@ -1981,6 +2062,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_5_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_5_INTERNALNAME) .isVersioned(TABLE_5_VERSIONED) .isPublic(TABLE_5_IS_PUBLIC) @@ -2040,6 +2122,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_6_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_6_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_6_INTERNALNAME) .isVersioned(TABLE_6_VERSIONED) .isPublic(TABLE_6_IS_PUBLIC) @@ -2099,6 +2182,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_7_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_7_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_7_INTERNAL_NAME) .isVersioned(TABLE_7_VERSIONED) .isPublic(TABLE_7_IS_PUBLIC) @@ -2170,6 +2254,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_4_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_4_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_4_INTERNALNAME) .description(TABLE_4_DESCRIPTION) .name(TABLE_4_NAME) @@ -2226,7 +2311,7 @@ public abstract class BaseTest { .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>(Set.of("Timestamp"))) .foreignKeys(new LinkedList<>()) - .uniques(List.of(List.of("Timestamp"))) + .uniques(new LinkedList<>(List.of(List.of("Timestamp")))) .build(); public final static TableCreateDto TABLE_4_CREATE_DTO = TableCreateDto.builder() @@ -2264,7 +2349,7 @@ public abstract class BaseTest { public final static Long TABLE_8_ID = 8L; public final static Long TABLE_8_DATABASE_ID = DATABASE_3_ID; - public final static String TABLE_8_NAME = "mfcc"; + 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; @@ -2312,6 +2397,7 @@ public abstract class BaseTest { public final static TableBriefDto TABLE_8_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_8_ID) + .databaseId(DATABASE_3_ID) .internalName(TABLE_8_INTERNAL_NAME) .description(TABLE_8_DESCRIPTION) .isVersioned(TABLE_8_VERSIONED) @@ -2337,6 +2423,194 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); + public final static Long TABLE_9_ID = 9L; + public final static Long TABLE_9_DATABASE_ID = DATABASE_4_ID; + public final static String TABLE_9_NAME = "mfcc"; + public final static String TABLE_9_INTERNAL_NAME = "mfcc"; + 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 Boolean TABLE_9_PROCESSED_CONSTRAINTS = true; + public final static String TABLE_9_DESCRIPTION = "Hello mfcc"; + public final static String TABLE_9_QUEUE_NAME = TABLE_9_INTERNAL_NAME; + public final static String TABLE_9_ROUTING_KEY = "dbrepo\\." + DATABASE_3_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 static Table TABLE_9 = Table.builder() + .id(TABLE_9_ID) + .tdbid(TABLE_9_DATABASE_ID) + .internalName(TABLE_9_INTERNAL_NAME) + .description(TABLE_9_DESCRIPTION) + .isVersioned(TABLE_9_VERSIONED) + .isPublic(TABLE_9_IS_PUBLIC) + .isSchemaPublic(TABLE_9_SCHEMA_PUBLIC) + .database(null /* DATABASE_1 */) + .name(TABLE_9_NAME) + .queueName(TABLE_9_QUEUE_NAME) + .columns(new LinkedList<>()) /* TABLE_9_COLUMNS */ + .constraints(null) /* TABLE_9_CONSTRAINTS */ + .ownedBy(USER_1_ID) + .owner(USER_1) + .created(TABLE_9_CREATED) + .lastModified(TABLE_9_LAST_MODIFIED) + .build(); + + public final static TableDto TABLE_9_DTO = TableDto.builder() + .id(TABLE_9_ID) + .tdbid(TABLE_9_DATABASE_ID) + .internalName(TABLE_9_INTERNAL_NAME) + .description(TABLE_9_DESCRIPTION) + .isVersioned(TABLE_9_VERSIONED) + .isPublic(TABLE_9_IS_PUBLIC) + .isSchemaPublic(TABLE_9_SCHEMA_PUBLIC) + .name(TABLE_9_NAME) + .queueName(TABLE_9_QUEUE_NAME) + .columns(new LinkedList<>()) /* TABLE_9_COLUMNS_DTO */ + .constraints(null) /* TABLE_9_CONSTRAINTS_DTO */ + .owner(USER_1_BRIEF_DTO) + .build(); + + public final static TableBriefDto TABLE_9_BRIEF_DTO = TableBriefDto.builder() + .id(TABLE_9_ID) + .databaseId(DATABASE_4_ID) + .internalName(TABLE_9_INTERNAL_NAME) + .description(TABLE_9_DESCRIPTION) + .isVersioned(TABLE_9_VERSIONED) + .isPublic(TABLE_9_IS_PUBLIC) + .isSchemaPublic(TABLE_9_SCHEMA_PUBLIC) + .name(TABLE_9_NAME) + .ownedBy(USER_1_ID) + .build(); + + public final static PrivilegedTableDto TABLE_9_PRIVILEGED_DTO = PrivilegedTableDto.builder() + .id(TABLE_9_ID) + .tdbid(TABLE_9_DATABASE_ID) + .internalName(TABLE_9_INTERNAL_NAME) + .description(TABLE_9_DESCRIPTION) + .isVersioned(TABLE_9_VERSIONED) + .isPublic(TABLE_9_IS_PUBLIC) + .isSchemaPublic(TABLE_9_SCHEMA_PUBLIC) + .name(TABLE_9_NAME) + .queueName(TABLE_9_QUEUE_NAME) + .columns(new LinkedList<>()) /* TABLE_9_COLUMNS_DTO */ + .owner(USER_1_BRIEF_DTO) + .isPublic(DATABASE_3_PUBLIC) + .lastRetrieved(Instant.now()) + .build(); + + public final static Long COLUMN_9_1_ID = 78L; + public final static String COLUMN_9_1_NAME = "location"; + public final static String COLUMN_9_1_INTERNAL_NAME = "location"; + + public final static 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 final static Long COLUMN_9_2_ID = 79L; + + public final static Long COLUMN_9_3_ID = 80L; + + public final static List<TableColumn> TABLE_9_COLUMNS = List.of(TableColumn.builder() + .id(COLUMN_9_1_ID) + .ordinalPosition(0) + .table(TABLE_9) + .name(COLUMN_9_1_NAME) + .internalName(COLUMN_9_1_INTERNAL_NAME) + .columnType(TableColumnType.VARCHAR) + .size(255L) + .isNullAllowed(false) + .enums(null) + .sets(null) + .build(), + TableColumn.builder() + .id(COLUMN_9_2_ID) + .ordinalPosition(1) + .table(TABLE_9) + .name("lat") + .internalName("lat") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build(), + TableColumn.builder() + .id(COLUMN_9_3_ID) + .ordinalPosition(2) + .table(TABLE_9) + .name("lng") + .internalName("lng") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build()); + + public final static List<ColumnDto> TABLE_9_COLUMNS_DTO = List.of(ColumnDto.builder() + .id(COLUMN_9_1_ID) + .ordinalPosition(0) + .name(COLUMN_9_1_NAME) + .internalName(COLUMN_9_1_INTERNAL_NAME) + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(false) + .enums(null) + .sets(null) + .build(), + ColumnDto.builder() + .id(COLUMN_9_2_ID) + .ordinalPosition(1) + .name("lat") + .internalName("lat") + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build(), + ColumnDto.builder() + .id(COLUMN_9_3_ID) + .ordinalPosition(2) + .name("lng") + .internalName("lng") + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .enums(null) + .sets(null) + .build()); + + public final static Constraints TABLE_9_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_9) + .column(TABLE_9_COLUMNS.get(0)) + .id(9L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_9_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_9_BRIEF_DTO) + .column(TABLE_9_COLUMNS_BRIEF_0_DTO) + .id(9L) + .build()))) + .build(); + public final static String QUEUE_NAME = "dbrepo"; public final static String QUEUE_VHOST = "dbrepo"; public final static Boolean QUEUE_AUTO_DELETE = false; @@ -2359,7 +2633,9 @@ public abstract class BaseTest { 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 final static UUID ONTOLOGY_1_CREATED_BY = USER_1_ID; public final static Ontology ONTOLOGY_1 = Ontology.builder() @@ -2371,6 +2647,26 @@ public abstract class BaseTest { .rdfPath(ONTOLOGY_1_RDF_PATH) .build(); + public final static OntologyDto ONTOLOGY_1_DTO = OntologyDto.builder() + .id(ONTOLOGY_1_ID) + .prefix(ONTOLOGY_1_PREFIX) + .uri(ONTOLOGY_1_URI) + .uriPattern(ONTOLOGY_1_URI_PATTERN) + .sparqlEndpoint(ONTOLOGY_1_SPARQL_ENDPOINT) + .sparql(ONTOLOGY_1_SPARQL) + .rdfPath(ONTOLOGY_1_RDF_PATH) + .rdf(ONTOLOGY_1_RDF) + .build(); + + public final static OntologyBriefDto ONTOLOGY_1_BRIEF_DTO = OntologyBriefDto.builder() + .id(ONTOLOGY_1_ID) + .prefix(ONTOLOGY_1_PREFIX) + .uri(ONTOLOGY_1_URI) + .uriPattern(ONTOLOGY_1_URI_PATTERN) + .sparql(ONTOLOGY_1_SPARQL) + .rdf(ONTOLOGY_1_RDF) + .build(); + public final static OntologyCreateDto ONTOLOGY_1_CREATE_DTO = OntologyCreateDto.builder() .prefix(ONTOLOGY_1_PREFIX) .uri(ONTOLOGY_1_URI) @@ -2528,7 +2824,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_8_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_8_1_ID) .ordinalPosition(COLUMN_8_1_ORDINALPOS) - .table(TABLE_8_DTO) .name(COLUMN_8_1_NAME) .internalName(COLUMN_8_1_INTERNAL_NAME) .columnType(COLUMN_8_1_TYPE_DTO) @@ -2537,7 +2832,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_8_2_ID) .ordinalPosition(COLUMN_8_2_ORDINALPOS) - .table(TABLE_8_DTO) .name(COLUMN_8_2_NAME) .internalName(COLUMN_8_2_INTERNAL_NAME) .columnType(COLUMN_8_2_TYPE_DTO) @@ -2546,7 +2840,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_8_3_ID) .ordinalPosition(COLUMN_8_3_ORDINALPOS) - .table(TABLE_8_DTO) .name(COLUMN_8_3_NAME) .internalName(COLUMN_8_3_INTERNAL_NAME) .columnType(COLUMN_8_3_TYPE_DTO) @@ -2587,7 +2880,7 @@ public abstract class BaseTest { put(COLUMN_8_3_INTERNAL_NAME, null); }} )); - + @SuppressWarnings("java:S3599") public final static TableStatisticDto TABLE_8_STATISTIC_DTO = TableStatisticDto.builder() .columns(new HashMap<>() {{ @@ -2686,8 +2979,31 @@ public abstract class BaseTest { .isPersisted(QUERY_3_PERSISTED) .resultNumber(2L) .build(); - + + public final static Long QUERY_7_ID = 7L; 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_CREATED = Instant.now().minus(4, MINUTES); + public final static Instant QUERY_7_EXECUTION = Instant.now().minus(1, MINUTES); + public final static Instant QUERY_7_LAST_MODIFIED = Instant.ofEpochSecond(1541588454L); + 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 final static QueryDto QUERY_7_DTO = QueryDto.builder() + .id(QUERY_7_ID) + .databaseId(DATABASE_4_ID) + .query(QUERY_7_STATEMENT) + .queryNormalized(QUERY_7_STATEMENT) + .resultNumber(QUERY_7_RESULT_NUMBER) + .resultHash(QUERY_7_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_7_QUERY_HASH) + .execution(QUERY_7_EXECUTION) + .isPersisted(QUERY_7_PERSISTED) + .resultNumber(2L) + .build(); public final static Long QUERY_4_ID = 4L; public final static String QUERY_4_STATEMENT = "SELECT `id`, `value` FROM `mfcc`"; @@ -2914,14 +3230,14 @@ public abstract class BaseTest { .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>(List.of("id"))) .foreignKeys(new LinkedList<>()) - .uniques(List.of(List.of("date"))) + .uniques(new LinkedList<>(List.of(List.of("date")))) .build(); public final static ConstraintsCreateDto TABLE_1_CONSTRAINTS_CREATE_INVALID_DTO = ConstraintsCreateDto.builder() .checks(new LinkedHashSet<>()) .primaryKey(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) - .uniques(List.of(List.of("date"))) + .uniques(new LinkedList<>(List.of(List.of("date")))) .build(); public final static TableCreateDto TABLE_1_CREATE_DTO = TableCreateDto.builder() @@ -2957,7 +3273,6 @@ public abstract class BaseTest { .table(TABLE_2) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(TableColumnType.VARCHAR) .size(255L) .isNullAllowed(false) @@ -2970,7 +3285,6 @@ public abstract class BaseTest { .table(TABLE_2) .name("lat") .internalName("lat") - .ordinalPosition(1) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -2984,7 +3298,6 @@ public abstract class BaseTest { .table(TABLE_2) .name("lng") .internalName("lng") - .ordinalPosition(2) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -3009,12 +3322,11 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_2_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_2_1_ID) - .table(TABLE_2_DTO) .tableId(TABLE_2_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(0) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(false) @@ -3023,12 +3335,11 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(COLUMN_2_2_ID) - .table(TABLE_2_DTO) .tableId(TABLE_2_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(1) .name("lat") .internalName("lat") - .ordinalPosition(1) .columnType(ColumnTypeDto.DOUBLE) .size(22L) .isNullAllowed(true) @@ -3037,12 +3348,11 @@ public abstract class BaseTest { .build(), ColumnDto.builder() .id(COLUMN_2_3_ID) - .table(TABLE_2_DTO) .tableId(TABLE_2_ID) .databaseId(DATABASE_1_ID) + .ordinalPosition(2) .name("lng") .internalName("lng") - .ordinalPosition(2) .columnType(ColumnTypeDto.DOUBLE) .size(22L) .isNullAllowed(true) @@ -3516,7 +3826,6 @@ public abstract class BaseTest { public final static List<ColumnDto> TABLE_3_COLUMNS_DTO = List.of(ColumnDto.builder() .id(COLUMN_3_1_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.BIGINT) .name("id") @@ -3528,7 +3837,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_2_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("linie") @@ -3540,7 +3848,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_3_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("richtung") @@ -3552,7 +3859,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_4_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.DATE) .name("betriebsdatum") @@ -3564,7 +3870,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_5_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fahrzeug") @@ -3576,7 +3881,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_6_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("kurs") @@ -3588,7 +3892,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_7_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("seq_von") @@ -3600,7 +3903,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_8_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_diva_von") @@ -3612,7 +3914,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_9_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_punkt_diva_von") @@ -3624,7 +3925,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_10_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_kurz_von1") @@ -3636,7 +3936,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_11_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.DATE) .name("datum_von") @@ -3648,7 +3947,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_12_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("soll_an_von") @@ -3660,7 +3958,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_13_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("ist_an_von") @@ -3672,7 +3969,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_14_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("soll_ab_von") @@ -3684,7 +3980,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_15_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("ist_ab_von") @@ -3696,7 +3991,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_16_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("seq_nach") @@ -3708,7 +4002,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_17_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_diva_nach") @@ -3720,7 +4013,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_18_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_punkt_diva_nach") @@ -3732,7 +4024,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_19_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_kurz_nach1") @@ -3744,7 +4035,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_20_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.DATE) .name("datum_nach") @@ -3756,7 +4046,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_21_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("soll_an_nach") @@ -3768,7 +4057,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_22_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("ist_an_nach1") @@ -3780,7 +4068,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_23_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("soll_ab_nach") @@ -3792,7 +4079,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_24_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("ist_ab_nach") @@ -3804,7 +4090,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_25_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fahrt_id") @@ -3816,7 +4101,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_26_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fahrweg_id") @@ -3828,7 +4112,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_27_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fw_no") @@ -3840,7 +4123,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_28_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fw_typ") @@ -3852,7 +4134,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_29_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fw_kurz") @@ -3864,7 +4145,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_30_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("fw_lang") @@ -3876,7 +4156,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_31_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("umlauf_von") @@ -3888,7 +4167,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_32_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_id_von") @@ -3900,7 +4178,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_33_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_id_nach") @@ -3912,7 +4189,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_34_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_punkt_id_von") @@ -3924,7 +4200,6 @@ public abstract class BaseTest { ColumnDto.builder() .id(COLUMN_3_35_ID) .tableId(TABLE_3_ID) - .table(TABLE_3_DTO) .databaseId(DATABASE_1_ID) .columnType(ColumnTypeDto.INT) .name("halt_punkt_id_nach") @@ -4177,7 +4452,6 @@ public abstract class BaseTest { .id(COLUMN_5_1_ID) .ordinalPosition(0) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("id") .internalName("id") .columnType(ColumnTypeDto.BIGINT) @@ -4187,7 +4461,6 @@ public abstract class BaseTest { .id(COLUMN_5_2_ID) .ordinalPosition(1) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Animal Name") .internalName("animal_name") .columnType(ColumnTypeDto.VARCHAR) @@ -4197,7 +4470,6 @@ public abstract class BaseTest { .id(COLUMN_5_3_ID) .ordinalPosition(2) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Hair") .internalName("hair") .columnType(ColumnTypeDto.BOOL) @@ -4207,7 +4479,6 @@ public abstract class BaseTest { .id(COLUMN_5_4_ID) .ordinalPosition(3) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Feathers") .internalName("feathers") .columnType(ColumnTypeDto.BOOL) @@ -4217,7 +4488,6 @@ public abstract class BaseTest { .id(COLUMN_5_5_ID) .ordinalPosition(4) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Bread") .internalName("bread") .columnType(ColumnTypeDto.BOOL) @@ -4227,7 +4497,6 @@ public abstract class BaseTest { .id(COLUMN_5_6_ID) .ordinalPosition(5) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Eggs") .internalName("eggs") .columnType(ColumnTypeDto.BOOL) @@ -4237,7 +4506,6 @@ public abstract class BaseTest { .id(COLUMN_5_7_ID) .ordinalPosition(6) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Milk") .internalName("milk") .columnType(ColumnTypeDto.BOOL) @@ -4247,7 +4515,6 @@ public abstract class BaseTest { .id(COLUMN_5_8_ID) .ordinalPosition(7) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Water") .internalName("water") .columnType(ColumnTypeDto.BOOL) @@ -4257,7 +4524,6 @@ public abstract class BaseTest { .id(COLUMN_5_9_ID) .ordinalPosition(8) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Airborne") .internalName("airborne") .columnType(ColumnTypeDto.BOOL) @@ -4267,7 +4533,6 @@ public abstract class BaseTest { .id(COLUMN_5_10_ID) .ordinalPosition(9) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Waterborne") .internalName("waterborne") .columnType(ColumnTypeDto.BOOL) @@ -4277,7 +4542,6 @@ public abstract class BaseTest { .id(COLUMN_5_11_ID) .ordinalPosition(10) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Aquantic") .internalName("aquantic") .columnType(ColumnTypeDto.BOOL) @@ -4287,7 +4551,6 @@ public abstract class BaseTest { .id(COLUMN_5_12_ID) .ordinalPosition(11) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Predator") .internalName("predator") .columnType(ColumnTypeDto.BOOL) @@ -4297,7 +4560,6 @@ public abstract class BaseTest { .id(COLUMN_5_13_ID) .ordinalPosition(12) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Backbone") .internalName("backbone") .columnType(ColumnTypeDto.BOOL) @@ -4307,7 +4569,6 @@ public abstract class BaseTest { .id(COLUMN_5_14_ID) .ordinalPosition(13) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Breathes") .internalName("breathes") .columnType(ColumnTypeDto.BOOL) @@ -4317,7 +4578,6 @@ public abstract class BaseTest { .id(COLUMN_5_15_ID) .ordinalPosition(14) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Venomous") .internalName("venomous") .columnType(ColumnTypeDto.BOOL) @@ -4327,7 +4587,6 @@ public abstract class BaseTest { .id(COLUMN_5_16_ID) .ordinalPosition(15) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Fin") .internalName("fin") .columnType(ColumnTypeDto.BOOL) @@ -4337,7 +4596,6 @@ public abstract class BaseTest { .id(COLUMN_5_17_ID) .ordinalPosition(16) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Legs") .internalName("legs") .columnType(ColumnTypeDto.INT) @@ -4347,7 +4605,6 @@ public abstract class BaseTest { .id(COLUMN_5_18_ID) .ordinalPosition(17) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Tail") .internalName("tail") .columnType(ColumnTypeDto.DECIMAL) @@ -4357,7 +4614,6 @@ public abstract class BaseTest { .id(COLUMN_5_19_ID) .ordinalPosition(18) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Domestic") .internalName("domestic") .columnType(ColumnTypeDto.BOOL) @@ -4367,7 +4623,6 @@ public abstract class BaseTest { .id(COLUMN_5_20_ID) .ordinalPosition(19) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Catsize") .internalName("catsize") .columnType(ColumnTypeDto.BOOL) @@ -4377,7 +4632,6 @@ public abstract class BaseTest { .id(COLUMN_5_21_ID) .ordinalPosition(20) .tableId(TABLE_5_ID) - .table(TABLE_5_DTO) .name("Class Type") .internalName("class_type") .columnType(ColumnTypeDto.DECIMAL) @@ -4385,9 +4639,9 @@ public abstract class BaseTest { .build()); public final static List<ForeignKeyCreateDto> TABLE_5_FOREIGN_KEYS_INVALID_CREATE = List.of(ForeignKeyCreateDto.builder() - .columns(List.of("somecolumn")) + .columns(new LinkedList<>(List.of("somecolumn"))) .referencedTable("sometable") - .referencedColumns(List.of("someothercolumn")) + .referencedColumns(new LinkedList<>(List.of("someothercolumn"))) .build()); public final static ConstraintsCreateDto TABLE_5_CONSTRAINTS_INVALID_CREATE = ConstraintsCreateDto.builder() @@ -4502,7 +4756,7 @@ public abstract class BaseTest { public final static ConstraintsCreateDto TABLE_5_CREATE_CONSTRAINTS_DTO = ConstraintsCreateDto.builder() .primaryKey(Set.of("id")) - .uniques(List.of(List.of("id"))) + .uniques(new LinkedList<>(List.of(List.of("id")))) .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .build(); @@ -4587,7 +4841,6 @@ public abstract class BaseTest { .id(67L) .ordinalPosition(0) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("id") .internalName("id") .columnType(ColumnTypeDto.BIGINT) @@ -4597,7 +4850,6 @@ public abstract class BaseTest { .id(68L) .ordinalPosition(1) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("firstname") .internalName("firstname") .columnType(ColumnTypeDto.VARCHAR) @@ -4607,7 +4859,6 @@ public abstract class BaseTest { .id(69L) .ordinalPosition(2) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("lastname") .internalName("lastname") .columnType(ColumnTypeDto.VARCHAR) @@ -4617,7 +4868,6 @@ public abstract class BaseTest { .id(70L) .ordinalPosition(3) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("birth") .internalName("birth") .columnType(ColumnTypeDto.YEAR) @@ -4627,7 +4877,6 @@ public abstract class BaseTest { .id(71L) .ordinalPosition(4) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("reminder") .internalName("reminder") .columnType(ColumnTypeDto.TIME) @@ -4637,7 +4886,6 @@ public abstract class BaseTest { .id(72L) .ordinalPosition(5) .tableId(TABLE_6_ID) - .table(TABLE_6_DTO) .name("ref_id") .internalName("ref_id") .columnType(ColumnTypeDto.BIGINT) @@ -4648,9 +4896,9 @@ public abstract class BaseTest { List.of("firstname", "lastname")); public final static List<ForeignKeyCreateDto> TABLE_6_FOREIGN_KEYS_CREATE = List.of(ForeignKeyCreateDto.builder() - .columns(List.of("ref_id")) + .columns(new LinkedList<>(List.of("ref_id"))) .referencedTable("zoo") - .referencedColumns(List.of("id")) + .referencedColumns(new LinkedList<>(List.of("id"))) .build()); public final static Set<String> TABLE_6_CHECKS_CREATE = Set.of("firstname != lastname"); @@ -4723,7 +4971,6 @@ public abstract class BaseTest { .id(COLUMN_7_1_ID) .ordinalPosition(0) .tableId(TABLE_7_ID) - .table(TABLE_7_DTO) .name("name_id") .internalName("name_id") .columnType(ColumnTypeDto.BIGINT) @@ -4733,7 +4980,6 @@ public abstract class BaseTest { .id(COLUMN_7_2_ID) .ordinalPosition(1) .tableId(TABLE_7_ID) - .table(TABLE_7_DTO) .name("zoo_id") .internalName("zoo_id") .columnType(ColumnTypeDto.BIGINT) @@ -4754,34 +5000,37 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_1_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(1L) + .ordinalPosition(0) .databaseId(DATABASE_1_ID) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(false) .build(), ViewColumnDto.builder() .id(2L) + .ordinalPosition(1) .databaseId(DATABASE_1_ID) .name("lat") .internalName("lat") - .ordinalPosition(1) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) .build(), ViewColumnDto.builder() .id(3L) + .ordinalPosition(2) .databaseId(DATABASE_1_ID) .name("lng") .internalName("lng") - .ordinalPosition(2) - .columnType(ColumnTypeDto.DOUBLE) - .size(22L) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) .isNullAllowed(true) - .build()); + .build() + ); public final static View VIEW_1 = View.builder() .id(VIEW_1_ID) @@ -4795,6 +5044,7 @@ public abstract class BaseTest { .queryHash(VIEW_1_QUERY_HASH) .ownedBy(USER_1_ID) .owner(USER_1) + .identifiers(new LinkedList<>()) /* IDENTIFIER_3 */ .columns(null) /* VIEW_1_COLUMNS */ .build(); @@ -4823,7 +5073,6 @@ public abstract class BaseTest { .ordinalPosition(0) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(TableColumnType.VARCHAR) .size(255L) .isNullAllowed(false) @@ -4834,7 +5083,6 @@ public abstract class BaseTest { .ordinalPosition(1) .name("lat") .internalName("lat") - .ordinalPosition(1) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -4846,7 +5094,6 @@ public abstract class BaseTest { .ordinalPosition(2) .name("lng") .internalName("lng") - .ordinalPosition(2) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -4863,11 +5110,11 @@ public abstract class BaseTest { .vdbid(VIEW_1_DATABASE_ID) .isPublic(VIEW_1_PUBLIC) .isSchemaPublic(VIEW_1_SCHEMA_PUBLIC) + .identifiers(null /* VIEW_1_DTO_IDENTIFIERS */) .owner(USER_1_BRIEF_DTO) .query(VIEW_1_QUERY) .queryHash(VIEW_1_QUERY_HASH) .columns(VIEW_1_COLUMNS_DTO) - .database(null) .build(); public final static PrivilegedViewDto VIEW_1_PRIVILEGED_DTO = PrivilegedViewDto.builder() @@ -4918,26 +5165,29 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_2_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(4L) - .name("date") + .databaseId(DATABASE_1_ID) + .ordinalPosition(0) + .name("Date") .internalName("date") - .ordinalPosition(1) .columnType(ColumnTypeDto.DATE) .isNullAllowed(true) .build(), ViewColumnDto.builder() .id(5L) + .databaseId(DATABASE_1_ID) + .ordinalPosition(1) .name("loc") .internalName("loc") - .ordinalPosition(2) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(true) .build(), ViewColumnDto.builder() .id(6L) - .name("mintemp") - .internalName("mintemp") - .ordinalPosition(3) + .databaseId(DATABASE_1_ID) + .ordinalPosition(2) + .name("Rainfall") + .internalName("rainfall") .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -4945,9 +5195,10 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(7L) - .name("rainfall") - .internalName("rainfall") - .ordinalPosition(4) + .databaseId(DATABASE_1_ID) + .ordinalPosition(3) + .name("MinTemp") + .internalName("mintemp") .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -5073,9 +5324,10 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_3_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(8L) + .databaseId(DATABASE_1_ID) + .ordinalPosition(0) .name("MinTemp") .internalName("mintemp") - .ordinalPosition(0) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -5083,30 +5335,31 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(9L) + .databaseId(DATABASE_1_ID) + .ordinalPosition(1) .name("Rainfall") .internalName("rainfall") - .ordinalPosition(1) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) - .concept(CONCEPT_1_DTO) - .unit(UNIT_1_DTO) .isNullAllowed(true) .build(), ViewColumnDto.builder() .id(10L) + .databaseId(DATABASE_1_ID) + .ordinalPosition(2) .name("Location") .internalName("location") - .ordinalPosition(2) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(true) .build(), ViewColumnDto.builder() .id(11L) + .databaseId(DATABASE_1_ID) + .ordinalPosition(3) .name("Date") .internalName("date") - .ordinalPosition(3) .columnType(ColumnTypeDto.DATE) .isNullAllowed(true) .build() @@ -5230,6 +5483,7 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_4_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(12L) + .databaseId(DATABASE_2_ID) .ordinalPosition(0) .name("Animal Name") .internalName("animal_name") @@ -5238,6 +5492,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(13L) + .databaseId(DATABASE_2_ID) .ordinalPosition(1) .name("Hair") .internalName("hair") @@ -5246,6 +5501,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(14L) + .databaseId(DATABASE_2_ID) .ordinalPosition(2) .name("Feathers") .internalName("feathers") @@ -5254,6 +5510,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(15L) + .databaseId(DATABASE_2_ID) .ordinalPosition(3) .name("Eggs") .internalName("eggs") @@ -5262,6 +5519,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(16L) + .databaseId(DATABASE_2_ID) .ordinalPosition(4) .name("Milk") .internalName("milk") @@ -5270,6 +5528,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(17L) + .databaseId(DATABASE_2_ID) .ordinalPosition(5) .name("Airborne") .internalName("airborne") @@ -5278,6 +5537,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(18L) + .databaseId(DATABASE_2_ID) .ordinalPosition(6) .name("Aquantic") .internalName("aquantic") @@ -5286,6 +5546,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(19L) + .databaseId(DATABASE_2_ID) .ordinalPosition(7) .name("Predator") .internalName("predator") @@ -5294,6 +5555,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(20L) + .databaseId(DATABASE_2_ID) .ordinalPosition(8) .name("Backbone") .internalName("backbone") @@ -5302,6 +5564,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(21L) + .databaseId(DATABASE_2_ID) .ordinalPosition(9) .name("Breathes") .internalName("breathes") @@ -5310,6 +5573,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(22L) + .databaseId(DATABASE_2_ID) .ordinalPosition(10) .name("Venomous") .internalName("venomous") @@ -5318,6 +5582,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(23L) + .databaseId(DATABASE_2_ID) .ordinalPosition(11) .name("Fin") .internalName("fin") @@ -5326,6 +5591,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(24L) + .databaseId(DATABASE_2_ID) .ordinalPosition(12) .name("Legs") .internalName("legs") @@ -5334,6 +5600,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(25L) + .databaseId(DATABASE_2_ID) .ordinalPosition(13) .name("Tail") .internalName("tail") @@ -5342,6 +5609,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(26L) + .databaseId(DATABASE_2_ID) .ordinalPosition(14) .name("Domestic") .internalName("domestic") @@ -5350,6 +5618,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(27L) + .databaseId(DATABASE_2_ID) .ordinalPosition(15) .name("Catsize") .internalName("catsize") @@ -5358,6 +5627,7 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(28L) + .databaseId(DATABASE_2_ID) .ordinalPosition(16) .name("Class Type") .internalName("class_type") @@ -5620,7 +5890,6 @@ public abstract class BaseTest { .ordinalPosition(0) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(TableColumnType.VARCHAR) .size(255L) .isNullAllowed(false) @@ -5631,7 +5900,6 @@ public abstract class BaseTest { .ordinalPosition(1) .name("lat") .internalName("lat") - .ordinalPosition(1) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -5643,7 +5911,6 @@ public abstract class BaseTest { .ordinalPosition(2) .name("lng") .internalName("lng") - .ordinalPosition(2) .columnType(TableColumnType.DECIMAL) .size(10L) .d(0L) @@ -5654,20 +5921,20 @@ public abstract class BaseTest { public final static List<ViewColumnDto> VIEW_5_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(29L) + .databaseId(DATABASE_3_ID) .ordinalPosition(0) .name("location") .internalName("location") - .ordinalPosition(0) .columnType(ColumnTypeDto.VARCHAR) .size(255L) .isNullAllowed(false) .build(), ViewColumnDto.builder() .id(30L) + .databaseId(DATABASE_3_ID) .ordinalPosition(1) .name("lat") .internalName("lat") - .ordinalPosition(1) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -5675,10 +5942,10 @@ public abstract class BaseTest { .build(), ViewColumnDto.builder() .id(31L) + .databaseId(DATABASE_3_ID) .ordinalPosition(2) .name("lng") .internalName("lng") - .ordinalPosition(2) .columnType(ColumnTypeDto.DECIMAL) .size(10L) .d(0L) @@ -5769,6 +6036,8 @@ public abstract class BaseTest { 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"; @@ -6057,8 +6326,8 @@ public abstract class BaseTest { public final static Identifier IDENTIFIER_1_WITH_DOI = Identifier.builder() .id(IDENTIFIER_1_ID) .queryId(IDENTIFIER_1_QUERY_ID) - .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1)) - .titles(List.of(IDENTIFIER_1_TITLE_1, IDENTIFIER_1_TITLE_2)) + .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) @@ -6074,9 +6343,9 @@ public abstract class BaseTest { .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE) .owner(USER_1) - .licenses(List.of(LICENSE_1)) - .creators(List.of(IDENTIFIER_1_CREATOR_1)) - .funders(List.of(IDENTIFIER_1_FUNDER_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(); @@ -6084,8 +6353,8 @@ public abstract class BaseTest { .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .queryId(IDENTIFIER_1_QUERY_ID) - .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_DTO)) - .titles(List.of(IDENTIFIER_1_TITLE_1_DTO, IDENTIFIER_1_TITLE_2_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_DTO, IDENTIFIER_1_TITLE_2_DTO))) .doi(IDENTIFIER_1_DOI) .execution(IDENTIFIER_1_EXECUTION) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) @@ -6097,10 +6366,10 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_1_RESULT_NUMBER) .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) - .owner(USER_1_DTO) - .licenses(List.of(LICENSE_1_DTO)) - .creators(List.of(IDENTIFIER_1_CREATOR_1_DTO)) - .funders(List.of(IDENTIFIER_1_FUNDER_1_DTO)) + .owner(USER_1_BRIEF_DTO) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) + .creators(new LinkedList<>(List.of(IDENTIFIER_1_CREATOR_1_DTO))) + .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_DTO))) .status(IDENTIFIER_1_STATUS_TYPE_DTO) .build(); @@ -6108,7 +6377,7 @@ public abstract class BaseTest { .id(IDENTIFIER_1_ID) .databaseId(DATABASE_1_ID) .queryId(IDENTIFIER_1_QUERY_ID) - .titles(List.of(IDENTIFIER_1_TITLE_1_DTO, IDENTIFIER_1_TITLE_2_DTO)) + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_DTO, IDENTIFIER_1_TITLE_2_DTO))) .doi(IDENTIFIER_1_DOI) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publisher(IDENTIFIER_1_PUBLISHER) @@ -6121,16 +6390,16 @@ public abstract class BaseTest { .type(IDENTIFIER_1_TYPE_DTO) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publisher(IDENTIFIER_1_PUBLISHER) - .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) - .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO))) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) .doi(IDENTIFIER_1_DOI) - .licenses(List.of(LICENSE_1_DTO)) - .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) - .funders(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO)) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) + .creators(new LinkedList<>(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO))) + .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO))) .build(); public final static IdentifierCreateDto IDENTIFIER_1_CREATE_WITH_DOI_DTO = IdentifierCreateDto.builder() @@ -6139,45 +6408,45 @@ public abstract class BaseTest { .doi(IDENTIFIER_1_DOI) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publisher(IDENTIFIER_1_PUBLISHER) - .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) - .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO))) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) - .licenses(List.of(LICENSE_1_DTO)) - .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) - .funders(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO)) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) + .creators(new LinkedList<>(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO))) + .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO))) .build(); public final static IdentifierSaveDto IDENTIFIER_1_SAVE_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_1_ID) .databaseId(IDENTIFIER_1_DATABASE_ID) - .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) - .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO, IDENTIFIER_1_TITLE_2_CREATE_DTO))) .relatedIdentifiers(new LinkedList<>()) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) - .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) - .funders(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO)) + .creators(new LinkedList<>(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO))) + .funders(new LinkedList<>(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO))) .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) - .licenses(List.of(LICENSE_1_DTO)) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .build(); public final static IdentifierSaveDto IDENTIFIER_1_SAVE_MODIFY_DTO = IdentifierSaveDto.builder() .id(IDENTIFIER_1_ID) .databaseId(IDENTIFIER_1_DATABASE_ID) - .descriptions(List.of()) // <<< - .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) // <<< + .descriptions(new LinkedList<>(List.of())) // <<< + .titles(new LinkedList<>(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO))) // <<< .relatedIdentifiers(new LinkedList<>()) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) - .creators(List.of()) // <<< - .funders(List.of()) // <<< + .creators(new LinkedList<>(List.of())) // <<< + .funders(new LinkedList<>(List.of())) // <<< .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) - .licenses(List.of()) // <<< + .licenses(new LinkedList<>(List.of())) // <<< .build(); public final static Long IDENTIFIER_5_ID = 5L; @@ -6283,6 +6552,9 @@ public abstract class BaseTest { .nameIdentifier(CREATOR_1_ORCID) .nameIdentifierScheme(NameIdentifierSchemeTypeDto.ORCID) .affiliation(CREATOR_1_AFFIL) + .affiliationIdentifier(CREATOR_1_AFFIL_ROR) + .affiliationIdentifierScheme(CREATOR_1_AFFIL_TYPE_DTO) + .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); public final static CreatorSaveDto IDENTIFIER_5_CREATOR_1_CREATE_DTO = CreatorSaveDto.builder() @@ -6372,8 +6644,8 @@ public abstract class BaseTest { .id(IDENTIFIER_5_ID) .databaseId(DATABASE_2_ID) .queryId(IDENTIFIER_5_QUERY_ID) - .descriptions(List.of(IDENTIFIER_5_DESCRIPTION_1_DTO)) - .titles(List.of(IDENTIFIER_5_TITLE_1_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_5_DESCRIPTION_1_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_5_TITLE_1_DTO))) .doi(IDENTIFIER_5_DOI) .execution(IDENTIFIER_5_EXECUTION) .publicationDay(IDENTIFIER_5_PUBLICATION_DAY) @@ -6386,15 +6658,16 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_5_RESULT_NUMBER) .publisher(IDENTIFIER_5_PUBLISHER) .type(IDENTIFIER_5_TYPE_DTO) - .owner(USER_2_DTO) - .creators(List.of(IDENTIFIER_5_CREATOR_1_DTO, IDENTIFIER_5_CREATOR_2_DTO)) + .owner(USER_2_BRIEF_DTO) + .status(IDENTIFIER_5_STATUS_TYPE_DTO) + .creators(new LinkedList<>(List.of(IDENTIFIER_5_CREATOR_1_DTO, IDENTIFIER_5_CREATOR_2_DTO))) .build(); public final static IdentifierBriefDto IDENTIFIER_5_BRIEF_DTO = IdentifierBriefDto.builder() .id(IDENTIFIER_5_ID) .databaseId(DATABASE_2_ID) .queryId(IDENTIFIER_5_QUERY_ID) - .titles(List.of(IDENTIFIER_5_TITLE_1_DTO)) + .titles(new LinkedList<>(List.of(IDENTIFIER_5_TITLE_1_DTO))) .doi(IDENTIFIER_5_DOI) .publicationYear(IDENTIFIER_5_PUBLICATION_YEAR) .publisher(IDENTIFIER_5_PUBLISHER) @@ -6433,15 +6706,15 @@ public abstract class BaseTest { .id(IDENTIFIER_5_ID) .queryId(IDENTIFIER_5_QUERY_ID) .databaseId(IDENTIFIER_5_DATABASE_ID) - .descriptions(List.of(IDENTIFIER_5_DESCRIPTION_1_CREATE_DTO)) - .titles(List.of(IDENTIFIER_5_TITLE_1_CREATE_DTO)) - .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_5_DESCRIPTION_1_CREATE_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_5_TITLE_1_CREATE_DTO))) + .relatedIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO))) .publicationDay(IDENTIFIER_5_PUBLICATION_DAY) .publicationMonth(IDENTIFIER_5_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_5_PUBLICATION_YEAR) - .creators(List.of(IDENTIFIER_5_CREATOR_1_CREATE_DTO, IDENTIFIER_5_CREATOR_2_CREATE_DTO)) + .creators(new LinkedList<>(List.of(IDENTIFIER_5_CREATOR_1_CREATE_DTO, IDENTIFIER_5_CREATOR_2_CREATE_DTO))) .publisher(IDENTIFIER_5_PUBLISHER) - .licenses(List.of(LICENSE_1_DTO)) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .type(IDENTIFIER_5_TYPE_DTO) .build(); @@ -6540,6 +6813,7 @@ public abstract class BaseTest { .affiliation(CREATOR_1_AFFIL) .affiliationIdentifier(CREATOR_1_AFFIL_ROR) .affiliationIdentifierScheme(CREATOR_1_AFFIL_TYPE) + .affiliationIdentifierSchemeUri(CREATOR_1_AFFIL_URI) .build(); public final static CreatorDto IDENTIFIER_6_CREATOR_1_DTO = CreatorDto.builder() @@ -6608,7 +6882,10 @@ public abstract class BaseTest { .creatorName(CREATOR_3_NAME) .nameIdentifier(CREATOR_3_ORCID) .nameIdentifierScheme(NameIdentifierSchemeType.ORCID) + .affiliation(CREATOR_3_AFFIL) .affiliationIdentifier(CREATOR_3_AFFIL_ROR) + .affiliationIdentifierScheme(CREATOR_3_AFFIL_SCHEME_TYPE) + .affiliationIdentifierSchemeUri(CREATOR_3_AFFIL_URI) .build(); public final static CreatorDto IDENTIFIER_6_CREATOR_3_DTO = CreatorDto.builder() @@ -6620,6 +6897,8 @@ public abstract class BaseTest { .nameIdentifierScheme(NameIdentifierSchemeTypeDto.ORCID) .affiliation(CREATOR_3_AFFIL) .affiliationIdentifier(CREATOR_3_AFFIL_ROR) + .affiliationIdentifierScheme(CREATOR_3_AFFIL_SCHEME_TYPE_DTO) + .affiliationIdentifierSchemeUri(CREATOR_3_AFFIL_URI) .build(); public final static Identifier IDENTIFIER_6 = Identifier.builder() @@ -6652,8 +6931,8 @@ public abstract class BaseTest { .id(IDENTIFIER_6_ID) .databaseId(DATABASE_3_ID) .queryId(IDENTIFIER_6_QUERY_ID) - .descriptions(List.of(IDENTIFIER_6_DESCRIPTION_1_DTO)) - .titles(List.of(IDENTIFIER_6_TITLE_1_DTO)) + .descriptions(new LinkedList<>(List.of(IDENTIFIER_6_DESCRIPTION_1_DTO))) + .titles(new LinkedList<>(List.of(IDENTIFIER_6_TITLE_1_DTO))) .doi(IDENTIFIER_6_DOI) .execution(IDENTIFIER_6_EXECUTION) .publicationDay(IDENTIFIER_6_PUBLICATION_DAY) @@ -6666,7 +6945,7 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_6_RESULT_NUMBER) .publisher(IDENTIFIER_6_PUBLISHER) .type(IDENTIFIER_6_TYPE_DTO) - .owner(USER_3_DTO) + .owner(USER_3_BRIEF_DTO) .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .creators(new LinkedList<>(List.of(IDENTIFIER_6_CREATOR_1_DTO, IDENTIFIER_6_CREATOR_2_DTO, IDENTIFIER_6_CREATOR_3_DTO))) .status(IDENTIFIER_6_STATUS_TYPE_DTO) @@ -6677,7 +6956,7 @@ public abstract class BaseTest { .id(IDENTIFIER_6_ID) .databaseId(DATABASE_3_ID) .queryId(IDENTIFIER_6_QUERY_ID) - .titles(List.of(IDENTIFIER_6_TITLE_1_DTO)) + .titles(new LinkedList<>(List.of(IDENTIFIER_6_TITLE_1_DTO))) .doi(IDENTIFIER_6_DOI) .publicationYear(IDENTIFIER_6_PUBLICATION_YEAR) .publisher(IDENTIFIER_6_PUBLISHER) @@ -6772,10 +7051,11 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_7_RESULT_NUMBER) .publisher(IDENTIFIER_7_PUBLISHER) .type(IDENTIFIER_7_TYPE_DTO) - .owner(USER_4_DTO) + .owner(USER_4_BRIEF_DTO) + .relatedIdentifiers(new LinkedList<>()) .licenses(new LinkedList<>()) .funders(new LinkedList<>()) - .creators(new LinkedList<>()) + .creators(new LinkedList<>(List.of(IDENTIFIER_7_CREATOR_1_DTO))) .status(IDENTIFIER_7_STATUS_TYPE_DTO) .build(); @@ -6803,7 +7083,7 @@ public abstract class BaseTest { .relatedIdentifiers(new LinkedList<>()) .publicationMonth(IDENTIFIER_7_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_7_PUBLICATION_YEAR) - .creators(List.of(IDENTIFIER_7_CREATOR_1_CREATE_DTO)) + .creators(new LinkedList<>(List.of(IDENTIFIER_7_CREATOR_1_CREATE_DTO))) .funders(new LinkedList<>()) .licenses(new LinkedList<>()) .publisher(IDENTIFIER_7_PUBLISHER) @@ -6885,7 +7165,7 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_2_RESULT_NUMBER) .publisher(IDENTIFIER_2_PUBLISHER) .type(IDENTIFIER_2_TYPE_DTO) - .owner(USER_1_DTO) + .owner(USER_1_BRIEF_DTO) .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .creators(new LinkedList<>()) .status(IDENTIFIER_2_STATUS_TYPE_DTO) @@ -6915,7 +7195,7 @@ public abstract class BaseTest { .creators(new LinkedList<>()) .publisher(IDENTIFIER_2_PUBLISHER) .type(IDENTIFIER_2_TYPE_DTO) - .licenses(List.of(LICENSE_1_DTO)) + .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .queryId(QUERY_1_ID) .build(); @@ -6986,7 +7266,7 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_3_RESULT_NUMBER) .publisher(IDENTIFIER_3_PUBLISHER) .type(IDENTIFIER_3_TYPE_DTO) - .owner(USER_1_DTO) + .owner(USER_1_BRIEF_DTO) .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .creators(new LinkedList<>()) .status(IDENTIFIER_3_STATUS_TYPE_DTO) @@ -7085,7 +7365,7 @@ public abstract class BaseTest { .resultNumber(IDENTIFIER_4_RESULT_NUMBER) .publisher(IDENTIFIER_4_PUBLISHER) .type(IDENTIFIER_4_TYPE_DTO) - .owner(USER_1_DTO) + .owner(USER_1_BRIEF_DTO) .licenses(new LinkedList<>(List.of(LICENSE_1_DTO))) .creators(new LinkedList<>()) .status(IDENTIFIER_4_STATUS_TYPE_DTO) @@ -7161,6 +7441,14 @@ public abstract class BaseTest { .displayEnd(BANNER_MESSAGE_1_END) .build(); + public final static BannerMessageDto BANNER_MESSAGE_1_DTO = BannerMessageDto.builder() + .id(BANNER_MESSAGE_1_ID) + .message(BANNER_MESSAGE_1_MESSAGE) + .type(BANNER_MESSAGE_1_TYPE_DTO) + .displayStart(BANNER_MESSAGE_1_START) + .displayEnd(BANNER_MESSAGE_1_END) + .build(); + public final static BannerMessageCreateDto BANNER_MESSAGE_1_CREATE_DTO = BannerMessageCreateDto.builder() .message(BANNER_MESSAGE_1_MESSAGE) .type(BANNER_MESSAGE_1_TYPE_DTO) @@ -7205,7 +7493,7 @@ public abstract class BaseTest { .isSchemaPublic(DATABASE_1_SCHEMA_PUBLIC) .name(DATABASE_1_NAME) .description(DATABASE_1_DESCRIPTION) - .identifiers(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4)) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))) .cid(CONTAINER_1_ID) .container(CONTAINER_1) .internalName(DATABASE_1_INTERNALNAME) @@ -7233,21 +7521,22 @@ public abstract class BaseTest { .container(CONTAINER_1_BRIEF_DTO) .internalName(DATABASE_1_INTERNALNAME) .exchangeName(DATABASE_1_EXCHANGE) - .identifiers(List.of(IDENTIFIER_1_BRIEF_DTO, IDENTIFIER_2_BRIEF_DTO, IDENTIFIER_3_BRIEF_DTO, IDENTIFIER_4_BRIEF_DTO)) - .tables(List.of(TABLE_1_BRIEF_DTO, TABLE_2_BRIEF_DTO, TABLE_3_BRIEF_DTO, TABLE_4_BRIEF_DTO)) - .views(List.of(VIEW_1_BRIEF_DTO, VIEW_2_BRIEF_DTO, VIEW_3_BRIEF_DTO)) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_1_BRIEF_DTO, IDENTIFIER_2_BRIEF_DTO, IDENTIFIER_3_BRIEF_DTO, IDENTIFIER_4_BRIEF_DTO))) + .tables(new LinkedList<>(List.of(TABLE_1_BRIEF_DTO, TABLE_2_BRIEF_DTO, TABLE_3_BRIEF_DTO, TABLE_4_BRIEF_DTO))) + .views(new LinkedList<>(List.of(VIEW_1_BRIEF_DTO, VIEW_2_BRIEF_DTO, VIEW_3_BRIEF_DTO))) .build(); public final static PrivilegedDatabaseDto DATABASE_1_PRIVILEGED_DTO = PrivilegedDatabaseDto.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) .exchangeName(DATABASE_1_EXCHANGE) - .identifiers(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO)) - .tables(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO)) - .views(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO)) + .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))) + .views(new LinkedList<>(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO))) .owner(USER_1_BRIEF_DTO) .lastRetrieved(Instant.now()) .build(); @@ -7386,13 +7675,14 @@ public abstract class BaseTest { public final static PrivilegedDatabaseDto DATABASE_2_PRIVILEGED_DTO = PrivilegedDatabaseDto.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) .exchangeName(DATABASE_2_EXCHANGE) - .identifiers(List.of(IDENTIFIER_5_DTO)) - .tables(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO)) - .views(List.of(VIEW_4_DTO)) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_DTO))) + .tables(new LinkedList<>(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO))) + .views(new LinkedList<>(List.of(VIEW_4_DTO))) .owner(USER_2_BRIEF_DTO) .lastRetrieved(Instant.now()) .build(); @@ -7404,9 +7694,9 @@ public abstract class BaseTest { .container(CONTAINER_1_BRIEF_DTO) .internalName(DATABASE_2_INTERNALNAME) .exchangeName(DATABASE_2_EXCHANGE) - .identifiers(List.of(IDENTIFIER_5_BRIEF_DTO)) - .tables(List.of(TABLE_5_BRIEF_DTO, TABLE_6_BRIEF_DTO, TABLE_7_BRIEF_DTO)) - .views(List.of(VIEW_4_BRIEF_DTO)) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_BRIEF_DTO))) + .tables(new LinkedList<>(List.of(TABLE_5_BRIEF_DTO, TABLE_6_BRIEF_DTO, TABLE_7_BRIEF_DTO))) + .views(new LinkedList<>(List.of(VIEW_4_BRIEF_DTO))) .identifiers(new LinkedList<>()) .owner(USER_2_BRIEF_DTO) .build(); @@ -7524,7 +7814,7 @@ public abstract class BaseTest { .tables(new LinkedList<>()) .views(new LinkedList<>()) .accesses(new LinkedList<>()) /* DATABASE_3_USER_1_WRITE_ALL_ACCESS */ - .identifiers(new LinkedList<>()) + .identifiers(new LinkedList<>()) /* IDENTIFIER_6 */ .build(); public final static DatabaseAccess DATABASE_3_USER_1_READ_ACCESS = DatabaseAccess.builder() @@ -7637,13 +7927,14 @@ public abstract class BaseTest { public final static PrivilegedDatabaseDto DATABASE_3_PRIVILEGED_DTO = PrivilegedDatabaseDto.builder() .id(DATABASE_3_ID) .isPublic(DATABASE_3_PUBLIC) + .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) .name(DATABASE_3_NAME) .container(CONTAINER_1_PRIVILEGED_DTO) .internalName(DATABASE_3_INTERNALNAME) .exchangeName(DATABASE_3_EXCHANGE) - .identifiers(List.of(IDENTIFIER_6_DTO)) - .tables(List.of(TABLE_8_DTO)) - .views(List.of(VIEW_5_DTO)) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_6_DTO))) + .tables(new LinkedList<>(List.of(TABLE_8_DTO))) + .views(new LinkedList<>(List.of(VIEW_5_DTO))) .owner(USER_3_BRIEF_DTO) .lastRetrieved(Instant.now()) .build(); @@ -7694,6 +7985,21 @@ public abstract class BaseTest { .identifiers(new LinkedList<>()) .build(); + public final static PrivilegedDatabaseDto DATABASE_4_PRIVILEGED_DTO = PrivilegedDatabaseDto.builder() + .id(DATABASE_4_ID) + .isPublic(DATABASE_4_PUBLIC) + .isSchemaPublic(DATABASE_4_SCHEMA_PUBLIC) + .name(DATABASE_4_NAME) + .container(CONTAINER_1_PRIVILEGED_DTO) + .internalName(DATABASE_4_INTERNALNAME) + .exchangeName(DATABASE_4_EXCHANGE) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_7_DTO))) + .tables(new LinkedList<>(List.of(TABLE_9_DTO))) + .views(new LinkedList<>(List.of())) + .owner(USER_3_BRIEF_DTO) + .lastRetrieved(Instant.now()) + .build(); + public final static DatabaseAccess DATABASE_4_USER_1_READ_ACCESS = DatabaseAccess.builder() .type(AccessType.READ) .hdbid(DATABASE_4_ID) @@ -7757,6 +8063,8 @@ public abstract class BaseTest { .huserid(USER_3_ID) .build(); + public final static List<IdentifierDto> VIEW_1_DTO_IDENTIFIERS = List.of(IDENTIFIER_3_DTO); + public final static Constraints TABLE_1_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) @@ -7928,6 +8236,7 @@ public abstract class BaseTest { public final static Constraints TABLE_7_CONSTRAINTS = Constraints.builder() .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>(List.of(ForeignKey.builder() + .id(8L) .name("fk_name_id") .onDelete(ReferenceType.NO_ACTION) .references(new LinkedList<>(List.of(ForeignKeyReference.builder() @@ -7941,6 +8250,7 @@ public abstract class BaseTest { .onUpdate(ReferenceType.NO_ACTION) .build(), ForeignKey.builder() + .id(9L) .name("fk_zoo_id") .onDelete(ReferenceType.NO_ACTION) .references(new LinkedList<>(List.of(ForeignKeyReference.builder() diff --git a/dbrepo-search-service/Pipfile b/dbrepo-search-service/Pipfile index 287670f8ddac63952943a27dcdddbe08e78289bc..ec74a381be4f01297cf01d2f638182ba2a8a1d9d 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.6.0.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.6.1.tar.gz"} gunicorn = "*" [dev-packages] diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index c7e1f6005d78d40641abae50f4bb3189251aac42..c0508dd3daf66ff03c848411ae47f1698da81014 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "ed3c0ae802499c4020eea0c4d2e62f57a0a642cc0ebe9698f228cd8fd8f42ccb" + "sha256": "a0682b0583cfc91d643a307a7dce7a524e7f7c29dbf2c9c5e9a6f16eb5f5ee91" }, "pipfile-spec": 6, "requires": { @@ -360,9 +360,9 @@ }, "dbrepo": { "hashes": [ - "sha256:769c6d9c4475b26d3f752dcc9910346798d31afeca45ef014f48dd293074b8fb" + "sha256:a08b6eb49c108466b231c1b2cae5be501043fe4208a782899ce103105e22e3c6" ], - "path": "./lib/dbrepo-1.6.0.tar.gz" + "path": "./lib/dbrepo-1.6.1.tar.gz" }, "docker": { "hashes": [ @@ -602,7 +602,7 @@ "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" ], - "markers": "python_version < '3.13' and (platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32'))))))", + "markers": "python_version < '3.14' and (platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32'))))))", "version": "==3.1.1" }, "gunicorn": { @@ -1099,11 +1099,11 @@ }, "pydantic": { "hashes": [ - "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d", - "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06" + "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", + "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53" ], "markers": "python_version >= '3.8'", - "version": "==2.10.4" + "version": "==2.10.5" }, "pydantic-core": { "hashes": [ @@ -1321,20 +1321,20 @@ }, "rdflib": { "hashes": [ - "sha256:164de86bd3564558802ca983d84f6616a4a1a420c7a17a8152f5016076b2913e", - "sha256:e590fa9a2c34ba33a667818b5a84be3fb8a4d85868f8038f17912ec84f912a25" + "sha256:4fc8f6d50b199dc38fbc5256370f038c1cedca6102ccbde4e37c0fd2b7f36e65", + "sha256:5a694a64f48a751079999c37dccf91a6210077d845d09adf7c3ce23a876265a7" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==7.1.1" + "markers": "python_version >= '3.9' and python_version < '4'", + "version": "==7.1.2" }, "referencing": { "hashes": [ - "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", - "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" + "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794", + "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade" ], - "markers": "python_version >= '3.8'", - "version": "==0.35.1" + "markers": "python_version >= '3.9'", + "version": "==0.36.1" }, "requests": { "hashes": [ @@ -1463,66 +1463,66 @@ }, "sqlalchemy": { "hashes": [ - "sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763", - "sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436", - "sha256:07b441f7d03b9a66299ce7ccf3ef2900abc81c0db434f42a5694a37bd73870f2", - "sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588", - "sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e", - "sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959", - "sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d", - "sha256:28120ef39c92c2dd60f2721af9328479516844c6b550b077ca450c7d7dc68575", - "sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908", - "sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8", - "sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8", - "sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545", - "sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7", - "sha256:4557e1f11c5f653ebfdd924f3f9d5ebfc718283b0b9beebaa5dd6b77ec290971", - "sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855", - "sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c", - "sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71", - "sha256:50aae840ebbd6cdd41af1c14590e5741665e5272d2fee999306673a1bb1fdb4d", - "sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb", - "sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72", - "sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f", - "sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5", - "sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346", - "sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24", - "sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e", - "sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5", - "sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08", - "sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793", - "sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88", - "sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686", - "sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b", - "sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2", - "sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28", - "sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d", - "sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5", - "sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a", - "sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a", - "sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3", - "sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf", - "sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5", - "sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef", - "sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689", - "sha256:b81ee3d84803fd42d0b154cb6892ae57ea6b7c55d8359a02379965706c7efe6c", - "sha256:be9812b766cad94a25bc63bec11f88c4ad3629a0cec1cd5d4ba48dc23860486b", - "sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07", - "sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa", - "sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06", - "sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1", - "sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff", - "sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa", - "sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687", - "sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4", - "sha256:f942a799516184c855e1a32fbc7b29d7e571b52612647866d4ec1c3242578fcb", - "sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44", - "sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c", - "sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e", - "sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53" + "sha256:03f0528c53ca0b67094c4764523c1451ea15959bbf0a8a8a3096900014db0278", + "sha256:12b0f1ec623cccf058cf21cb544f0e74656618165b083d78145cafde156ea7b6", + "sha256:12b28d99a9c14eaf4055810df1001557176716de0167b91026e648e65229bffb", + "sha256:1b2690456528a87234a75d1a1644cdb330a6926f455403c8e4f6cad6921f9098", + "sha256:1cdba1f73b64530c47b27118b7053b8447e6d6f3c8104e3ac59f3d40c33aa9fd", + "sha256:293f9ade06b2e68dd03cfb14d49202fac47b7bb94bffcff174568c951fbc7af2", + "sha256:2952748ecd67ed3b56773c185e85fc084f6bdcdec10e5032a7c25a6bc7d682ef", + "sha256:2f95fc8e3f34b5f6b3effb49d10ac97c569ec8e32f985612d9b25dd12d0d2e94", + "sha256:2fa2c0913f02341d25fb858e4fb2031e6b0813494cca1ba07d417674128ce11b", + "sha256:3151822aa1db0eb5afd65ccfafebe0ef5cda3a7701a279c8d0bf17781a793bb4", + "sha256:35bd2df269de082065d4b23ae08502a47255832cc3f17619a5cea92ce478b02b", + "sha256:41296bbcaa55ef5fdd32389a35c710133b097f7b2609d8218c0eabded43a1d84", + "sha256:44f569d0b1eb82301b92b72085583277316e7367e038d97c3a1a899d9a05e342", + "sha256:46954173612617a99a64aee103bcd3f078901b9a8dcfc6ae80cbf34ba23df989", + "sha256:4b12885dc85a2ab2b7d00995bac6d967bffa8594123b02ed21e8eb2205a7584b", + "sha256:4f581d365af9373a738c49e0c51e8b18e08d8a6b1b15cc556773bcd8a192fa8b", + "sha256:51bc9cfef83e0ac84f86bf2b10eaccb27c5a3e66a1212bef676f5bee6ef33ebb", + "sha256:521ef85c04c33009166777c77e76c8a676e2d8528dc83a57836b63ca9c69dcd1", + "sha256:5bc3339db84c5fb9130ac0e2f20347ee77b5dd2596ba327ce0d399752f4fce39", + "sha256:635d8a21577341dfe4f7fa59ec394b346da12420b86624a69e466d446de16aff", + "sha256:648ec5acf95ad59255452ef759054f2176849662af4521db6cb245263ae4aa33", + "sha256:650dcb70739957a492ad8acff65d099a9586b9b8920e3507ca61ec3ce650bb72", + "sha256:6b788f14c5bb91db7f468dcf76f8b64423660a05e57fe277d3f4fad7b9dcb7ce", + "sha256:6c67415258f9f3c69867ec02fea1bf6508153709ecbd731a982442a590f2b7e4", + "sha256:74bbd1d0a9bacf34266a7907d43260c8d65d31d691bb2356f41b17c2dca5b1d0", + "sha256:75311559f5c9881a9808eadbeb20ed8d8ba3f7225bef3afed2000c2a9f4d49b9", + "sha256:78361be6dc9073ed17ab380985d1e45e48a642313ab68ab6afa2457354ff692c", + "sha256:7b7e772dc4bc507fdec4ee20182f15bd60d2a84f1e087a8accf5b5b7a0dcf2ba", + "sha256:82df02816c14f8dc9f4d74aea4cb84a92f4b0620235daa76dde002409a3fbb5a", + "sha256:84b9f23b0fa98a6a4b99d73989350a94e4a4ec476b9a7dfe9b79ba5939f5e80b", + "sha256:8c4096727193762e72ce9437e2a86a110cf081241919ce3fab8e89c02f6b6658", + "sha256:8e47f1af09444f87c67b4f1bb6231e12ba6d4d9f03050d7fc88df6d075231a49", + "sha256:93d1543cd8359040c02b6614421c8e10cd7a788c40047dbc507ed46c29ae5636", + "sha256:94b564e38b344d3e67d2e224f0aec6ba09a77e4582ced41e7bfd0f757d926ec9", + "sha256:955a2a765aa1bd81aafa69ffda179d4fe3e2a3ad462a736ae5b6f387f78bfeb8", + "sha256:9d087663b7e1feabea8c578d6887d59bb00388158e8bff3a76be11aa3f748ca2", + "sha256:9df21b8d9e5c136ea6cde1c50d2b1c29a2b5ff2b1d610165c23ff250e0704087", + "sha256:a8998bf9f8658bd3839cbc44ddbe982955641863da0c1efe5b00c1ab4f5c16b1", + "sha256:b2eae3423e538c10d93ae3e87788c6a84658c3ed6db62e6a61bb9495b0ad16bb", + "sha256:b661b49d0cb0ab311a189b31e25576b7ac3e20783beb1e1817d72d9d02508bf5", + "sha256:bedee60385c1c0411378cbd4dc486362f5ee88deceea50002772912d798bb00f", + "sha256:c505edd429abdfe3643fa3b2e83efb3445a34a9dc49d5f692dd087be966020e0", + "sha256:cce918ada64c956b62ca2c2af59b125767097ec1dca89650a6221e887521bfd7", + "sha256:cf5ae8a9dcf657fd72144a7fd01f243236ea39e7344e579a121c4205aedf07bb", + "sha256:cf95a60b36997dad99692314c4713f141b61c5b0b4cc5c3426faad570b31ca01", + "sha256:d57bafbab289e147d064ffbd5cca2d7b1394b63417c0636cea1f2e93d16eb9e8", + "sha256:d70f53a0646cc418ca4853da57cf3ddddbccb8c98406791f24426f2dd77fd0e2", + "sha256:d75ead7dd4d255068ea0f21492ee67937bd7c90964c8f3c2bea83c7b7f81b95f", + "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e", + "sha256:db18ff6b8c0f1917f8b20f8eca35c28bbccb9f83afa94743e03d40203ed83de9", + "sha256:dfff7be361048244c3aa0f60b5e63221c5e0f0e509f4e47b8910e22b57d10ae7", + "sha256:e4fb5ac86d8fe8151966814f6720996430462e633d225497566b3996966b9bdb", + "sha256:e56a139bfe136a22c438478a86f8204c1eb5eed36f4e15c4224e4b9db01cb3e4", + "sha256:e6f5d254a22394847245f411a2956976401e84da4288aa70cbcd5190744062c1", + "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069", + "sha256:ea308cec940905ba008291d93619d92edaf83232ec85fbd514dcb329f3192761", + "sha256:eaa8039b6d20137a4e02603aba37d12cd2dde7887500b8855356682fc33933f4" ], "markers": "python_version >= '3.7'", - "version": "==2.0.36" + "version": "==2.0.37" }, "sqlalchemy-utils": { "hashes": [ @@ -1598,74 +1598,88 @@ }, "wrapt": { "hashes": [ - "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d", - "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301", - "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635", - "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a", - "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed", - "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721", - "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801", - "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b", - "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1", - "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88", - "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8", - "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0", - "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f", - "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578", - "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7", - "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045", - "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada", - "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d", - "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b", - "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a", - "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977", - "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea", - "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346", - "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13", - "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22", - "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339", - "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9", - "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181", - "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c", - "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90", - "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a", - "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489", - "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f", - "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504", - "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea", - "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569", - "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4", - "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce", - "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab", - "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a", - "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f", - "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c", - "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9", - "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf", - "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d", - "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627", - "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d", - "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4", - "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c", - "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d", - "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad", - "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b", - "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33", - "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371", - "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1", - "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393", - "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106", - "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df", - "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379", - "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451", - "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b", - "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575", - "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed", - "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb", - "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838" + "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.0" + "version": "==1.17.2" }, "yarl": { "hashes": [ diff --git a/dbrepo-search-service/app.py b/dbrepo-search-service/app.py index e4e8581a9ee484c198f5a00a76a58b5296dd4188..f9e2dbcc77ac11a6f7c8175e2b0d868f848c98af 100644 --- a/dbrepo-search-service/app.py +++ b/dbrepo-search-service/app.py @@ -5,17 +5,19 @@ from json import dumps from typing import List, Any import requests -from clients.keycloak_client import User, KeycloakClient -from clients.opensearch_client import OpenSearchClient from dbrepo.api.dto import Database, ApiError from flasgger import LazyJSONEncoder, Swagger, swag_from -from flask import Flask, request +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 +from pydantic.deprecated.json import pydantic_encoder + +from clients.keycloak_client import User, KeycloakClient +from clients.opensearch_client import OpenSearchClient, flatten logging.addLevelName(level=logging.NOTSET, levelName='TRACE') logging.basicConfig(level=logging.DEBUG) @@ -123,18 +125,6 @@ template = { } } }, - "SearchResultDto": { - "required": ["results"], - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "type": "object" - } - } - } - }, "SearchRequestDto": { "required": ["search_term", "field_value_pairs"], "type": "object", @@ -208,13 +198,13 @@ app.json_encoder = LazyJSONEncoder @token_auth.verify_token -def verify_token(token: str): +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 as error: + except JWTDecodeError: return False @@ -259,10 +249,10 @@ def general_filter(index, results): "table": ["id", "name", "description"], "identifier": ["id", "type", "creator"], "user": ["id", "username"], - "database": ["id", "name", "is_public", "details"], + "database": ["id", "name", "is_public", "is_schema_public", "details"], "concept": ["uri", "name"], "unit": [], - "view": ["id", "name", "creator", " created"], + "view": ["id", "name", "creator"], } if index not in important_keys.keys(): raise KeyError(f"Failed to find index {index} in: {important_keys.keys()}") @@ -289,7 +279,7 @@ def get_index(index: str): :param index: desired index :return: list of the results """ - logging.info(f'Searching for index: {index}') + logging.debug(f'endpoint get search type: {index}') results = OpenSearchClient().query_index_by_term_opensearch("*", "contains") try: results = general_filter(index, results) @@ -298,7 +288,7 @@ 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 dict({"results": results}), 200 + return Response(dumps(results, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} except KeyError: return ApiError(status='NOT_FOUND', message=f'Failed to find get index: {index}', code='search.index.missing').model_dump(), 404 @@ -313,11 +303,11 @@ def get_fields(field_type: str): :param field_type: The search type :return: """ - logging.info(f'Searching in index database for type: {field_type}') + logging.debug(f'endpoint get search type fields: {field_type}') try: fields = OpenSearchClient().get_fields_for_index(field_type) logging.debug(f'get fields for field_type {field_type} resulted in {len(fields)} field(s)') - return fields, 200 + return Response(dumps(fields, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} 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 @@ -331,15 +321,19 @@ def get_fuzzy_search(): Main endpoint for fuzzy searching. :return: """ - search_term: str = request.args.get('q') + search_term: str | None = request.args.get('q') + logging.debug(f'endpoint get fuzzy search, q={search_term}') if search_term is None or len(search_term) == 0: 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}") - results = OpenSearchClient().fuzzy_search(search_term) - if "hits" in results and "hits" in results["hits"]: - results = [hit["_source"] for hit in results["hits"]["hits"]] - return dict({"results": results}), 200 + user_id, error, status = KeycloakClient().userId(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'} @app.route("/api/search/<string:field_type>", methods=["POST"], endpoint="search_post_general_search") @@ -353,27 +347,32 @@ def post_general_search(field_type): if request.content_type != "application/json": return ApiError(status='UNSUPPORTED_MEDIA_TYPE', message='Content type needs to be application/json', code='search.general.media').model_dump(), 415 - req_body = request.json - logging.info(f'Searching in index database for type: {field_type}') + value_pairs = request.json + logging.debug(f'endpoint get general search, field_type={field_type}, value_pairs={value_pairs}') t1 = request.args.get("t1") if not str(t1).isdigit(): t1 = None t2 = request.args.get("t2") if not str(t2).isdigit(): t2 = None - if t1 is not None and t2 is not None and "unit.uri" in req_body and "concept.uri" in req_body: - response = OpenSearchClient().unit_independent_search(t1, t2, req_body) + user_id, error, status = KeycloakClient().userId(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) else: - response = OpenSearchClient().general_search(field_type, req_body) + response: [Database] = OpenSearchClient().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)] + views = [view for view in flatten([database.views for database in response]) if + view.is_public or view.is_schema_public or (user_id is not None and view.owner.id == user_id)] if field_type == 'table': - tmp = [] - for database in response: - if database["tables"] is not None: - for table in database["tables"]: - table["is_public"] = database["is_public"] - tmp.append(table) - response = tmp + logging.debug(f'filtered to {len(tables)} tables') + response = tables if field_type == 'identifier': tmp = [] for database in response: @@ -393,12 +392,7 @@ def post_general_search(field_type): tmp.append(view['identifier']) response = tmp elif field_type == 'column': - response = [x for xs in response for x in xs["tables"]] - for table in response: - for column in table["columns"]: - column["table_id"] = table["id"] - column["database_id"] = table["database_id"] - response = [x for xs in response for x in xs["columns"]] + response = flatten([table.columns for table in tables]) elif field_type == 'concept': tmp = [] tables = [x for xs in response for x in xs["tables"]] @@ -414,15 +408,15 @@ def post_general_search(field_type): tmp.append(column["unit"]) response = tmp elif field_type == 'view': - response = [x for xs in response for x in xs["views"]] - return dict({'results': response, 'type': field_type}), 200 + response = views + return Response(dumps(response, default=pydantic_encoder)), 200, {'Content-Type': 'application/json'} @app.route("/api/search/database/<int:database_id>", methods=["PUT"], endpoint="search_put_database") @metrics.gauge(name='dbrepo_search_update_database', description='Time needed to update a database in the search database') @auth.login_required(role=['update-search-index']) -def update_database(database_id: int) -> Database | ApiError: +def update_database(database_id: int): logging.debug(f"updating database with id: {database_id}") try: payload: Database = Database.model_validate(request.json) @@ -431,7 +425,7 @@ def update_database(database_id: int) -> Database | ApiError: 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}") + logging.info(f"Updated database with id: {database_id}") return database.model_dump(), 202 @@ -442,7 +436,7 @@ def update_database(database_id: int) -> Database | ApiError: def delete_database(database_id: int): try: OpenSearchClient().delete_database(database_id) - return dumps({}), 202 + return Response(dumps({})), 202 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/init/Pipfile b/dbrepo-search-service/init/Pipfile index 5c3c4a2ad8767b0f190271524cc5cbfc248a340a..77bab3e84c036d88689f0431bf63dc2f5fe4d099 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.5.1.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.6.1.tar.gz"} rdflib = "*" [dev-packages] diff --git a/dbrepo-search-service/init/Pipfile.lock b/dbrepo-search-service/init/Pipfile.lock index 4362403bdd15b3976ac8f2c1b10a51bb63ba63ba..bf53ace7e7551b8e0961373d6ab23e49ff53f300 100644 --- a/dbrepo-search-service/init/Pipfile.lock +++ b/dbrepo-search-service/init/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0ed594feea5f1f7694d727f04d4bebd9cf341fed8f37e54819289daee0f22eb6" + "sha256": "9edba52503b8604b267d52e41954beba012143b1e47f56aaae553cdcaf054e55" }, "pipfile-spec": 6, "requires": { @@ -254,11 +254,10 @@ }, "dbrepo": { "hashes": [ - "sha256:1a52772dedf756bf48c52eec4df0c3a0c1fcef8034f47aa33c7ae5207cf85609", - "sha256:a18d7304b3ea3d5ba9c0b94988911ed6a129d59f2116d362ae9e4bf5a2803e2e" + "sha256:251f3c2088bbd289cee86d5394b1e62e29aa081f994dd0845d895e3330f6a106" ], - "markers": "python_version >= '3.11'", - "path": "./lib/dbrepo-1.5.1.tar.gz" + "path": "./lib/dbrepo-1.6.1.tar.gz", + "version": "==1.6.1" }, "docker": { "hashes": [ @@ -280,7 +279,6 @@ "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.3.3" }, "frozenlist": { @@ -645,7 +643,6 @@ "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda" ], "index": "pypi", - "markers": "python_version >= '3.8' and python_version < '4'", "version": "==2.8.0" }, "packaging": { @@ -810,11 +807,11 @@ }, "pydantic": { "hashes": [ - "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d", - "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06" + "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", + "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53" ], "markers": "python_version >= '3.8'", - "version": "==2.10.4" + "version": "==2.10.5" }, "pydantic-core": { "hashes": [ @@ -936,7 +933,6 @@ "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==8.3.4" }, "python-dateutil": { @@ -953,7 +949,6 @@ "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==1.0.1" }, "pytz": { @@ -965,12 +960,11 @@ }, "rdflib": { "hashes": [ - "sha256:164de86bd3564558802ca983d84f6616a4a1a420c7a17a8152f5016076b2913e", - "sha256:e590fa9a2c34ba33a667818b5a84be3fb8a4d85868f8038f17912ec84f912a25" + "sha256:4fc8f6d50b199dc38fbc5256370f038c1cedca6102ccbde4e37c0fd2b7f36e65", + "sha256:5a694a64f48a751079999c37dccf91a6210077d845d09adf7c3ce23a876265a7" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==7.1.1" + "version": "==7.1.2" }, "requests": { "hashes": [ @@ -1000,7 +994,6 @@ "sha256:0bdf270b5b7f53915832f7c31dd2bd3ffdc20b534ea6b32231cc7003049bd0e1" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.0.1rc1" }, "tinydb": { @@ -1053,74 +1046,88 @@ }, "wrapt": { "hashes": [ - "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d", - "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301", - "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635", - "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a", - "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed", - "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721", - "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801", - "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b", - "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1", - "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88", - "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8", - "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0", - "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f", - "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578", - "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7", - "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045", - "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada", - "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d", - "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b", - "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a", - "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977", - "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea", - "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346", - "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13", - "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22", - "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339", - "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9", - "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181", - "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c", - "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90", - "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a", - "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489", - "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f", - "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504", - "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea", - "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569", - "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4", - "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce", - "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab", - "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a", - "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f", - "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c", - "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9", - "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf", - "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d", - "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627", - "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d", - "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4", - "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c", - "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d", - "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad", - "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b", - "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33", - "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371", - "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1", - "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393", - "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106", - "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df", - "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379", - "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451", - "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b", - "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575", - "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed", - "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb", - "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838" + "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.0" + "version": "==1.17.2" }, "yarl": { "hashes": [ @@ -1278,7 +1285,6 @@ "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f" ], "index": "pypi", - "markers": "python_version >= '3.9'", "version": "==7.6.10" }, "iniconfig": { @@ -1311,7 +1317,6 @@ "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==8.3.4" } } diff --git a/dbrepo-search-service/init/app.py b/dbrepo-search-service/init/app.py index 9fe915f92c50d2b712058783d4eecf1b087cc8f7..f8f671bade77541508aec72cd19066157cd162f3 100644 --- a/dbrepo-search-service/init/app.py +++ b/dbrepo-search-service/init/app.py @@ -1,12 +1,11 @@ import json -import os import logging +import os +from logging.config import dictConfig from typing import List import opensearchpy.exceptions from dbrepo.RestClient import RestClient -from logging.config import dictConfig - from dbrepo.api.dto import Database from opensearchpy import OpenSearch @@ -46,6 +45,8 @@ class App: search_username: str = None search_password: str = None search_instance: OpenSearch = None + system_username: str = None + system_password: str = None def __init__(self): self.metadata_service_endpoint = os.getenv("METADATA_SERVICE_ENDPOINT", "http://metadata-service:8080") @@ -53,6 +54,8 @@ class App: 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: """ @@ -84,7 +87,8 @@ class App: def fetch_databases(self) -> List[Database]: logging.debug(f"fetching database from endpoint: {self.metadata_service_endpoint}") - client = RestClient(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}") @@ -93,16 +97,17 @@ class App: return databases def save_databases(self, databases: List[Database]): - logging.debug(f"save {len(databases)} database(s)") + 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="database", id=doc.id) - logging.debug(f"deleted database with id {doc.id}") + self._instance().delete(index=index, id=doc.id) + logging.debug(f"truncated database with id {doc.id} in index: {index}") except opensearchpy.NotFoundError: - logging.warning(f"Database with id {doc.id} does not exist, skip.") - self._instance().create(index="database", id=doc.id, body=doc.model_dump()) - logging.debug(f"created database with id {doc.id}") + 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}") if __name__ == "__main__": diff --git a/dbrepo-search-service/init/clients/keycloak_client.py b/dbrepo-search-service/init/clients/keycloak_client.py index afa36a1112ce41b5686641f5691df3f44075cf2f..2e15d00a9b272233feb7bab4cf6166c63b151e04 100644 --- a/dbrepo-search-service/init/clients/keycloak_client.py +++ b/dbrepo-search-service/init/clients/keycloak_client.py @@ -1,14 +1,17 @@ import logging from dataclasses import dataclass -import requests -from flask import current_app from typing import List +import requests +from dbrepo.api.dto import ApiError +from flask import current_app 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] @@ -30,8 +33,22 @@ class KeycloakClient: raise AssertionError("Failed to obtain user token(s)") return response.json()["access_token"] - def verify_jwt(self, access_token: str) -> User: + def verify_jwt(self, access_token: str) -> ApiError | 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"]) + 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/clients/opensearch_client.py b/dbrepo-search-service/init/clients/opensearch_client.py index 7d25fcded5a29e87524523785133d7aaa56f314d..35c26f03f5f684adc2652c199db7f99afd6cfc13 100644 --- a/dbrepo-search-service/init/clients/opensearch_client.py +++ b/dbrepo-search-service/init/clients/opensearch_client.py @@ -1,17 +1,18 @@ """ The opensearch_client.py is used by the different API endpoints in routes.py to handle requests to the opensearch db """ +import logging import os +from collections.abc import MutableMapping from json import dumps, load -import logging from dbrepo.api.dto import Database -from collections.abc import MutableMapping - -from opensearchpy import OpenSearch, TransportError, RequestError, NotFoundError +from dbrepo.api.exceptions import ForbiddenError, NotExistsError +from opensearchpy import OpenSearch, NotFoundError +from requests import head -from omlib.measure import om from omlib.constants import OM_IDS +from omlib.measure import om from omlib.omconstants import OM from omlib.unit import Unit @@ -21,16 +22,22 @@ class OpenSearchClient: 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 - password: str = None - instance: OpenSearch = None def __init__(self, host: str = None, port: int = None, username: str = None, password: str = None): self.host = os.getenv('OPENSEARCH_HOST', host) + self.metadata_endpoint = os.getenv('METADATA_SERVICE_ENDPOINT', 'http://metadata-service:8080') + self.password = os.getenv('OPENSEARCH_PASSWORD', password) 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) - self.password = os.getenv('OPENSEARCH_PASSWORD', password) def _instance(self) -> OpenSearch: """ @@ -44,18 +51,6 @@ class OpenSearchClient: http_auth=(self.username, self.password)) return self.instance - def get_database(self, database_id: int) -> Database: - """ - Gets a database by given id. - - @param database_id: The database id. - - @returns: The database, if successful. - @throws: opensearchpy.exceptions.NotFoundError If the database was not found in the Search Database. - """ - response: dict = self._instance().get(index="database", id=database_id) - return Database.parse_obj(response["_source"]) - def update_database(self, database_id: int, data: Database) -> Database: """ Updates the database data with given id. @@ -69,9 +64,7 @@ class OpenSearchClient: 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) - database = Database.parse_obj(response["_source"]) - logging.info(f"Updated database with id {database_id} in index 'database'") - return database + return Database.model_validate(response["_source"]) def delete_database(self, database_id: int) -> None: """ @@ -124,7 +117,7 @@ class OpenSearchClient: "unit": "tables.columns.unit.*", "identifier": "identifiers.*", "view": "views.*", - "user": "creator.*", + "user": "owner.*", } if field_type not in fields.keys(): raise NotFoundError(f"Failed to find field type: {field_type}") @@ -143,27 +136,50 @@ class OpenSearchClient: fields_list.append(entry) return fields_list - def fuzzy_search(self, search_term=None): - logging.info(f"Performing fuzzy search") - fuzzy_body = { - "query": { - "multi_match": { - "query": search_term, - "fuzziness": "AUTO", - "fuzzy_transpositions": True, - "minimum_should_match": 3 - } - } - } - logging.debug(f'search body: {fuzzy_body}') + def fuzzy_search(self, search_term: str, user_id: str | None = None, user_token: str | None = None) -> [Database]: response = self._instance().search( index="database", - body=fuzzy_body + body={ + "query": { + "multi_match": { + "query": search_term, + "fuzziness": "AUTO", + "prefix_length": 2 + } + } + } ) - logging.info(f"Found {len(response['hits']['hits'])} result(s)") - return response - - def general_search(self, field_type: str = None, field_value_pairs: dict = None): + results: [Database] = [] + if "hits" in response and "hits" in response["hits"]: + results = [Database.model_validate(hit["_source"]) for hit in response["hits"]["hits"]] + logging.debug(f'found {len(results)} results') + return self.filter_results(results, user_id, user_token) + + def filter_results(self, results: [Database], user_id: str | None = None, user_token: str | None = None) -> [ + Database]: + filtered: [Database] = [] + for database in results: + if database.is_public or database.is_schema_public: + logging.debug(f'database with id {database.id} is public or has public schema') + filtered.append(database) + elif user_id is not None and user_token is not None: + try: + url = f'{self.metadata_endpoint}/api/database/{database.id}/access/{user_id}' + logging.debug(f'requesting access from url: {url}') + response = head(url=url, auth=(self.system_username, self.system_password)) + if response.status_code == 200: + logging.debug(f'database with id {database.id} is draft and access was found') + filtered.append(database) + else: + logging.warning( + f'database with id {database.id} is not accessible: code {response.status_code}') + except (ForbiddenError, NotExistsError) as e: + logging.warning(f'database with id {database.id} is draft but no access was found') + logging.debug(f'filtered {len(filtered)} results') + return filtered + + def general_search(self, field_type: str = None, field_value_pairs: dict = None, user_id: str | None = None, + user_token: str | None = None) -> [Database]: """ Main method for searching stuff in the opensearch db @@ -204,10 +220,14 @@ class OpenSearchClient: index="database", body=dumps(body) ) - results = [hit["_source"] for hit in response["hits"]["hits"]] - return results - - def unit_independent_search(self, t1: float, t2: float, field_value_pairs): + results: [Database] = [] + if "hits" in response and "hits" in response["hits"]: + results = [Database.model_validate(hit["_source"]) for hit in response["hits"]["hits"]] + logging.debug(f'found {len(results)} results') + return self.filter_results(results, user_id, user_token) + + def unit_independent_search(self, t1: float, t2: float, field_value_pairs: dict, userId: str | None = None) -> [ + Database]: """ Main method for searching stuff in the opensearch db @@ -288,16 +308,12 @@ class OpenSearchClient: body = '' for search in searches: body += '%s \n' % dumps(search) - responses = self._instance().msearch( + response = self._instance().msearch( body=dumps(body) ) - response = { - "hits": { - "hits": flatten([hits["hits"]["hits"] for hits in responses["responses"]]) - }, - "took": responses["took"] - } - return response + results = flatten([hits["hits"]["hits"] for hits in response["responses"]]) + return [database for database in results if + database.is_public or database.is_schema_public or (userId is not None and database.owner.id == userId)] def key_to_attr_name(key: str) -> str: @@ -324,7 +340,7 @@ def attr_name_to_attr_friendly_name(key: str) -> str: :param key: The attribute key :return: The human-readable representation of the attribute key """ - with open('friendly_names_overrides.json') as json_data: + with open('./friendly_names_overrides.json') as json_data: d = load(json_data) for json_key in d.keys(): if json_key == key: diff --git a/dbrepo-search-service/init/database.json b/dbrepo-search-service/init/database.json index fb175700c614599daab44fa0fb77e51a05151b62..59cbd78438a5fff391d1237c70a0384d7b397a83 100644 --- a/dbrepo-search-service/init/database.json +++ b/dbrepo-search-service/init/database.json @@ -244,7 +244,7 @@ "created": { "type": "date" }, - "creator": { + "owner": { "properties": { "id": { "type": "text", @@ -310,7 +310,7 @@ "created": { "type": "date" }, - "creator": { + "owner": { "properties": { "id": { "type": "text", @@ -359,9 +359,9 @@ } } }, - "creators": { + "owners": { "properties": { - "creator_name": { + "owner_name": { "type": "text", "fields": { "keyword": { @@ -572,37 +572,6 @@ } } }, - "owner": { - "properties": { - "id": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "qualified_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "username": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, "tables": { "properties": { "columns": { @@ -610,7 +579,7 @@ "auto_generated": { "type": "boolean" }, - "column_type": { + "type": { "type": "text", "fields": { "keyword": { @@ -643,6 +612,9 @@ "is_public": { "type": "boolean" }, + "is_schema_public": { + "type": "boolean" + }, "mean": { "type": "float" }, @@ -733,7 +705,7 @@ "created": { "type": "date" }, - "creator": { + "owner": { "properties": { "id": { "type": "text", @@ -830,55 +802,6 @@ "num_rows": { "type": "long" }, - "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 - } - } - } - } - }, "queue_name": { "type": "text", "fields": { @@ -906,7 +829,7 @@ "auto_generated": { "type": "boolean" }, - "column_type": { + "type": { "type": "text", "fields": { "keyword": { @@ -936,6 +859,9 @@ "is_public": { "type": "boolean" }, + "is_schema_public": { + "type": "boolean" + }, "name": { "type": "text", "fields": { @@ -950,7 +876,7 @@ "created": { "type": "date" }, - "creator": { + "owner": { "properties": { "id": { "type": "text", @@ -1010,7 +936,7 @@ "created": { "type": "date" }, - "creator": { + "owner": { "properties": { "id": { "type": "text", @@ -1059,9 +985,9 @@ } } }, - "creators": { + "owners": { "properties": { - "creator_name": { + "owner_name": { "type": "text", "fields": { "keyword": { diff --git a/dbrepo-search-service/init/lib/dbrepo-1.5.1.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.5.1.tar.gz deleted file mode 100644 index ca01f15711ae3ba792d5ecfca40356b50dda6b15..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/init/lib/dbrepo-1.5.1.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.5.2.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.5.2.tar.gz deleted file mode 100644 index 52bf0fe9a030ce509450bc52427eb7e2c1f1da13..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/init/lib/dbrepo-1.5.2.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz deleted file mode 100644 index 2bb796d8fece2d97c3b2168248ff493dfa24a549..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.1.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.6.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..7914db1bb84dddf85611cda3b766c0c0cdc094c7 Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.6.1.tar.gz differ diff --git a/dbrepo-search-service/lib/dbrepo-1.5.1.tar.gz b/dbrepo-search-service/lib/dbrepo-1.5.1.tar.gz deleted file mode 100644 index ca01f15711ae3ba792d5ecfca40356b50dda6b15..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/lib/dbrepo-1.5.1.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/lib/dbrepo-1.5.2.tar.gz b/dbrepo-search-service/lib/dbrepo-1.5.2.tar.gz deleted file mode 100644 index 52bf0fe9a030ce509450bc52427eb7e2c1f1da13..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/lib/dbrepo-1.5.2.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz b/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz deleted file mode 100644 index 2bb796d8fece2d97c3b2168248ff493dfa24a549..0000000000000000000000000000000000000000 Binary files a/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz and /dev/null differ diff --git a/dbrepo-search-service/lib/dbrepo-1.6.1.tar.gz b/dbrepo-search-service/lib/dbrepo-1.6.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..7914db1bb84dddf85611cda3b766c0c0cdc094c7 Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.6.1.tar.gz differ diff --git a/dbrepo-search-service/os-yml/get_fuzzy_search.yml b/dbrepo-search-service/os-yml/get_fuzzy_search.yml index bc54419eb9735fe731fb12a5e911070ebc29f80e..db2ef87b3268f10329ba11117ee323208d940af5 100644 --- a/dbrepo-search-service/os-yml/get_fuzzy_search.yml +++ b/dbrepo-search-service/os-yml/get_fuzzy_search.yml @@ -19,6 +19,9 @@ responses: content: application/json: schema: - $ref: '#/components/schemas/SearchResultDto' + type: array + properties: + id: + type: string 415: description: Wrong accept type diff --git a/dbrepo-search-service/test/test_app.py b/dbrepo-search-service/test/test_app.py index 0482ff3f586050f49135039bb36ec5d16320396d..0c577b228a951064ffd650b860100ad17f80ba72 100644 --- a/dbrepo-search-service/test/test_app.py +++ b/dbrepo-search-service/test/test_app.py @@ -3,7 +3,7 @@ import time import unittest import jwt -from dbrepo.api.dto import Database, Table, Constraints, Column, ColumnType, Concept, Unit, \ +from dbrepo.api.dto import Database, Table, Constraints, Column, ColumnType, ConceptBrief, UnitBrief, \ UserBrief, ContainerBrief, ImageBrief from app import app @@ -32,12 +32,21 @@ req = Database(id=1, routing_key="dbrepo.1.1", is_public=True, is_schema_public=True, - columns=[Column(id=1, database_id=1, table_id=1, name="ID", internal_name="id", - column_type=ColumnType.BIGINT, is_public=True, is_null_allowed=False, - size=20, d=0, - concept=Concept(id=1, uri="http://www.wikidata.org/entity/Q2221906"), - unit=Unit(id=1, - uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), + columns=[Column(id=1, + database_id=1, + table_id=1, + ord=0, + name="ID", + internal_name="id", + type=ColumnType.BIGINT, + is_public=True, + is_null_allowed=False, + size=20, + d=0, + concept=ConceptBrief(id=1, + uri="http://www.wikidata.org/entity/Q2221906"), + unit=UnitBrief(id=1, + uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), val_min=0, val_max=10)] )]) diff --git a/dbrepo-search-service/test/test_jwt.py b/dbrepo-search-service/test/test_jwt.py index 59cd4ee1168117d0aeb6bf3549fe5088edc379b9..96ce8410da4be0598fd6d635e7decc9950bd42e8 100644 --- a/dbrepo-search-service/test/test_jwt.py +++ b/dbrepo-search-service/test/test_jwt.py @@ -12,9 +12,9 @@ class JwtTest(unittest.TestCase): def response(self, roles: [str]) -> dict: return dict({ - "client_id": "username", - "realm_access": { - "roles": roles + 'client_id': 'username', + 'realm_access': { + 'roles': roles } }) @@ -37,13 +37,13 @@ class JwtTest(unittest.TestCase): def test_verify_token_empty_token_fails(self): with app.app_context(): # test - user = verify_token("") + user = verify_token('') self.assertFalse(user) def test_verify_token_malformed_token_fails(self): with app.app_context(): # test - user = verify_token("eyEYEY12345") + user = verify_token('eyEYEY12345') self.assertFalse(user) def test_verify_token_succeeds(self): @@ -59,25 +59,25 @@ class JwtTest(unittest.TestCase): def test_verify_password_no_username_fails(self): with app.app_context(): # test - user = verify_password(None, "pass") + 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") + 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) + 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", "") + user = verify_password('username', '') self.assertFalse(user) def test_verify_password_succeeds(self): @@ -87,11 +87,12 @@ class JwtTest(unittest.TestCase): mock.post('http://auth-service:8080/api/auth/realms/dbrepo/protocol/openid-connect/token', json=self.response([])) # test - user = verify_password("username", "password") + 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(username="username", roles=[])) + roles: [str] = get_user_roles( + User(id='b98415d8-28bc-4472-84ff-3d09cc79aff6', username='username', roles=[])) self.assertEqual([], roles) diff --git a/dbrepo-search-service/test/test_opensearch_client.py b/dbrepo-search-service/test/test_opensearch_client.py index 295b2917af7995f56ef0d962fac0948334c9aeff..9da77adfde53e155dddc36f364bea9d974964125 100644 --- a/dbrepo-search-service/test/test_opensearch_client.py +++ b/dbrepo-search-service/test/test_opensearch_client.py @@ -2,7 +2,7 @@ import unittest import opensearchpy from dbrepo.api.dto import Database, Table, Column, ColumnType, Constraints, PrimaryKey, \ - TableMinimal, ColumnMinimal, Concept, Unit, UserBrief, ContainerBrief, ImageBrief + TableMinimal, ColumnMinimal, ConceptBrief, UnitBrief, UserBrief, ContainerBrief, ImageBrief from opensearchpy import NotFoundError from app import app @@ -35,12 +35,19 @@ req = Database(id=1, routing_key="dbrepo.1.1", is_public=True, is_schema_public=True, - columns=[Column(id=1, database_id=1, table_id=1, name="ID", internal_name="id", - column_type=ColumnType.BIGINT, is_public=True, is_null_allowed=False, - size=20, d=0, - concept=Concept(id=1, uri="http://www.wikidata.org/entity/Q2221906"), - unit=Unit(id=1, - uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), + columns=[Column(id=1, + database_id=1, + table_id=1, + name="ID", + ord=0, + internal_name="id", + type=ColumnType.BIGINT, + is_null_allowed=False, + size=20, + d=0, + concept=ConceptBrief(id=1, uri="http://www.wikidata.org/entity/Q2221906"), + unit=UnitBrief(id=1, + uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius"), val_min=0, val_max=10)] )]) @@ -71,12 +78,12 @@ class OpenSearchClientTest(unittest.TestCase): is_versioned=True, owner=UserBrief(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", username="foo"), columns=[Column(id=1, - name="ID", - internal_name="id", database_id=req.id, table_id=1, - column_type=ColumnType.BIGINT, - is_public=True, + ord=0, + name="ID", + internal_name="id", + type=ColumnType.BIGINT, is_null_allowed=False)])] database = OpenSearchClient().update_database(database_id=req.id, data=req) self.assertEqual(1, database.id) @@ -107,10 +114,9 @@ class OpenSearchClientTest(unittest.TestCase): self.assertEqual(1, database.tables[0].columns[0].id) self.assertEqual("ID", database.tables[0].columns[0].name) self.assertEqual("id", database.tables[0].columns[0].internal_name) - self.assertEqual(ColumnType.BIGINT, database.tables[0].columns[0].column_type) + self.assertEqual(ColumnType.BIGINT, database.tables[0].columns[0].type) self.assertEqual(1, database.tables[0].columns[0].database_id) self.assertEqual(1, database.tables[0].columns[0].table_id) - self.assertEqual(True, database.tables[0].columns[0].is_public) self.assertEqual(False, database.tables[0].columns[0].is_null_allowed) def test_update_database_create_succeeds(self): @@ -159,27 +165,6 @@ class OpenSearchClientTest(unittest.TestCase): # test OpenSearchClient().delete_database(database_id=req.id) - def test_get_database_succeeds(self): - with app.app_context(): - # mock - OpenSearchClient().update_database(database_id=req.id, data=req) - - # test - database = OpenSearchClient().get_database(database_id=req.id) - self.assertEqual(req.id, database.id) - - def test_get_database_fails(self): - with app.app_context(): - - # mock - OpenSearchClient().update_database(database_id=req.id, data=req) - - # test - try: - OpenSearchClient().get_database(database_id=req.id) - except opensearchpy.exceptions.NotFoundError: - pass - def test_get_fields_for_index_database_succeeds(self): with app.app_context(): # mock @@ -204,8 +189,7 @@ class OpenSearchClientTest(unittest.TestCase): OpenSearchClient().update_database(database_id=req.id, data=req) # test - response = OpenSearchClient().fuzzy_search(search_term="test") - self.assertTrue(len(response) > 0) + OpenSearchClient().fuzzy_search(search_term="test_tuw") def test_unit_independent_search_fails(self): with app.app_context(): diff --git a/dbrepo-storage-service/init/Dockerfile b/dbrepo-storage-service/init/Dockerfile index 4f4f0c797434901d27311cadbbe250bb0e96c480..be95322ff4721d63a62dc4cf8e18c0f768db8eaa 100644 --- a/dbrepo-storage-service/init/Dockerfile +++ b/dbrepo-storage-service/init/Dockerfile @@ -8,6 +8,6 @@ USER 1001 WORKDIR /app -COPY --chown=1001 --chmod=0744 ./init.sh /app/init.sh +COPY --chown=1001 --chmod=0777 ./init.sh /app/init.sh ENTRYPOINT [ "bash", "-c", "/app/init.sh" ] diff --git a/dbrepo-ui/bun.lockb b/dbrepo-ui/bun.lockb index b82e45d505fdc0e1f41e246f7d1caefe3e23007c..45a8c51c621dab127458d68a4493b23d2df9f88d 100755 Binary files a/dbrepo-ui/bun.lockb and b/dbrepo-ui/bun.lockb differ diff --git a/dbrepo-ui/components/JumboBox.vue b/dbrepo-ui/components/JumboBox.vue new file mode 100644 index 0000000000000000000000000000000000000000..d2b804f819f22782ba4895c601c8b2ea118ce4e3 --- /dev/null +++ b/dbrepo-ui/components/JumboBox.vue @@ -0,0 +1,59 @@ +<template> + <div> + <v-row> + <v-col> + <v-card + elevation="0" + variant="flat" + class="mx-auto" + max-width="600" + :title="title" + :subtitle="subtitle" + :text="text"> + <template v-slot:prepend> + <v-icon + :color="iconColor"> + {{ icon }} + </v-icon> + </template> + </v-card> + </v-col> + </v-row> + </div> +</template> +<script> +export default { + props: { + title: { + type: String, + default: () => { + return 'Title' + } + }, + subtitle: { + type: String, + default: () => { + return 'Subtitle' + } + }, + text: { + type: String, + default: () => { + return 'Text' + } + }, + icon: { + type: String, + default: () => { + return 'mdi-alert-rhombus-outline' + } + }, + iconColor: { + type: String, + default: () => { + return 'warning' + } + } + } +} +</script> diff --git a/dbrepo-ui/components/ResourceStatus.vue b/dbrepo-ui/components/ResourceStatus.vue new file mode 100644 index 0000000000000000000000000000000000000000..5167d899ea6e73c150db478f8fc3b063a3ba1e12 --- /dev/null +++ b/dbrepo-ui/components/ResourceStatus.vue @@ -0,0 +1,69 @@ +<template> + <span + v-if="mode"> + <v-chip + v-if="!inline" + :size="size" + :color="color" + variant="outlined"> + {{ status }} + </v-chip> + <span + v-else> + {{ status }} + </span> + </span> +</template> +<script> +export default { + props: { + resource: { + default: () => { + return null + } + }, + inline: { + default: () => { + return false + } + }, + size: { + default: () => { + return 'small' + } + } + }, + computed: { + mode () { + if (!this.resource) { + return null + } + if (!this.resource.is_public && !this.resource.is_schema_public) { + return 'draft' + } else if(!this.resource.is_public && this.resource.is_schema_public) { + return 'schema' + } else if(this.resource.is_public && !this.resource.is_schema_public) { + return 'data' + } + return 'public' + }, + status () { + if (!this.resource) { + return null + } + return this.$t(`pages.database.status.${this.mode}`) + }, + color () { + switch (this.mode) { + case 'schema': + case 'data': + return 'warning' + case 'draft': + return 'error' + case 'public': + return 'success' + } + } + } +} +</script> diff --git a/dbrepo-ui/components/database/DatabaseCard.vue b/dbrepo-ui/components/database/DatabaseCard.vue index fba3853a31cf25649f915d4c0a3e422f5ec879bf..c31d288c6fde7ed711ab8d1cab5e5da22a38876e 100644 --- a/dbrepo-ui/components/database/DatabaseCard.vue +++ b/dbrepo-ui/components/database/DatabaseCard.vue @@ -27,21 +27,8 @@ {{ identifierDescription(database) }} </div> <div class="mt-2 db-tags"> - <v-chip - v-if="database.is_public" - size="small" - color="success" - variant="outlined"> - {{ $t('toolbars.database.public') }} - </v-chip> - <v-chip - v-if="!database.is_public" - size="small" - :color="colorVariant" - variant="outlined" - flat> - {{ $t('toolbars.database.private') }} - </v-chip> + <ResourceStatus + :resource="database" /> <v-chip v-if="identifierYear(database)" size="small" @@ -86,8 +73,12 @@ <script> import { formatLanguage } from '@/utils' +import ResourceStatus from '@/components/ResourceStatus.vue' export default { + components: { + ResourceStatus + }, data() { return { loading: false @@ -175,7 +166,7 @@ export default { return null } return this.identifiers[0] - }, + } } } </script> diff --git a/dbrepo-ui/components/database/DatabaseCreate.vue b/dbrepo-ui/components/database/DatabaseCreate.vue index d0f386b08899b2c3f911958297e88d7d67bba4f8..07fd9d34ea218a91bb6ffb634d210bd5493ad830 100644 --- a/dbrepo-ui/components/database/DatabaseCreate.vue +++ b/dbrepo-ui/components/database/DatabaseCreate.vue @@ -17,7 +17,7 @@ <v-row dense> <v-col> <v-text-field - v-model="payload.name" + v-model="name" name="database" :variant="inputVariant" :label="$t('pages.database.subpages.create.name.label')" @@ -55,33 +55,12 @@ </v-row> <v-row> <v-col> - <v-select - v-model="mode" - name="mode" - :label="$t('pages.database.subpages.create.visibility.label')" - :hint="$t('pages.database.subpages.create.visibility.hint')" - persistent-hint - :variant="inputVariant" - :items="visibilityOptions" - item-title="name" - item-value="value" - :rules="[v => !!v || $t('validation.required')]" - return-object - required> - <template - v-slot:append-inner> - <v-tooltip - location="bottom"> - <template - v-slot:activator="{ props }"> - <v-icon - v-bind="props" - icon="mdi-help-circle-outline" /> - </template> - {{ mode.hint }} - </v-tooltip> - </template> - </v-select> + <v-checkbox + v-model="draft" + name="draft" + :label="$t('pages.database.subpages.create.draft.label')" + :hint="$t('pages.database.subpages.create.draft.hint')" + persistent-hint /> </v-col> </v-row> </v-card-text> @@ -117,6 +96,8 @@ export default { loading: false, loadingContainers: false, engine: null, + draft: true, + name: null, engines: [], visibilityOptions: [ { @@ -129,13 +110,7 @@ export default { hint: this.$t('pages.database.subpages.create.visibility.private.hint'), value: false } - ], - mode: true, - payload: { - name: null, - is_public: true, - is_schema_public: true, - } + ] } }, computed: { @@ -179,16 +154,16 @@ export default { .catch(({code}) => { this.loadingContainers = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) }, create () { this.loading = true - this.payload.container_id = this.engine.id - this.payload.is_public = this.mode.value - this.payload.is_schema_public = this.mode.value const databaseService = useDatabaseService() - databaseService.create(this.payload) + databaseService.create({ name: this.name, container_id: this.engine.id, is_public: !this.draft, is_schema_public: !this.draft }) .then(async (database) => { await this.$router.push(`/database/${database.id}/info`) this.loading = false diff --git a/dbrepo-ui/components/database/DatabaseToolbar.vue b/dbrepo-ui/components/database/DatabaseToolbar.vue index 65363c3467067aa4dd3eca9e2d5595a913723684..59b0bc6db65fe888ba74df900580193ff16e92f2 100644 --- a/dbrepo-ui/components/database/DatabaseToolbar.vue +++ b/dbrepo-ui/components/database/DatabaseToolbar.vue @@ -8,62 +8,51 @@ type="subtitle" width="200" /> <span - v-if="database && $vuetify.display.lgAndUp"> + class="mr-2" + v-if="database && $vuetify.display.mdAndUp"> {{ database.name }} </span> - <v-chip - v-if="database && database.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="database && !database.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> + <ResourceStatus + :size="$vuetify.display.mdAndUp ? 'small' : 'default'" + :resource="database" /> </v-toolbar-title> <v-spacer /> <v-btn v-if="false" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-chart-timeline-variant-shimmer' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-chart-timeline-variant-shimmer' : null" color="tertiary" :variant="buttonVariant" - :text="$t('toolbars.database.dashboard.permanent') + ($vuetify.display.lgAndUp ? ' ' + $t('toolbars.database.dashboard.xl') : '')" /> + :text="$t('toolbars.database.dashboard.permanent') + ($vuetify.display.mdAndUp ? ' ' + $t('toolbars.database.dashboard.xl') : '')" /> <v-btn v-if="canCreateTable" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-table-large-plus' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-table-large-plus' : null" color="secondary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-table.xl') + ' ' : '') + $t('toolbars.database.create-table.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-table.xl') + ' ' : '') + $t('toolbars.database.create-table.permanent')" class="mr-2" :to="`/database/${$route.params.database_id}/table/create/dataset`" /> <v-btn v-if="canCreateSubset" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-wrench' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-wrench' : null" color="secondary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-subset.xl') + ' ' : '') + $t('toolbars.database.create-subset.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-subset.xl') + ' ' : '') + $t('toolbars.database.create-subset.permanent')" class="mr-2 white--text" :to="`/database/${$route.params.database_id}/subset/create`" /> <v-btn v-if="canCreateView" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-view-carousel-outline' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-view-carousel-outline' : null" color="secondary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-view.xl') + ' ' : '') + $t('toolbars.database.create-view.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-view.xl') + ' ' : '') + $t('toolbars.database.create-view.permanent')" class="mr-2 white--text" :to="`/database/${$route.params.database_id}/view/create`" /> <v-btn v-if="canCreateIdentifier" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-identifier' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-identifier' : null" color="primary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-pid.xl') + ' ' : '') + $t('toolbars.database.create-pid.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-pid.xl') + ' ' : '') + $t('toolbars.database.create-pid.permanent')" class="mr-2" :to="`/database/${$route.params.database_id}/persist`" /> <template v-slot:extension> @@ -95,8 +84,12 @@ <script> import { useCacheStore } from '@/stores/cache' import { useUserStore } from '@/stores/user' +import ResourceStatus from '@/components/ResourceStatus.vue' export default { + components: { + ResourceStatus + }, data () { return { tab: null, diff --git a/dbrepo-ui/components/dialogs/DropTable.vue b/dbrepo-ui/components/dialogs/DropTable.vue deleted file mode 100644 index d465c882d0529a817be21f836ea82739fc30155b..0000000000000000000000000000000000000000 --- a/dbrepo-ui/components/dialogs/DropTable.vue +++ /dev/null @@ -1,114 +0,0 @@ -<template> - <div> - <v-form ref="form" v-model="valid" autocomplete="off" @submit.prevent="submit"> - <v-card - :title="$t('pages.table.subpages.drop.title') + ' ' + table.internal_name" - variant="elevated"> - <v-card-text> - <v-row dense> - <v-col> - <span> - {{ $t('pages.table.subpages.drop.warning.prefix') }} - </span> - <code class="code-key">{{ table.internal_name }}</code> - <span> - {{ $t('pages.table.subpages.drop.warning.suffix') }} - </span> - </v-col> - </v-row> - <v-row> - <v-col> - <v-text-field - id="confirm" - v-model="confirm" - name="confirm" - persistent-hint - :variant="inputVariant" - :label="$t('pages.table.subpages.drop.name.label')" - :hint="$t('pages.table.subpages.drop.name.hint')" - autofocus - required /> - </v-col> - </v-row> - </v-card-text> - <v-card-actions> - <v-spacer /> - <v-btn - :variant="buttonVariant" - :text="$t('navigation.cancel')" - @click="cancel" /> - <v-btn - color="error" - variant="flat" - :text="$t('navigation.delete')" - :loading="loadingDelete" - :disabled="confirm !== table.internal_name" - type="submit" - @click="dropTable" /> - </v-card-actions> - </v-card> - </v-form> - </div> -</template> - -<script> -import { useCacheStore } from '@/stores/cache' - -export default { - data () { - return { - confirm: null, - loadingDelete: false, - valid: false, - cacheStore: useCacheStore() - } - }, - computed: { - table () { - return this.cacheStore.getTable - }, - database () { - return this.cacheStore.getDatabase - }, - inputVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal - }, - buttonVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal - } - }, - methods: { - submit () { - this.$refs.form.validate() - }, - cancel () { - this.$emit('close', { action: 'closed' }) - }, - dropTable () { - if (!this.table.id) { - return - } - this.loadingDelete = true - const tableService = useTableService() - tableService.remove(this.database.id, this.table.id) - .then(() => { - console.info('Deleted table with id ', this.table.id) - this.cacheStore.reloadDatabase() - const toast = useToastInstance() - toast.success('Successfully deleted table with id ' + this.table.id) - this.$router.push(`/database/${this.$route.params.database_id}/table`) - }) - .finally(() => { - this.loadingDelete = false - }) - } - } -} -</script> -<style scoped> -.code-key { - padding: 2px 4px; -} -</style> diff --git a/dbrepo-ui/components/dialogs/EditAccess.vue b/dbrepo-ui/components/dialogs/EditAccess.vue index 039b1c40e8e5d241b1d52f6145affad898581702..856a442592bf9b40000b9295c8b7ed9bc17f6b78 100644 --- a/dbrepo-ui/components/dialogs/EditAccess.vue +++ b/dbrepo-ui/components/dialogs/EditAccess.vue @@ -172,11 +172,14 @@ export default { accessService.remove(this.$route.params.database_id, this.localUserId) .then(() => { const toast = useToastInstance() - toast.success(this.$t('success.access.revoked')) + toast.success(this.$t('success.access.revoked', { access: this.modify.type })) this.$emit('close-dialog', { success: true }) }) .catch(({code, message}) => { const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) }) .finally(() => { @@ -185,14 +188,17 @@ export default { }, modifyAccess () { const accessService = useAccessService() - accessService.modify(this.$route.params.database_id, this.localUserId, this.modify) + accessService.update(this.$route.params.database_id, this.localUserId, this.modify) .then(() => { const toast = useToastInstance() - toast.success(this.$t('success.access.modified')) + toast.success(this.$t('success.access.modified', { access: this.modify.type })) this.$emit('close-dialog', { success: true }) }) .catch(({code, message}) => { const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) }) .finally(() => { @@ -204,11 +210,14 @@ export default { accessService.create(this.$route.params.database_id, this.localUserId, this.modify) .then(() => { const toast = useToastInstance() - toast.success(this.$t('success.access.created')) + toast.success(this.$t('success.access.created', { access: this.modify.type })) this.$emit('close-dialog', { success: true }) }) .catch(({code, message}) => { const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) }) .finally(() => { @@ -220,10 +229,13 @@ export default { const userService = useUserService() userService.findAll() .then((users) => { - this.users = users.filter(u => u.username !== this.database.creator.username) + this.users = users.filter(u => u.id !== this.database.owner.id) }) .catch(({code}) => { const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { diff --git a/dbrepo-ui/components/dialogs/EditTuple.vue b/dbrepo-ui/components/dialogs/EditTuple.vue index ea0bfb3c5b9161a907c2ca61544daafb737dd128..3290d230d1bf216bd2f212c4fbe9c683901e4b96 100644 --- a/dbrepo-ui/components/dialogs/EditTuple.vue +++ b/dbrepo-ui/components/dialogs/EditTuple.vue @@ -27,7 +27,7 @@ type="number"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -61,7 +61,7 @@ type="text"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -94,7 +94,7 @@ type="number"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -126,7 +126,7 @@ :hint="hint(column)"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -161,7 +161,7 @@ :items="isSet(column) ? column.sets : column.enums"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -192,7 +192,7 @@ :clearable="!required(column)"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -221,7 +221,7 @@ :hint="hint(column)"> <template v-slot:append> - {{ column.column_type.toUpperCase() }} + {{ column.type.toUpperCase() }} <NuxtLink target="_blank" class="ml-2" @@ -313,6 +313,8 @@ export default { oldTuple: null, error: false, menu: false, + loadContainer: false, + container: null, bools: [ { title: 'true', value: true }, { title: 'false', value: false } @@ -321,6 +323,7 @@ export default { } }, mounted() { + this.fetchContainer() this.$refs.form.validate() this.oldTuple = Object.assign({}, this.tuple) }, @@ -328,11 +331,20 @@ export default { database () { return this.cacheStore.getDatabase }, + table () { + return this.cacheStore.getTable + }, columnTypes () { - if (!this.database) { + if (!this.container) { + return [] + } + return this.container.image.data_types + }, + primaryKeyColumns () { + if (!this.table) { return [] } - return this.database.container.image.data_types + return this.table.constraints.primary_key.map(pk => pk.column) }, title () { return (this.edit ? this.$t('toolbars.table.data.edit') : this.$t('toolbars.table.data.add')) + ' ' + this.$t('toolbars.table.data.tuple') @@ -360,7 +372,7 @@ export default { if (!is_null_allowed) { hint += this.$t('pages.table.subpages.data.required.hint') } - if (column.column_type === 'sequence') { + if (column.type === 'sequence') { hint += ' ' + this.$t('pages.table.subpages.data.auto.hint') } if (is_primary_key) { @@ -371,47 +383,47 @@ export default { } return hint }, - documentationLink ({column_type}) { - const filter = this.columnTypes.filter(t => t.value === column_type) + documentationLink ({type}) { + const filter = this.columnTypes.filter(t => t.value === type) if (filter.length !== 1) { return null } return filter[0].documentation }, - formatHint ({column_type}) { - const filter = this.columnTypes.filter(t => t.value === column_type) + formatHint ({type}) { + const filter = this.columnTypes.filter(t => t.value === type) if (filter.length !== 1) { return null } return filter[0].data_hint }, isTextField (column) { - const { column_type } = column - return ['char', 'varchar', 'tinytext', 'mediumtext'].includes(column_type) + const { type } = column + return ['char', 'varchar', 'tinytext', 'mediumtext'].includes(type) }, isTextArea (column) { - return ['text'].includes(column.column_type) + return ['text'].includes(column.type) }, isFileField (column) { - return ['blob', 'longblob', 'mediumblob', 'tinyblob'].includes(column.column_type) + return ['blob', 'longblob', 'mediumblob', 'tinyblob'].includes(column.type) }, isBoolean (column) { - return ['bool'].includes(column.column_type) + return ['bool'].includes(column.type) }, isNumber (column) { - return ['int', 'binary', 'bit', 'tinyint', 'smallint', 'mediumint', 'bigint'].includes(column.column_type) + return ['int', 'binary', 'bit', 'tinyint', 'smallint', 'mediumint', 'bigint', 'serial'].includes(column.type) }, isFloatingPoint (column) { - return ['float', 'double', 'decimal'].includes(column.column_type) + return ['float', 'double', 'decimal'].includes(column.type) }, isEnum (column) { - return column.column_type === 'enum' + return column.type === 'enum' }, isSet (column) { - return column.column_type === 'set' + return column.type === 'set' }, isTimeField (column) { - return ['date', 'datetime', 'timestamp', 'time', 'year'].includes(column.column_type) + return ['date', 'datetime', 'timestamp', 'time', 'year'].includes(column.type) }, rules (column) { if (column.is_null_allowed) { @@ -419,7 +431,7 @@ export default { } const rules = [] rules.push(v => v !== null || this.$t('validation.required')) - if (column.column_type === 'decimal' || column.column_type === 'double') { + if (column.type === 'decimal' || column.type === 'double') { rules.push(v => !(!v || v.split('.')[0].length > column.size) || `${this.$t('pages.table.subpages.data.float.max')} ${column.size} ${this.$t('pages.table.subpages.data.float.before')}`) rules.push(v => !(!v || (column.d && v.split('.')[1].length > column.d)) || `${this.$t('pages.table.subpages.data.float.max')} ${column.d} ${this.$t('pages.table.subpages.data.float.after')}`) } @@ -439,19 +451,11 @@ export default { }, updateTuple () { const constraints = {} - if (this.table.constraints.primary_key.length > 0) { - this.table.constraints.primary_key - .forEach((pk) => { - constraints[pk.column.internal_name] = this.oldTuple[pk.column.internal_name] - }) - console.debug('table has primary key: set update tuple constraints', constraints) - } else { - this.table.columns - .forEach((column) => { - constraints[column.internal_name] = this.oldTuple[column.internal_name] - }) - console.debug('table does not have a primary key: set update tuple constraints', constraints) - } + this.primaryKeyColumns + .forEach((pk) => { + constraints[pk.internal_name] = this.oldTuple[pk.internal_name] + }) + console.debug('table has primary key: set update tuple constraints', constraints) const tupleService = useTupleService() this.loading = true tupleService.update(this.$route.params.database_id, this.$route.params.table_id, { data: this.tuple, keys: constraints }) @@ -462,9 +466,12 @@ export default { this.loading = false }) .catch(({message}) => { + this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) - this.loading = false }) .finally(() => { this.loading = false @@ -491,10 +498,13 @@ export default { this.$emit('close', { success: true }) this.loading = false }) - .catch(({message}) => { + .catch(({code, message}) => { + this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) - this.loading = false }) .finally(() => { this.loading = false @@ -504,6 +514,29 @@ export default { const toast = useToastInstance() toast.success(this.$t('success.upload.blob')) this.tuple[column.internal_name] = s3key + }, + fetchContainer () { + if (!this.database) { + return + } + this.loadContainer = true + const containerService = useContainerService() + containerService.findOne(this.database.container.id) + .then((container) => { + this.container = container + this.loadContainer = false + }) + .catch(({code, message}) => { + this.loadContainer = false + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(message) + }) + .finally(() => { + this.loadContainer = false + }) } } } diff --git a/dbrepo-ui/components/dialogs/UpdateTable.vue b/dbrepo-ui/components/dialogs/UpdateTable.vue deleted file mode 100644 index 6e4e07182c12c480b1f4c5d4da3756d3e111164a..0000000000000000000000000000000000000000 --- a/dbrepo-ui/components/dialogs/UpdateTable.vue +++ /dev/null @@ -1,167 +0,0 @@ -<template> - <div> - <v-form - ref="form" - v-model="valid" - autocomplete="off" - @submit.prevent="submit"> - <v-card - :title="$t('pages.view.visibility.title')"> - <v-card-text> - <v-row> - <v-col> - <v-textarea - v-model="modify.description" - rows="2" - :rules="[ - v => (!!v || v.length <= 180) || ($t('validation.max-length') + 180), - ]" - clearable - counter="180" - persistent-counter - persistent-hint - :variant="inputVariant" - :hint="$t('pages.table.subpages.import.description.hint')" - :label="$t('pages.table.subpages.import.description.label')"/> - </v-col> - </v-row> - <v-row - dense> - <v-col - md="6"> - <v-select - v-model="modify.is_public" - :items="visibilities" - persistent-hint - :variant="inputVariant" - required - :rules="[ - v => v !== null || $t('validation.required') - ]" - :label="$t('pages.database.subpages.create.data.label')" - :hint="$t('pages.database.subpages.create.data.hint')" /> - </v-col> - <v-col - md="6"> - <v-select - v-model="modify.is_schema_public" - :items="visibilities" - persistent-hint - :variant="inputVariant" - required - :rules="[ - v => v !== null || $t('validation.required') - ]" - :label="$t('pages.database.subpages.create.schema.label')" - :hint="$t('pages.database.subpages.create.schema.hint')" /> - </v-col> - </v-row> - </v-card-text> - <v-card-actions> - <v-spacer /> - <v-btn - :variant="buttonVariant" - :text="$t('navigation.cancel')" - @click="cancel" /> - <v-btn - id="database" - variant="flat" - :disabled="!valid || !isChange" - :color="buttonColor" - :loading="loading" - type="submit" - :text="$t('navigation.modify')" - @click="update" /> - </v-card-actions> - </v-card> - </v-form> - </div> -</template> - -<script> -import { useCacheStore } from '@/stores/cache' - -export default { - props: { - table: { - type: Object, - default () { - return { - is_public: true, - is_schema_public: true, - description: null - } - } - }, - }, - data () { - return { - valid: false, - loading: false, - visibilities: [ - { title: this.$t('toolbars.database.public'), value: true }, - { title: this.$t('toolbars.database.private'), value: false }, - ], - modify: { - description: this.table.description, - is_public: this.table.is_public, - is_schema_public: this.table.is_schema_public - }, - cacheStore: useCacheStore() - } - }, - computed: { - database () { - return this.cacheStore.getDatabase - }, - inputVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal - }, - buttonVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal - }, - isChange () { - if (this.table.description !== this.modify.description) { - return true - } - if (this.table.is_public !== this.modify.is_public) { - return true - } - return this.table.is_schema_public !== this.modify.is_schema_public - }, - buttonColor () { - return !this.isChange ? null : 'warning' - } - }, - methods: { - submit () { - this.$refs.form.validate() - }, - cancel () { - this.$emit('close', { success: false }) - }, - update () { - this.loading = true - const tableService = useTableService() - tableService.update(this.$route.params.database_id, this.$route.params.table_id, this.modify) - .then(() => { - this.loading = false - const toast = useToastInstance() - toast.success(this.$t('success.table.updated')) - this.$emit('close', { success: true }) - this.cacheStore.reloadTable() - }) - .catch(({code}) => { - this.loading = false - const toast = useToastInstance() - toast.error(this.$t(code)) - }) - .finally(() => { - this.loading = false - }) - } - } -} -</script> diff --git a/dbrepo-ui/components/dialogs/ViewVisibility.vue b/dbrepo-ui/components/dialogs/ViewVisibility.vue index 226772edd922a9d71e40a312d461c666c50e8893..7d113116674f79d6980c71096061fc965c15e93e 100644 --- a/dbrepo-ui/components/dialogs/ViewVisibility.vue +++ b/dbrepo-ui/components/dialogs/ViewVisibility.vue @@ -14,29 +14,29 @@ md="6"> <v-select v-model="modify.is_public" - :items="visibilities" + :items="dataOptions" persistent-hint :variant="inputVariant" required :rules="[ v => v !== null || $t('validation.required') ]" - :label="$t('pages.database.subpages.create.data.label')" - :hint="$t('pages.database.subpages.create.data.hint')" /> + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'view' })" /> </v-col> <v-col md="6"> <v-select v-model="modify.is_schema_public" - :items="visibilities" + :items="schemaOptions" persistent-hint :variant="inputVariant" required :rules="[ v => v !== null || $t('validation.required') ]" - :label="$t('pages.database.subpages.create.schema.label')" - :hint="$t('pages.database.subpages.create.schema.hint')" /> + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'view', schema: 'columns' })" /> </v-col> </v-row> </v-card-text> @@ -82,9 +82,13 @@ export default { loadingUsers: false, users: [], error: false, - visibilities: [ - { title: this.$t('toolbars.database.public'), value: true }, - { title: this.$t('toolbars.database.private'), value: false }, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, ], modify: { is_public: this.view.is_public, @@ -122,25 +126,6 @@ export default { cancel () { this.$emit('close', { success: false }) }, - updateVisibility () { - this.loading = true - const viewService = useViewService() - viewService.update(this.$route.params.database_id, this.$route.params.view_id, this.modify) - .then(() => { - this.loading = false - const toast = useToastInstance() - toast.success(this.$t('success.view.modified')) - this.$emit('close', { success: true }) - }) - .catch(({code, message}) => { - this.loading = false - const toast = useToastInstance() - toast.error(message) - }) - .finally(() => { - this.loading = false - }) - } } } </script> diff --git a/dbrepo-ui/components/identifier/Citation.vue b/dbrepo-ui/components/identifier/Citation.vue index 7cd99194b099987f3853fde4afd7bf92f463dd38..5722351f0ab1d3697783f3f0f82c54c5452981d4 100644 --- a/dbrepo-ui/components/identifier/Citation.vue +++ b/dbrepo-ui/components/identifier/Citation.vue @@ -68,9 +68,12 @@ export default { this.loading = false }) .catch(({code, message}) => { + this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(`${code}: ${message}`)) - this.loading = false }) } } diff --git a/dbrepo-ui/components/identifier/Select.vue b/dbrepo-ui/components/identifier/Select.vue index bacbab44149b75289a81741afc52fd4c2983283f..e1de8d1b26bc021bdf54d98c106d7e79cd8ec65d 100644 --- a/dbrepo-ui/components/identifier/Select.vue +++ b/dbrepo-ui/components/identifier/Select.vue @@ -86,7 +86,7 @@ export default { if (!this.user) { return this.identifiers.filter(i => i.status === 'published') } - return this.identifiers.filter(i => i.status === 'published' || i.creator.id === this.user.id) + return this.identifiers.filter(i => i.status === 'published' || i.owner.id === this.user.id) }, listVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/components/search/AdvancedSearch.vue b/dbrepo-ui/components/search/AdvancedSearch.vue index 13de402e019f2a791f0233c4fc611164e46e20d8..8197cd3fb8a960f44440cc8238c0a1a42cb7f57e 100644 --- a/dbrepo-ui/components/search/AdvancedSearch.vue +++ b/dbrepo-ui/components/search/AdvancedSearch.vue @@ -75,14 +75,14 @@ :variant="inputVariant" :label="field.attr_friendly_name" /> <v-text-field - v-if="(field.type === 'keyword' && field.attr_name !== 'column_type') || field.type === 'text' || field.type === 'date'" + v-if="(field.type === 'keyword' && field.attr_name !== 'type') || field.type === 'text' || field.type === 'date'" v-model="advancedSearchData[field.attr_name]" type="text" :variant="inputVariant" :label="field.attr_friendly_name" clearable /> <v-select - v-if="field.type === 'keyword' && field.attr_name === 'column_type'" + v-if="field.type === 'keyword' && field.attr_name === 'type'" v-model="advancedSearchData[field.attr_name]" :items="columnTypes" item-value="value" @@ -384,8 +384,8 @@ export default { this.loading = true const searchService = useSearchService() searchService.general_search(this.searchType, this.advancedSearchData) - .then(({results, type}) => { - this.$emit('search-result', {results, type}) + .then((results) => { + this.$emit('search-result', results) }) .finally(() => { this.loading = false @@ -443,7 +443,7 @@ export default { return } this.resetAdvancedSearchFields() - this.$emit('search-result', { results: [], type: this.searchType }) + this.$emit('search-result', []) const searchService = useSearchService() this.loadingFields = true searchService.fields(this.searchType) diff --git a/dbrepo-ui/components/subset/Builder.vue b/dbrepo-ui/components/subset/Builder.vue index 2a14b8f474a8f7a3cc0e38302e3ebad0e0df5a7d..2895476a59ea37a7db0cd768050012bbff9f6cff 100644 --- a/dbrepo-ui/components/subset/Builder.vue +++ b/dbrepo-ui/components/subset/Builder.vue @@ -68,7 +68,7 @@ md="4"> <v-select v-model="view.is_public" - :items="visibilities" + :items="dataOptions" persistent-hint :variant="inputVariant" required @@ -76,14 +76,14 @@ :rules="[ v => !!v || $t('validation.required') ]" - :label="$t('pages.database.subpages.create.data.label')" - :hint="$t('pages.database.subpages.create.data.hint')" /> + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint')" /> </v-col> <v-col md="4"> <v-select v-model="view.is_schema_public" - :items="visibilities" + :items="schemaOptions" persistent-hint :variant="inputVariant" required @@ -91,8 +91,8 @@ :rules="[ v => !!v || $t('validation.required') ]" - :label="$t('pages.database.subpages.create.schema.label')" - :hint="$t('pages.database.subpages.create.schema.hint')" /> + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'subset', schema: 'query' })" /> </v-col> </v-row> <v-window @@ -332,9 +332,13 @@ export default { columns: [], timestamp: null, executeDifferentTimestamp: false, - visibilities: [ - { title: this.$t('toolbars.database.public'), value: true }, - { title: this.$t('toolbars.database.private'), value: false }, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, ], tableDetails: null, resultId: null, @@ -485,9 +489,12 @@ export default { this.loadingColumns = false }) .catch(({code}) => { + this.loadingColumns = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) - this.loadingColumns = false }) }, validViewName (name) { diff --git a/dbrepo-ui/components/subset/Results.vue b/dbrepo-ui/components/subset/Results.vue index e9e3c0deb5cddf119cab770014ff085d71b6df94..e558186daf15c186dfdc085a844799815e3756a4 100644 --- a/dbrepo-ui/components/subset/Results.vue +++ b/dbrepo-ui/components/subset/Results.vue @@ -2,12 +2,15 @@ <div> <v-data-table-server flat + v-model="selection" :headers="headers" :loading="loading || loadingCount || loadingExecute" :options="options" :items="result.rows" :items-length="total" :footer-props="footerProps" + :show-select="select" + return-object :items-per-page-options="footerProps.itemsPerPageOptions" @update:options="updateOptions" /> </div> @@ -24,6 +27,10 @@ export default { type: Boolean, default: () => false }, + select: { + type: Boolean, + default: () => false + }, timestamp: { type: String, default: () => new Date().toISOString() @@ -35,6 +42,7 @@ export default { loadingExecute: false, resultId: null, id: null, + selection: null, result: { headers: [], rows: [] @@ -64,6 +72,11 @@ export default { this.reExecute(this.id) }, deep: true + }, + selection: { + handler () { + this.$emit('selection', this.selection) + } } }, methods: { @@ -224,6 +237,9 @@ export default { this.options.page = page this.options.itemsPerPage = itemsPerPage this.reExecute(this.id) + }, + resetSelection () { + this.selection = [] } } } diff --git a/dbrepo-ui/components/subset/SubsetList.vue b/dbrepo-ui/components/subset/SubsetList.vue index f57dc68a88fd77c06b858b423565b4ccac7d46f0..62a456eb793ae1f95a49fda7569e8fb8799b9ccb 100644 --- a/dbrepo-ui/components/subset/SubsetList.vue +++ b/dbrepo-ui/components/subset/SubsetList.vue @@ -26,21 +26,6 @@ :to="link(item)" :href="link(item)"> <template v-slot:append> - <v-chip - v-if="database.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="!database.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> <v-tooltip v-if="hasPublishedIdentifier(item)" :text="$t('pages.identifier.pid.title')" @@ -101,7 +86,11 @@ export default { queryService.findAll(this.$route.params.database_id, true) .then((subsets) => { this.loadingSubsets = false - this.subsets = subsets + this.subsets = subsets.map(subset => { + subset.is_public = this.database.is_public + subset.is_schema_public = this.database.is_schema_public + return subset + }) }) .catch(({code}) => { this.loadingSubsets = false diff --git a/dbrepo-ui/components/subset/SubsetToolbar.vue b/dbrepo-ui/components/subset/SubsetToolbar.vue index 0fc5be7c88e0db232ba76bf91cec1f3c351ab5be..405bb6d00fe4989a2e73c6abb2bf518194ff5b1a 100644 --- a/dbrepo-ui/components/subset/SubsetToolbar.vue +++ b/dbrepo-ui/components/subset/SubsetToolbar.vue @@ -3,7 +3,6 @@ <v-toolbar flat> <v-btn - class="mr-2" variant="plain" size="small" icon="mdi-arrow-left" @@ -17,7 +16,7 @@ :loading="loadingSave" color="secondary" variant="flat" - class="mb-1 ml-2" + class="mr-2" :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-star' : null" :text="$t('toolbars.subset.save.permanent')" @click.stop="save" /> @@ -26,15 +25,15 @@ :loading="loadingSave" color="warning" variant="flat" - class="mb-1 ml-2" + class="mr-2" :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-star-off' : null" :text="$t('toolbars.subset.unsave.permanent')" @click.stop="forget" /> <v-btn v-if="canGetPid" - class="mb-1 ml-2" color="primary" variant="flat" + class="mr-2" :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null" :disabled="!executionUTC" :to="`/database/${$route.params.database_id}/subset/${$route.params.subset_id}/persist`"> @@ -73,7 +72,6 @@ export default { loading: false, loadingSave: false, downloadLoading: false, - subset: null, userStore: useUserStore(), cacheStore: useCacheStore() } @@ -97,11 +95,14 @@ export default { roles () { return this.userStore.getRoles }, + subset () { + return this.cacheStore.getSubset + }, identifiers () { - if (!this.database || !this.database.subsets || this.database.subsets.length === 0) { + if (!this.subset) { return [] } - return this.database.subsets.filter(s => s.query_id === Number(this.$route.params.subset_id)) + return this.subset.identifiers }, canViewData () { if (!this.database) { @@ -157,7 +158,7 @@ export default { if (!this.user || !this.subset || !this.database) { return false } - return this.database.owner.id === this.user.id || (this.subset.creator.id === this.user.id && this.hasReadAccess) + return this.database.owner.id === this.user.id || (this.subset.owner.id === this.user.id && this.hasReadAccess) }, title () { if (!this.identifier) { @@ -171,12 +172,6 @@ export default { return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal } }, - mounted () { - /* load subset metadata */ - if (!this.subset) { - this.loadSubset() - } - }, methods: { save () { this.loadingSave = true @@ -206,20 +201,6 @@ export default { .finally(() => { this.loadingSave = false }) - }, - loadSubset () { - this.loading = true - const queryService = useQueryService() - queryService.findOne(this.$route.params.database_id, this.$route.params.subset_id) - .then((subset) => { - this.subset = subset - }) - .catch(() => { - this.loading = false - }) - .finally(() => { - this.loading = false - }) } } } diff --git a/dbrepo-ui/components/table/TableHistory.vue b/dbrepo-ui/components/table/TableHistory.vue index 34d45248e7341b9a5b8b3af1c2d799e4408e6ecb..ccc270c46c22de4933c76a448a9e7db95a2f6a10 100644 --- a/dbrepo-ui/components/table/TableHistory.vue +++ b/dbrepo-ui/components/table/TableHistory.vue @@ -173,9 +173,12 @@ export default { } }) .catch(({message}) => { + this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(message) - this.loading = false }) } } diff --git a/dbrepo-ui/components/table/TableImport.vue b/dbrepo-ui/components/table/TableImport.vue index c0e4d6f9348d1cebe920fcd1e55f64e504cada16..580839974eeab5525fb090dcc6bdcea977846fec 100644 --- a/dbrepo-ui/components/table/TableImport.vue +++ b/dbrepo-ui/components/table/TableImport.vue @@ -434,10 +434,12 @@ export default { this.loadingImport = false }) .catch(({code, message}) => { + this.loadingImport = false const toast = useToastInstance() - console.error(code, message) + if (typeof code !== 'string') { + return + } toast.error(`${this.$t(code)}: ${message}`) - this.loadingImport = false }) .finally(() => { this.loadingImport = false diff --git a/dbrepo-ui/components/table/TableList.vue b/dbrepo-ui/components/table/TableList.vue index 8bb77b2b5a8971e3a0d8dbe557e9d5d849f492c1..234470076db8bb400542fdebe4274b2eefad8e62 100644 --- a/dbrepo-ui/components/table/TableList.vue +++ b/dbrepo-ui/components/table/TableList.vue @@ -19,21 +19,8 @@ :subtitle="table.description ? table.description : ''" :to="`/database/${$route.params.database_id}/table/${table.id}/info`"> <template v-slot:append> - <v-chip - v-if="table && table.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="table && !table.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> + <ResourceStatus + :resource="table" /> <v-tooltip v-if="hasPublishedIdentifier(table)" :text="$t('pages.identifier.pid.title')" @@ -69,7 +56,7 @@ export default { dialogDelete: false, headers: [ { value: 'name', title: 'Name' }, - { value: 'column_type', title: 'Type' }, + { value: 'type', title: 'Type' }, { value: 'column_concept', title: 'Concept' }, { value: 'column_unit', title: 'Unit' }, { value: 'is_primary_key', title: 'Primary Key' }, diff --git a/dbrepo-ui/components/table/TableSchema.vue b/dbrepo-ui/components/table/TableSchema.vue index e9cb03c6173f334866a95e18bec220c64258fbe9..24c4fcd6823cd8d2bf33d3be5d61217978798f5c 100644 --- a/dbrepo-ui/components/table/TableSchema.vue +++ b/dbrepo-ui/components/table/TableSchema.vue @@ -281,6 +281,9 @@ export default { .catch(({code}) => { this.loadingColumnTypes = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) }, diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue index b7d358d2492bd01aa8eddc479405c660784f66c6..9821cb6fe4bbbbcfb4ad5de1df1160fedb84c722 100644 --- a/dbrepo-ui/components/table/TableToolbar.vue +++ b/dbrepo-ui/components/table/TableToolbar.vue @@ -9,76 +9,49 @@ <v-toolbar-title v-if="table"> <v-skeleton-loader - v-if="!table && $vuetify.display.lgAndUp" + v-if="!table && $vuetify.display.mdAndUp" type="subtitle" width="200" /> <span - v-if="table && $vuetify.display.lgAndUp"> + class="mr-2" + v-if="table && $vuetify.display.mdAndUp"> {{ table.name }} </span> - <v-chip - v-if="table && table.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="table && !table.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> + <ResourceStatus + :size="$vuetify.display.mdAndUp ? 'small' : 'default'" + :resource="table" /> </v-toolbar-title> <v-spacer /> <v-btn v-if="canImportCsv" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-cloud-upload' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-cloud-upload' : null" color="tertiary" :variant="buttonVariant" - :text="$t('toolbars.database.import-csv.permanent') + ($vuetify.display.lgAndUp ? ' ' + $t('toolbars.database.import-csv.xl') : '')" + :text="$t('toolbars.database.import-csv.permanent') + ($vuetify.display.mdAndUp ? ' ' + $t('toolbars.database.import-csv.xl') : '')" class="mr-2" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/import`" /> <v-btn v-if="canExecuteQuery" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-wrench' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-wrench' : null" color="secondary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-subset.xl') + ' ' : '') + $t('toolbars.database.create-subset.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-subset.xl') + ' ' : '') + $t('toolbars.database.create-subset.permanent')" class="mr-2" :to="`/database/${$route.params.database_id}/subset/create?tid=${$route.params.table_id}`" /> <v-btn v-if="canCreateView" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-view-carousel' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-view-carousel' : null" color="secondary" variant="flat" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-view.xl') + ' ' : '') + $t('toolbars.database.create-view.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-view.xl') + ' ' : '') + $t('toolbars.database.create-view.permanent')" class="mr-2" :to="`/database/${$route.params.database_id}/view/create?tid=${$route.params.table_id}`" /> - <v-btn - v-if="canUpdateTable" - class="mr-2" - variant="flat" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-table-edit' : null" - color="warning" - :text="($vuetify.display.lgAndUp ? $t('toolbars.database.update-table.xl') + ' ' : '') + $t('toolbars.database.update-table.permanent')" - @click="updateTableDialog = true" /> - <v-btn - v-if="canDropTable" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-delete' : null" - color="error" - variant="flat" - :text="($vuetify.display.lgAndUp ? 'Drop ' : '') + 'Table'" - class="mr-2" - @click="dropTableDialog = true" /> <v-btn v-if="canGetPid" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-content-save-outline' : null" color="primary" variant="flat" - :text="($vuetify.display.lgAndUp ? 'Get ' : '') + 'PID'" + :text="($vuetify.display.mdAndUp ? 'Get ' : '') + 'PID'" class="mr-2" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/persist`" /> <template v-slot:extension> @@ -94,37 +67,24 @@ v-if="canViewSchema" :text="$t('navigation.schema')" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/schema`" /> + <v-tab + v-if="canUpdateTable" + :text="$t('navigation.settings')" + :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/settings`" /> </v-tabs> </template> </v-toolbar> - <v-dialog - v-model="dropTableDialog" - max-width="640"> - <DropTable - @close="closeDelete" /> - </v-dialog> - <v-dialog - v-model="updateTableDialog" - max-width="640"> - <UpdateTable - :table="table" - @close="closeUpdate" /> - </v-dialog> </div> </template> <script> import EditTuple from '@/components/dialogs/EditTuple.vue' -import DropTable from '@/components/dialogs/DropTable.vue' -import UpdateTable from '@/components/dialogs/UpdateTable.vue' import { useCacheStore } from '@/stores/cache' import { useUserStore } from '@/stores/user' export default { components: { - EditTuple, - DropTable, - UpdateTable + EditTuple }, data () { return { @@ -133,7 +93,6 @@ export default { error: false, edit: false, dropTableDialog: false, - updateTableDialog: false, cacheStore: useCacheStore(), userStore: useUserStore() } @@ -173,16 +132,6 @@ export default { const userService = useUserService() return userService.hasReadAccess(this.access) && this.roles.includes('execute-query') }, - canDropTable () { - if (!this.roles || !this.table || !this.user) { - return false - } - if (this.roles.includes('delete-foreign-table')) { - return true - } - const tableService = useTableService() - return tableService.isOwner(this.table, this.user) && this.roles.includes('delete-table') && this.table.identifiers.length === 0 - }, canCreateView () { if (!this.roles || !this.table || !this.user) { return false @@ -200,7 +149,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.table.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id }, canViewSchema () { if (!this.table) { @@ -212,7 +161,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.table.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id }, canImportCsv () { if (!this.roles || !this.table || !this.user) { @@ -229,27 +178,6 @@ export default { buttonVariant () { const runtimeConfig = useRuntimeConfig() return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal - }, - isContrastTheme () { - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') - }, - isDarkTheme () { - return this.$vuetify.theme.global.name.toLowerCase().startsWith('dark') - }, - colorVariant () { - return this.isContrastTheme ? '' : (this.isDarkTheme ? 'tertiary' : 'secondary') - }, - }, - methods: { - closeDelete ({success}) { - this.dropTableDialog = false - if (success) { - this.cacheStore.reloadDatabase() - this.$router.push(`/database/${this.$route.params.database_id}/table`) - } - }, - closeUpdate () { - this.updateTableDialog = false } } } diff --git a/dbrepo-ui/components/user/UserBadge.vue b/dbrepo-ui/components/user/UserBadge.vue index f7bd18c60fcd64ff65538ed075d483c7a1e61b9e..9eb679de3c9345e3af6a7a23e1dea867f5042ac4 100644 --- a/dbrepo-ui/components/user/UserBadge.vue +++ b/dbrepo-ui/components/user/UserBadge.vue @@ -5,12 +5,15 @@ class="mr-1" :orcid="orcid" /> <span v-if="isSelf"> - <v-badge - inline - content="you" - color="code"> - {{ creatorName }} - </v-badge> + {{ creatorName }} + <v-chip + size="x-small" + inline> + {{ $t('navigation.you') }} + <v-icon + icon="mdi-account-outline" + end /> + </v-chip> </span> <span v-else> diff --git a/dbrepo-ui/components/view/ViewList.vue b/dbrepo-ui/components/view/ViewList.vue index 543a8746affd8cbbed495647fc963c8db1534072..1b278a555c1154492882e92773b0f9203057c799 100644 --- a/dbrepo-ui/components/view/ViewList.vue +++ b/dbrepo-ui/components/view/ViewList.vue @@ -14,21 +14,8 @@ :class="clazz(view)" :to="`/database/${$route.params.database_id}/view/${view.id}/info`"> <template v-slot:append> - <v-chip - v-if="view && view.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="view && !view.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> + <ResourceStatus + :resource="view" /> <v-tooltip v-if="hasPublishedIdentifier(view)" :text="$t('pages.identifier.pid.title')" diff --git a/dbrepo-ui/components/view/ViewToolbar.vue b/dbrepo-ui/components/view/ViewToolbar.vue index 64ea3f1029407e3143bc6dd9b5cdfcb634aa9b94..6528dd3cd494c8cf878aea2149e41d1a5571e050 100644 --- a/dbrepo-ui/components/view/ViewToolbar.vue +++ b/dbrepo-ui/components/view/ViewToolbar.vue @@ -1,64 +1,35 @@ <template> <v-toolbar flat> <v-btn - class="mr-2" size="small" icon="mdi-arrow-left" :to="`/database/${$route.params.database_id}/view`" /> <v-toolbar-title - v-if="cachedView"> + v-if="view"> <span - v-if="$vuetify.display.lgAndUp"> + v-if="$vuetify.display.mdAndUp" + class="mr-2"> {{ title }} </span> - <v-chip - v-if="cachedView.is_public" - size="small" - class="ml-2" - color="success" - :text="$t('toolbars.database.public')" - variant="outlined" /> - <v-chip - v-if="!cachedView.is_public" - size="small" - class="ml-2" - :color="colorVariant" - variant="outlined" - :text="$t('toolbars.database.private')" - flat /> + <ResourceStatus + :size="$vuetify.display.mdAndUp ? 'small' : 'default'" + :resource="view" /> </v-toolbar-title> <v-spacer /> - <v-btn - v-if="canDeleteView" - class="mr-2" - variant="flat" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-delete' : null" - :loading="loadingDelete" - color="error" - :text="$t('navigation.delete')" - @click="deleteView" /> - <v-btn - v-if="canUpdateVisibility" - class="mr-2" - variant="flat" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-eye' : null" - color="warning" - :text="$t('navigation.visibility')" - @click="updateViewDialog = true" /> <v-btn v-if="canCreatePid" class="mr-2" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-content-save-outline' : null" variant="flat" color="primary" - :text="($vuetify.display.lgAndUp ? $t('toolbars.view.pid.xl') + ' ' : '') + $t('toolbars.view.pid.permanent')" + :text="($vuetify.display.mdAndUp ? $t('toolbars.view.pid.xl') + ' ' : '') + $t('toolbars.view.pid.permanent')" :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/persist`" /> <v-dialog v-model="updateViewDialog" persistent max-width="640"> <ViewVisibility - :view="cachedView" + :view="view" @close="close" /> </v-dialog> <template v-slot:extension> @@ -69,13 +40,17 @@ :text="$t('navigation.info')" :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/info`" /> <v-tab - v-if="canReadData" + v-if="canViewData" :text="$t('navigation.data')" :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/data`" /> <v-tab - v-if="canReadData" + v-if="canViewSchema" :text="$t('navigation.schema')" :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/schema`" /> + <v-tab + v-if="canViewSettings" + :text="$t('navigation.settings')" + :to="`/database/${$route.params.database_id}/view/${$route.params.view_id}/settings`" /> </v-tabs> </template> </v-toolbar> @@ -113,59 +88,41 @@ export default { const runtimeConfig = useRuntimeConfig() return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal }, - cachedView () { - if (!this.database) { - return null - } - return this.database.views.filter(v => v.id === Number(this.$route.params.view_id))[0] + view () { + return this.cacheStore.getView }, canViewData () { - if (!this.cachedView) { + if (!this.view) { return false } - if (this.cachedView.is_public) { + if (this.view.is_public) { return true } if (!this.user) { return false } - return this.hasReadAccess || this.cachedView.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id }, canViewSchema () { - if (!this.cachedView) { + if (!this.view) { return false } - if (this.cachedView.is_schema_public) { + if (this.view.is_schema_public) { return true } if (!this.user) { return false } - return this.hasReadAccess || this.cachedView.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id }, - canDeleteView () { - if (!this.roles || !this.user || !this.cachedView) { + canViewSettings () { + if (!this.user || !this.view) { return false } - return this.roles.includes('delete-database-view') && this.cachedView.owned_by === this.user.id - }, - canUpdateVisibility () { - if (!this.roles || !this.user || !this.cachedView) { - return false - } - return this.roles.includes('modify-view-visibility') && this.cachedView.owned_by === this.user.id - }, - isContrastTheme () { - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') - }, - isDarkTheme () { - return this.$vuetify.theme.global.name.toLowerCase().startsWith('dark') - }, - colorVariant () { - return this.isContrastTheme ? '' : (this.isDarkTheme ? 'tertiary' : 'secondary') + return this.view.owner.id === this.user.id }, canCreatePid () { - if (!this.roles || !this.user || !this.cachedView) { + if (!this.roles || !this.user || !this.view) { return false } const userService = useUserService() @@ -186,23 +143,11 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' }, - canReadData () { - if (!this.cachedView) { - return false - } - if (this.cachedView.is_public) { - return true - } - if (!this.user) { - return false - } - return this.cachedView.owner.id === this.user.id || this.hasReadAccess - }, identifiers () { - if (!this.cachedView) { + if (!this.view) { return [] } - return this.cachedView.identifiers.filter(s => s.view_id === Number(this.$route.params.view_id)) + return this.view.identifiers.filter(s => s.view_id === Number(this.$route.params.view_id)) }, identifier () { /* mount pid */ @@ -217,39 +162,10 @@ export default { return this.identifiers[0] }, title () { - if (!this.cachedView) { + if (!this.view) { return null } - return this.cachedView.name - } - }, - methods: { - deleteView () { - this.loadingDelete = true - const viewService = useViewService() - viewService.remove(this.$route.params.database_id, this.$route.params.view_id) - .then(() => { - const toast = useToastInstance() - toast.success(this.$t('success.view.delete')) - this.cacheStore.reloadDatabase() - this.$router.push(`/database/${this.$route.params.database_id}/view`) - }) - .catch(({code, message}) => { - const toast = useToastInstance() - if (typeof code !== 'string' || typeof message !== 'string') { - return - } - toast.error(this.$t(code) + ": " + message) - }) - .finally(() => { - this.loadingDelete = false - }) - }, - close ({success}) { - this.updateViewDialog = false - if (success) { - this.cacheStore.reloadDatabase() - } + return this.view.name } } } diff --git a/dbrepo-ui/composables/container-service.ts b/dbrepo-ui/composables/container-service.ts index 9aaf116e7efeed12f03170ec22340119d7d3341f..f1280517566165b8f190b9bd05eea3b1d4ac98f1 100644 --- a/dbrepo-ui/composables/container-service.ts +++ b/dbrepo-ui/composables/container-service.ts @@ -17,5 +17,21 @@ export const useContainerService = (): any => { }) } - return {findAll} + async function findOne(containerId: number): Promise<ContainerDto> { + const axios = useAxiosInstance(); + console.debug('find containers'); + return new Promise<ContainerDto>((resolve, reject) => { + axios.get<ContainerDto>(`/api/container/${containerId}`) + .then((response) => { + console.info(`Find container with id ${containerId}`) + resolve(response.data) + }) + .catch((error) => { + console.error('Failed to find container', error) + reject(axiosErrorToApiError(error)) + }) + }) + } + + return {findAll, findOne} } diff --git a/dbrepo-ui/composables/database-service.ts b/dbrepo-ui/composables/database-service.ts index b96d75ab80e880f52d416fef382f9d22de444502..7956f7b4dff6cb748733fd381275dd6d0622b60c 100644 --- a/dbrepo-ui/composables/database-service.ts +++ b/dbrepo-ui/composables/database-service.ts @@ -83,7 +83,7 @@ export const useDatabaseService = (): any => { }); } - async function findOne(id: number): Promise<DatabaseDto | null> { + async function findOne(id: number, rawError: boolean = false): Promise<DatabaseDto | null> { const axios = useAxiosInstance(); console.debug('find database with id', id); return new Promise((resolve, reject) => { @@ -94,6 +94,9 @@ export const useDatabaseService = (): any => { }) .catch((error) => { console.error('Failed to find database', error); + if (rawError) { + reject(error) + } reject(axiosErrorToApiError(error)); }); }); diff --git a/dbrepo-ui/composables/identifier-service.ts b/dbrepo-ui/composables/identifier-service.ts index f85c48dc21f1428ea0656a00861eb260e48c0cf5..3853d9df751aef86b62e2cb30394cf0be1896efb 100644 --- a/dbrepo-ui/composables/identifier-service.ts +++ b/dbrepo-ui/composables/identifier-service.ts @@ -328,6 +328,9 @@ export const useIdentifierService = (): any => { } function databaseToServerHead(database: DatabaseDto) { + if (!database) { + return + } const config = useRuntimeConfig() /* Google Rich Results */ const json: any = { diff --git a/dbrepo-ui/composables/search-service.ts b/dbrepo-ui/composables/search-service.ts index 62be8b9bc7160f70e33969970fbbba1c500d288f..b61f8358cf74167d1fef5c6f2de54ef017d4c7aa 100644 --- a/dbrepo-ui/composables/search-service.ts +++ b/dbrepo-ui/composables/search-service.ts @@ -18,11 +18,11 @@ export const useSearchService = (): any => { }) } - async function fuzzy_search(term: string): Promise<SearchResultDto> { + async function fuzzy_search(term: string): Promise<DatabaseDto[]> { const axios = useAxiosInstance() console.debug('fuzzy search for term', term) - return new Promise<SearchResultDto>((resolve, reject) => { - axios.get<SearchResultDto>(`/api/search?q=${term}`) + return new Promise<DatabaseDto[]>((resolve, reject) => { + axios.get<DatabaseDto[]>(`/api/search?q=${term}`) .then((response) => { console.info('Searched for term', term) resolve(response.data) diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts index f2e7a3a2f9f07cf9ed25b1220190e22879ef7a83..ca757c7451d70c4bd1fffc36b72c6a23d7fdde58 100644 --- a/dbrepo-ui/composables/table-service.ts +++ b/dbrepo-ui/composables/table-service.ts @@ -29,7 +29,7 @@ export const useTableService = (): any => { resolve(response.data) }) .catch((error) => { - console.error('Failed to find table') + console.error('Failed to find table', error) reject(axiosErrorToApiError(error)) }) }) @@ -287,6 +287,7 @@ export const useTableService = (): any => { exportData, create, remove, + updateSemantics, removeTuple, history, suggest, diff --git a/dbrepo-ui/composables/view-service.ts b/dbrepo-ui/composables/view-service.ts index 4c948a57f10b5637cb441baa83e42bb9c3850a46..417f5a645e978cc8f93e7fc524df22756c5b093e 100644 --- a/dbrepo-ui/composables/view-service.ts +++ b/dbrepo-ui/composables/view-service.ts @@ -24,7 +24,7 @@ export const useViewService = (): any => { return new Promise<ViewDto>((resolve, reject) => { axios.get<ViewDto>(`/api/database/${databaseId}/view/${viewId}`) .then((response) => { - console.info('Deleted view with id', viewId, 'in database with id', databaseId) + console.info('Found view with id', viewId, 'in database with id', databaseId) resolve(response.data) }) .catch((error) => { diff --git a/dbrepo-ui/layouts/default.vue b/dbrepo-ui/layouts/default.vue index 8816ab5c9190662331e8ff86b85984cb92eec37f..ad00d8117309a83844d42d2c52faa44c34a55a0b 100644 --- a/dbrepo-ui/layouts/default.vue +++ b/dbrepo-ui/layouts/default.vue @@ -100,7 +100,7 @@ class="mr-2" color="secondary" variant="flat" - prepend-icon="mdi-login" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-login' : null" to="/login"> {{ $t('navigation.login') }} </v-btn> @@ -108,7 +108,7 @@ v-if="!user" color="primary" variant="flat" - prepend-icon="mdi-account-plus" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-account-plus' : null" to="/signup"> {{ $t('navigation.signup') }} </v-btn> @@ -150,32 +150,47 @@ <v-main> <v-container> <slot /> + <JumboBox + v-if="error" + :title="$t(errorCodeKey(error).title, { resource })" + :subtitle="$t(errorCodeKey(error).subtitle)" + :text="$t(errorCodeKey(error).text, { resource })" /> </v-container> </v-main> </v-app> </template> <script setup> -const config = useRuntimeConfig() +import { ref } from 'vue' + +const runtimeConfig = useRuntimeConfig() +const config = ref(runtimeConfig) useServerHead({ - title: config.public.title, + title: runtimeConfig.public.title, meta: [ - {'ref': 'icon', type: 'image/x-icon', href: config.public.icon}, - {'http-equiv': 'Content-Security-Policy', content: 'upgrade-insecure-requests'} + { 'ref': 'icon', type: 'image/x-icon', href: runtimeConfig.public.icon }, + { 'http-equiv': 'Content-Security-Policy', content: 'upgrade-insecure-requests' } ] }) </script> <script> +import JumboBox from '@/components/JumboBox.vue' import { useUserStore } from '@/stores/user' import { useCacheStore } from '@/stores/cache' +import { errorCodeKey, makeError } from '@/utils' export default { + components: { + JumboBox + }, data () { return { drawer: false, model: null, query: null, loading: true, + databaseError: null, + accessError: null, searchResults: [], databases: [], loadingUser: true, @@ -199,12 +214,36 @@ export default { messages () { return this.cacheStore.getMessages }, + access () { + return this.userStore.getAccess + }, table () { return this.cacheStore.getTable }, + view () { + return this.cacheStore.getView + }, + subset () { + return this.cacheStore.getSubset + }, database () { return this.cacheStore.getDatabase }, + resource () { + if (!this.$route.params.database_id) { + return null + } + if (this.$route.params.table_id) { + return 'table' + } + if (this.$route.params.view_id) { + return 'view' + } + if (this.$route.params.subset_id) { + return 'subset' + } + return 'database' + }, roles () { return this.userStore.getRoles }, @@ -220,6 +259,27 @@ export default { commitShort () { return this.$config.public.commit.substr(0, 8) }, + error () { + if (this.databaseError) { + return this.databaseError + } + if (this.accessError) { + return this.accessError + } + if (!this.user) { + return null + } + if (this.table && !this.table.is_public && !this.table.is_schema_public && this.table.owner.id !== this.user.id) { + return makeError(403, null, null) + } + if (this.view && !this.view.is_public && !this.view.is_schema_public && this.view.owner.id !== this.user.id) { + return makeError(403, null, null) + } + if (this.subset && !this.subset.is_public && !this.subset.is_schema_public && this.subset.owner.id !== this.user.id) { + return makeError(403, null, null) + } + return null + }, canListOntologies () { if (!this.roles) { return false @@ -244,18 +304,42 @@ export default { '$route.params': { handler (newObj, oldObj) { if (!newObj.database_id) { + this.databaseError = null + this.accessError = null + this.cacheStore.setTable(null) + this.cacheStore.setView(null) + this.cacheStore.setSubset(null) + return + } + if (import.meta.server) { return } /* load database and optional access */ this.cacheStore.setRouteDatabase(newObj.database_id) + .catch((error) => { + this.databaseError = error + }) if (this.user) { this.userStore.setRouteAccess(newObj.database_id) } - if (!newObj.table_id) { - return - } /* load table */ - this.cacheStore.setRouteTable(newObj.database_id, newObj.table_id) + if (newObj.table_id) { + this.cacheStore.setRouteTable(newObj.database_id, newObj.table_id) + } else { + this.cacheStore.setTable(null) + } + /* load view */ + if (newObj.view_id) { + this.cacheStore.setRouteView(newObj.database_id, newObj.view_id) + } else { + this.cacheStore.setView(null) + } + /* load subset */ + if (newObj.subset_id) { + this.cacheStore.setRouteSubset(newObj.database_id, newObj.subset_id) + } else { + this.cacheStore.setSubset(null) + } }, deep: true, immediate: true @@ -273,6 +357,7 @@ export default { this.cacheStore.reloadMessages() }, methods: { + errorCodeKey, login () { const redirect = ![undefined, '/', '/login'].includes(this.$router.currentRoute.path) this.$router.push({ path: '/login', query: redirect ? { redirect: this.$router.currentRoute.path } : {} }) diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 655ec2a345b98294cf6512c531f83a67c9196d3c..2e94f572ec68f7f3c595254ed5c9a5e14099e623 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -37,7 +37,8 @@ "modify": "Modify", "help": "Help", "visibility": "Visibility", - "update": "Update" + "update": "Update", + "you": "You" }, "pages": { "identifier": { @@ -291,12 +292,13 @@ "read": "You can read all contents of this table" } }, - "visibility": { - "title": "Visibility", - "open": "Open", - "data": "Data is public", - "schema": "Schema is public", - "closed": "Closed" + "settings": { + "title": "Metadata", + "subtitle": "Optional table description for humans and visibility settings" + }, + "delete": { + "title": "Delete this table", + "subtitle": "This action deletes {table} and all data in it, there is no going back" }, "description": { "title": "Description", @@ -599,16 +601,30 @@ "internal-name": { "title": "Internal Name" }, - "visibility": { - "title": "Visibility", - "open": "Open", - "data": "Data is public", - "schema": "Schema is public", - "closed": "Closed" - }, "size": { "title": "Size" }, + "status": { + "title": "Status", + "public": "Public", + "data": "Data-only", + "schema": "Schema-only", + "draft": "Draft" + }, + "resource": { + "data": { + "label": "Transparency", + "hint": "Required, e.g. can hide the {resource} from lists, search, etc.", + "enabled": "Visible", + "disabled": "Hidden" + }, + "schema": { + "label": "Insights", + "hint": "Required, e.g. can hide insights on the {resource} such as {schema}.", + "enabled": "Visible", + "disabled": "Hidden" + } + }, "owner": { "title": "Owner" }, @@ -625,7 +641,7 @@ }, "subpages": { "access": { - "title": "Database Access", + "title": "Access to database", "subtitle": "Overview on users with their access to the database", "read": "Read all contents", "write-own": "Read all contents & write own tables", @@ -649,22 +665,14 @@ "hint": "Required. The internal database name will be lowercase alphanumeric, others will be replaced with _", "placeholder": "e.g. my_database, air_quality" }, + "draft": { + "label": "Draft", + "hint": "Hides the database, only users with access can see it" + }, "engine": { "label": "Engine", "hint": "Required" }, - "visibility": { - "label": "Visibility", - "hint": "Required", - "public": { - "label": "Public", - "hint": "Everything is visible to the public, e.g. to publish data used in a open-access paper. You can later update the visibility of data." - }, - "private": { - "label": "Private", - "hint": "Nothing is visible to anyone without dedicated read-access, e.g. to work on a dataset. You can later update the visibility of data." - } - }, "submit": { "text": "Create" }, @@ -727,11 +735,6 @@ "hint": "Required", "help": "Public = visible to anyone, Private = visible only to designated users" }, - "schema": { - "label": "Schema Visibility", - "hint": "Required", - "help": "Public = visible to anyone, Private = visible only to designated users" - }, "submit": { "text": "Modify" } @@ -917,6 +920,14 @@ "visibility": { "title": "Visibility" }, + "delete": { + "title": "Delete this view", + "subtitle": "This action deletes {view}, there is no going back" + }, + "settings": { + "title": "Metadata", + "subtitle": "Visibility settings" + }, "subpages": { "create": { "title": "Create View", @@ -1088,6 +1099,18 @@ } }, "error": { + "permission": { + "title": "You do not have permission to view this {resource}", + "text": "This a default-fallback error message since this {resource} marked as private. Please try logging in or request read-access permissions from the owner." + }, + "missing": { + "title": "The requested {resource} was not found", + "text": "We could not find the requested {resource} anywhere." + }, + "gone": { + "title": "The requested {resource} does not exist anymore", + "text": "We could not find the requested {resource} anymore." + }, "auth": { "connection": "Failed to contact auth service", "invalid": "Failed to authenticate in auth service" @@ -1120,7 +1143,7 @@ }, "database": { "connection": "Failed to contact database", - "create": "Failed to create database in data service", + "create": "Failed to create database in data service", "invalid": "Failed to perform action in database", "querystore": "Failed to insert query into query store", "missing": "Failed to find database in metadata database" @@ -1273,18 +1296,18 @@ "dataset": "Successfully analysed dataset" }, "access": { - "created": "Successfully provisioned access", - "modified": "Successfully modified access", - "revoked": "Successfully revoked access" + "created": "Granted {access} access successfully", + "modified": "Updated {access} access successfully", + "revoked": "Revoked {access} access successfully" }, "data": { "add": "Successfully added data entry", "update": "Successfully updated data entry" }, "table": { - "created": "Successfully created table", + "created": "Created table {table} successfully", "semantics": "Successfully assigned semantic instance", - "updated": "Successfully updated table" + "updated": "Updated table {table} successfully" }, "schema": { "tables": "Successfully refreshed database tables metadata.", @@ -1310,7 +1333,7 @@ "info": "Successfully updated user information", "theme": "Successfully updated user theme", "password": "Successfully updated user password", - "login": "Successfully logged in" + "login": "Welcome back, {username}!" }, "view": { "create": "Successfully created view", @@ -1345,8 +1368,6 @@ "database": { "recent": "Recent Databases", "links": "Important Links", - "public": "Public", - "private": "Private", "current": "Current Data", "history": "Historic Data", "create": { diff --git a/dbrepo-ui/nuxt.config.ts b/dbrepo-ui/nuxt.config.ts index cc68f1bd909e30f56b9081c4b869ada488e38e86..4bce6ec5c5b3dc7f025734d9bf15d8e914123f79 100644 --- a/dbrepo-ui/nuxt.config.ts +++ b/dbrepo-ui/nuxt.config.ts @@ -20,8 +20,6 @@ if (process.env.NODE_ENV === 'development') { /** * https://nuxt.com/docs/guide/concepts/rendering#hybrid-rendering */ -const routeRules = {} - export default defineNuxtConfig({ app: { head: { @@ -105,8 +103,6 @@ export default defineNuxtConfig({ } }, - routeRules, - devServer: { port: 3001 }, diff --git a/dbrepo-ui/package.json b/dbrepo-ui/package.json index 856f56f4f0294cbc555f7d8d0a3d2e931d45ea58..a1354778200ebabb28a575e204e264e6bd155774 100644 --- a/dbrepo-ui/package.json +++ b/dbrepo-ui/package.json @@ -23,6 +23,7 @@ "buffer": "^6.0.3", "chart.js": "^4.4.1", "date-fns": "^3.3.1", + "http-status-codes": "^2.3.0", "jwt-decode": "^4.0.0", "merkle-json": "^2.6.0", "moment": "^2.30.1", diff --git a/dbrepo-ui/pages/database/[database_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/info.vue index 5b739987fdcaa422d31e0fc2545bcdeacbdf38ad..02c2c8310ae9bafe8ce458decf6ccdd86a6cba37 100644 --- a/dbrepo-ui/pages/database/[database_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/info.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="canViewSchema"> <DatabaseToolbar /> <v-window v-model="tab"> @@ -58,26 +59,13 @@ </div> </v-list-item> <v-list-item - :title="$t('pages.database.visibility.title')" - density="compact"> - {{ databaseVisibility }} - </v-list-item> - <v-list-item + v-if="databaseSize" :title="$t('pages.database.size.title')" density="compact"> <div> {{ databaseSize }} </div> </v-list-item> - <v-list-item - :title="$t('pages.database.owner.title')" - density="compact"> - <div> - <UserBadge - :user="database.owner" - :other-user="user" /> - </div> - </v-list-item> <v-list-item v-if="access && access.type" :title="$t('pages.database.subpages.access.title')" @@ -101,11 +89,13 @@ </div> </v-list-item> <v-list-item - v-if="access" - :title="$t('pages.database.connection.title')" + :title="$t('pages.database.owner.title')" density="compact"> - <pre - class="pb-1">{{ jdbcString }}</pre> + <div> + <UserBadge + :user="database.owner" + :other-user="user" /> + </div> </v-list-item> <v-list-item v-if="database.contact" @@ -173,22 +163,12 @@ </div> </template> -<script setup> -const config = useRuntimeConfig() -const { database_id } = useRoute().params -const { data } = await useFetch(`${config.public.api.server}/api/database/${database_id}`) -if (data.value) { - const identifierService = useIdentifierService() - useServerHead(identifierService.databaseToServerHead(data.value)) - useServerSeoMeta(identifierService.databaseToServerSeoMeta(data.value)) -} -</script> <script> 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 { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils' +import { sizeToHumanLabel } from '@/utils' import { useUserStore } from '@/stores/user' import { useCacheStore } from '@/stores/cache' @@ -201,6 +181,7 @@ export default { }, data () { return { + error: null, items: [ { title: this.$t('navigation.databases'), @@ -245,6 +226,9 @@ export default { user () { return this.userStore.getUser }, + database () { + return this.cacheStore.getDatabase + }, roles () { return this.userStore.getRoles }, @@ -261,7 +245,7 @@ export default { if (!this.user) { return this.identifiers.filter(i => i.status === 'published') } - return this.identifiers.filter(i => i.status === 'published' || i.creator.id === this.user.id) + return this.identifiers.filter(i => i.status === 'published' || i.owner.id === this.user.id) }, identifier () { if (this.pid) { @@ -275,9 +259,6 @@ export default { access () { return this.userStore.getAccess }, - database () { - return this.cacheStore.getDatabase - }, pid () { return this.$route.query.pid }, @@ -337,13 +318,6 @@ export default { return { text: null, class: null } } }, - jdbcString () { - if (!this.database || !this.user) { - return - } - const flags = this.database.container.ui_additional_flags ? this.database.container.ui_additional_flags : '' - return `jdbc:${this.database.container.image.jdbc_method}://${this.database.container.ui_host}:${this.database.container.ui_port}/${this.database.internal_name}${flags} (${this.$t('pages.database.connection.username')}=${this.user.username}, ${this.$t('pages.database.connection.password')}=yourpassword)` - }, databaseExtraInfo () { return this.$config.public.database.extra }, @@ -355,23 +329,17 @@ export default { this.database.tables.forEach((t) => { sum += t.data_length }) return sizeToHumanLabel(sum) }, - databaseVisibility () { - if (!this.database) { - return null - } - if (this.database.is_public && this.database.is_schema_public) { - return this.$t('pages.database.visibility.open') - } - if (!this.database.is_public && !this.database.is_schema_public) { - return this.$t('pages.database.visibility.closed') - } - return this.database.is_public ? this.$t('pages.database.visibility.data') : this.$t('pages.database.visibility.schema') - }, previewImage () { if (!this.database) { return null } return this.database.preview_image + }, + canViewSchema () { + if (this.error) { + return false + } + return this.database } } } diff --git a/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue index 7de1348fdce246da3f47d8869f9705d13d5f7c7d..a57b439b216ae4743fd4bda292dc53e5f7e05a69 100644 --- a/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue @@ -1,6 +1,9 @@ <template> - <div v-if="canCreateIdentifier || canUpdateIdentifier"> - <Persist type="database" :database="database" /> + <div + v-if="canCreateIdentifier || canUpdateIdentifier"> + <Persist + type="database" + :database="database" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> diff --git a/dbrepo-ui/pages/database/[database_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/persist/index.vue index 0981a547905ad08494c980c3d07dce2242c4ea04..df675d262e8e116b0c4252d74fe6878681388acb 100644 --- a/dbrepo-ui/pages/database/[database_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/persist/index.vue @@ -1,6 +1,9 @@ <template> - <div v-if="canCreateIdentifier || canUpdateIdentifier"> - <Persist type="database" :database="database" /> + <div + v-if="canCreateIdentifier || canUpdateIdentifier"> + <Persist + type="database" + :database="database" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> diff --git a/dbrepo-ui/pages/database/[database_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/settings.vue index b3d5b634613c358b01bc13d53f270fe7ef7e4d2a..aed13a4e1e3ca25db85b8f905415a55336ba9fa2 100644 --- a/dbrepo-ui/pages/database/[database_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/settings.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="canView"> <DatabaseToolbar ref="toolbar" /> <v-window @@ -132,56 +133,35 @@ :title="$t('pages.database.subpages.settings.visibility.title')" :subtitle="$t('pages.database.subpages.settings.visibility.subtitle')"> <v-card-text> - <v-row> - <v-col md="8"> + <v-row + dense> + <v-col + md="4"> <v-select v-model="modifyVisibility.is_public" - :items="visibility" - :variant="inputVariant" - :label="$t('pages.database.subpages.settings.visibility.data.label')" - :hint="$t('pages.database.subpages.settings.visibility.data.hint')" + :items="dataOptions" persistent-hint - name="visibility"> - <template - v-slot:append> - <v-tooltip - location="bottom"> - <template - v-slot:activator="{ props }"> - <v-icon - v-bind="props" - icon="mdi-help-circle-outline" /> - </template> - {{ $t('pages.database.subpages.settings.visibility.data.help') }} - </v-tooltip> - </template> - </v-select> + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'database' })" /> </v-col> - </v-row> - <v-row> - <v-col md="8"> + <v-col + md="4"> <v-select v-model="modifyVisibility.is_schema_public" - :items="visibility" - :variant="inputVariant" - :label="$t('pages.database.subpages.settings.visibility.schema.label')" - :hint="$t('pages.database.subpages.settings.visibility.schema.hint')" + :items="schemaOptions" persistent-hint - name="schema-visibility"> - <template - v-slot:append> - <v-tooltip - location="bottom"> - <template - v-slot:activator="{ props }"> - <v-icon - v-bind="props" - icon="mdi-help-circle-outline" /> - </template> - {{ $t('pages.database.subpages.settings.visibility.schema.help') }} - </v-tooltip> - </template> - </v-select> + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'database', schema: 'tables, views, subsets' })" /> </v-col> </v-row> <v-row> @@ -302,15 +282,13 @@ export default { modifyImage: { key: null }, - visibility: [ - { - title: this.$t('toolbars.database.public'), - value: true - }, - { - title: this.$t('toolbars.database.private'), - value: false - } + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, ], headers: [ { @@ -428,6 +406,12 @@ export default { } return this.roles.includes('modify-database-image') }, + canView () { + if (this.error) { + return false + } + return this.database + }, previewImage () { if (this.file) { return URL.createObjectURL(this.file) @@ -541,10 +525,13 @@ export default { this.modifyImage.key = null this.loadingImage = false }) - .catch(() => { - const toast = useToastInstance() - toast.error('Failed to modify image') + .catch(({code}) => { this.loadingImage = false + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) }) .finally(() => { this.loadingImage = false diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue index 3ac8f40d645b44449f5607b9f3b031d06fa463d6..37c34a71677e1e8aa92464d43c47d89a95d22a81 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue @@ -33,7 +33,9 @@ :loading="loadingSubset" @click="loadSubset" /> </v-toolbar> - <v-card tile> + <v-card + v-if="subset" + tile> <QueryResults id="query-results" ref="queryResults" @@ -84,9 +86,6 @@ export default { disabled: true } ], - subset: { - id: this.$route.params.subset_id - }, cacheStore: useCacheStore() } }, @@ -94,6 +93,9 @@ export default { database () { return this.cacheStore.getDatabase }, + subset () { + return this.cacheStore.getSubset + }, executionUTC () { if (!this.subset) { return null @@ -113,11 +115,11 @@ export default { if (this.database.is_public) { return true } - return this.subset.creator.username === this.username + return this.subset.owner.username === this.username }, }, mounted () { - this.loadSubset() + this.loadResult() }, methods: { loadSubset () { @@ -136,8 +138,10 @@ export default { }) }, loadResult () { - this.$refs.queryResults.reExecute(this.subset.id) - this.$refs.queryResults.reExecuteCount(this.subset.id) + if (this.subset) { + this.$refs.queryResults.reExecute(this.subset.id) + this.$refs.queryResults.reExecuteCount(this.subset.id) + } }, download () { this.downloadLoading = true @@ -155,6 +159,9 @@ export default { .catch(({code}) => { this.downloadLoading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { @@ -164,5 +171,3 @@ export default { } } </script> -<style> -</style> diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue index 764d1b55ffa6b134c07e86290325525caa8919b2..f27153bebfc710b82f25fb0cc3d3a92297472aac 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue @@ -22,7 +22,7 @@ :title="$t('pages.subset.title')"> <v-card-text> <v-list - v-if="loadingSubset && !subset" + v-if="!subset" lines="two" dense> <v-skeleton-loader @@ -37,7 +37,14 @@ v-if="database" :title="$t('pages.subset.visibility.title')" density="compact"> - {{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }} + <ResourceStatus + v-if="!identifier" + :inline="true" + :resource="database" /> + <ResourceStatus + v-else + :inline="true" + :resource="identifier" /> </v-list-item> <v-list-item v-if="subset.creator" @@ -64,7 +71,8 @@ <v-list-item :title="`${$t('pages.subset.result.title')} ${$t('pages.subset.hash.title')}`" density="compact"> - <pre>{{ $t('pages.subset.hash.prefix') }}:{{ result_hash }}</pre> + <pre v-if="subset.result_hash">{{ $t('pages.subset.hash.prefix') }}:{{ subset.result_hash }}</pre> + <span v-else>(none)</span> </v-list-item> <v-list-item :title="$t('pages.subset.rows.title')" @@ -74,49 +82,10 @@ </v-list> </v-card-text> </v-card> - <v-divider /> - <v-card - :title="$t('pages.database.title')" - variant="flat" - rounded="0"> - <v-card-text> - <v-list - v-if="database" - dense> - <v-list-item - :title="$t('pages.database.visibility.title')"> - {{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }} - </v-list-item> - <v-list-item - :title="$t('pages.database.name.title')"> - <NuxtLink - class="text-primary" - :to="`/database/${database.id}`"> - {{ database.internal_name }} - </NuxtLink> - </v-list-item> - </v-list> - </v-card-text> - </v-card> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> -<script setup> -const config = useRuntimeConfig() -const { database_id, subset_id } = useRoute().params -const requestConfig = { timeout: 90_000, headers: { Accept: 'application/json', 'Content-Type': 'application/json' } } -const userStore = useUserStore() -if (userStore.getToken) { - requestConfig.headers.Authorization = `Bearer ${userStore.getToken}` -} -const { data } = await useFetch(`${config.public.api.server}/api/database/${database_id}/subset/${subset_id}`, requestConfig) -if (data.value) { - const identifierService = useIdentifierService() - useServerHead(identifierService.subsetToServerHead(data.value)) - useServerSeoMeta(identifierService.subsetToServerSeoMeta(data.value)) -} -</script> <script> import Summary from '@/components/identifier/Summary.vue' import SubsetToolbar from '@/components/subset/SubsetToolbar.vue' @@ -162,11 +131,9 @@ export default { persistQueryDialog: false, loadingDatabase: false, loadingIdentifier: false, - loadingSubset: true, downloadLoading: false, error: false, promises: [], - subset: null, userStore: useUserStore(), cacheStore: useCacheStore() } @@ -181,6 +148,9 @@ export default { access () { return this.userStore.getAccess }, + subset () { + return this.cacheStore.getSubset + }, user () { return this.userStore.getUser }, @@ -212,12 +182,6 @@ export default { } return enTitle[0].title }, - result_hash () { - if (!this.subset.result_hash) { - return '(none)' - } - return this.subset.result_hash - }, publisher () { if (this.database.publisher === null) { return 'NA' @@ -230,25 +194,6 @@ export default { } return formatTimestampUTCLabel(this.subset.created) } - }, - mounted () { - this.loadSubset() - }, - methods: { - loadSubset () { - this.loadingSubset = true - const queryService = useQueryService() - queryService.findOne(this.$route.params.database_id, this.$route.params.subset_id) - .then((subset) => { - this.subset = subset - }) - .catch(() => { - this.loadingSubset = false - }) - .finally(() => { - this.loadingSubset = false - }) - } } } </script> diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue index a3b7306643fbc455475e882b41b86ae1744ae013..b15ecb3292520979e550f68c7c16ef873638b124 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue @@ -1,6 +1,9 @@ <template> - <div v-if="canCreateIdentifier || canUpdateIdentifier"> - <Persist type="subset" :database="database" /> + <div + v-if="canCreateIdentifier || canUpdateIdentifier"> + <Persist + type="subset" + :database="database" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue index 01ba88a36c32142f68dbdeb94da99c86cdf10197..07be66bc73911c9bd7580991ef2c71c6d36de5bc 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue @@ -1,6 +1,10 @@ <template> - <div v-if="canPersistQuery"> - <Persist type="subset" :database="database" :query="query" /> + <div + v-if="canPersistQuery"> + <Persist + type="subset" + :database="database" + :query="query" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> diff --git a/dbrepo-ui/pages/database/[database_id]/subset/create.vue b/dbrepo-ui/pages/database/[database_id]/subset/create.vue index 5202bc633626e135e263056fa39b5022676c1575..b533dfb1a8e0af06cd1428032ebf188c9d3c4b0f 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/create.vue @@ -1,5 +1,6 @@ <template> - <div v-if="canCreateSubset"> + <div + v-if="canCreateSubset"> <Builder /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> diff --git a/dbrepo-ui/pages/database/[database_id]/subset/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/index.vue index 8d454ce83d11a4f6143093ecb20d268b1897a9d2..d031b3f3f654f260099e109cc17f5c61cf0c4eb6 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/index.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="canViewSchema"> <DatabaseToolbar /> <SubsetList /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> @@ -8,6 +9,7 @@ <script> import SubsetList from '@/components/subset/SubsetList.vue' +import { useCacheStore } from '@/stores/cache' export default { components: { @@ -29,7 +31,19 @@ export default { to: `/database/${this.$route.params.database_id}/subset`, disabled: true } - ] + ], + cacheStore: useCacheStore() + } + }, + computed: { + database () { + return this.cacheStore.getDatabase + }, + canViewSchema () { + if (this.error) { + return false + } + return this.database } } } diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue index cac7b4ab3dfca87c882b5032d9ed87dbd8ee356b..46e7f564a77cb4592c4df36c0bf07f5ce66f8ac1 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue @@ -9,14 +9,14 @@ <v-spacer /> <v-btn v-if="canAddTuple" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-plus' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-plus' : null" variant="flat" :text="$t('toolbars.table.data.add')" class="ml-2" @click="addTuple" /> <v-btn v-if="canEditTuple" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-pencil' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-pencil' : null" color="warning" variant="flat" :text="$t('toolbars.table.data.edit')" @@ -24,7 +24,7 @@ @click="editTuple" /> <v-btn v-if="canDeleteTuple" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-delete' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-delete' : null" color="error" variant="flat" :text="$t('toolbars.table.data.delete')" @@ -32,14 +32,14 @@ :loading="loadingDelete" @click="deleteItems" /> <v-btn - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-download' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-download' : null" variant="flat" :loading="downloadLoading" :text="$t('toolbars.table.data.download')" class="ml-2" @click.stop="download" /> <v-btn - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-refresh' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-refresh' : null" variant="flat" :text="$t('toolbars.table.data.refresh')" class="ml-2" @@ -47,7 +47,7 @@ :loading="loadingData" @click="reload" /> <v-btn - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-update' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-update' : null" variant="flat" :text="$t('toolbars.table.data.version')" class="ml-2 mr-2" @@ -61,13 +61,16 @@ {{ $t('error.table.connection') }} </v-card-text> </v-card> - <v-card tile> + <v-card + tile> <QueryResults id="query-results" ref="queryResults" + class="mt-0 mb-0" type="table" + :select="canSelectTuples" :timestamp="versionISO || lastReload.toISOString()" - class="mt-0 mb-0" /> + @selection="updateSelect" /> </v-card> <v-dialog v-model="pickVersionDialog" @@ -144,7 +147,6 @@ export default { version: null, lastReload: new Date(), tab: null, - error: false, tuple: null, options: { page: 1, @@ -193,9 +195,6 @@ export default { user () { return this.userStore.getUser }, - tables () { - return this.cacheStore.getTable - }, access () { return this.userStore.getAccess }, @@ -238,8 +237,16 @@ export default { } return this.access.type === 'write_all' }, + primaryKeyColumns () { + if (!this.table) { + return [] + } + return this.table.constraints.primary_key.map(pk => pk.column) + }, canViewTableData () { - /* view when database is public or when private: 1) view-table-data role present 2) access is at least read */ + if (this.error) { + return false + } if (!this.table) { return false } @@ -258,6 +265,13 @@ export default { const userService = useUserService() return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('insert-table-data') }, + canSelectTuples () { + if (!this.roles) { + return false + } + const userService = useUserService() + return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('insert-table-data') + }, canEditTuple () { if (!this.roles || this.selection === null || this.selection.length !== 1) { return false @@ -299,8 +313,7 @@ export default { for (const select of this.selection) { /* remove in container */ const constraints = {} - this.columns - .filter(c => c.is_primary_key) + this.primaryKeyColumns .forEach((c) => { constraints[c.internal_name] = select[c.internal_name] }) @@ -313,9 +326,12 @@ export default { } const tupleService = useTupleService() wait.push(tupleService.remove(this.$route.params.database_id, this.$route.params.table_id, { keys: constraints }) - .catch(({message}) => { + .catch(({code, message}) => { const toast = useToastInstance() - toast.error(message) + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) })) } Promise.all(wait) @@ -324,6 +340,7 @@ export default { toast.success(`Deleted ${this.selection.length} row(s)`) this.$emit('modified', { success: true, action: 'delete' }) this.selection = [] + this.$refs.queryResults.resetSelection() this.reload() }) this.loadingDelete = false @@ -345,6 +362,9 @@ export default { .catch(({code}) => { this.downloadLoading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { @@ -364,6 +384,9 @@ export default { .catch(({code}) => { this.downloadLoading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { @@ -390,11 +413,14 @@ export default { }, reload () { this.lastReload = new Date() + if (!this.canViewTableData) { + return + } this.$refs.queryResults.reExecute(Number(this.$route.params.table_id)) this.$refs.queryResults.reExecuteCount(Number(this.$route.params.table_id)) }, isFileField (column) { - return ['blob', 'longblob', 'mediumblob', 'tinyblob'].includes(column.column_type) + return ['blob', 'longblob', 'mediumblob', 'tinyblob'].includes(column.type) }, close ({ success }) { console.debug('closed edit/create tuple dialog') @@ -403,7 +429,11 @@ export default { if (success) { this.reload() this.selection = [] + this.$refs.queryResults.resetSelection() } + }, + updateSelect (selection) { + this.selection = selection } } } 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 5f322fa498b4b05607db6422cc7964d98515cb74..8108e0677e040b5ce500b188e64857398a9c3cb6 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 @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="canViewSchema"> <TableToolbar :selection="selection" /> <v-card @@ -21,45 +22,24 @@ rounded="0" :title="$t('pages.table.title')"> <v-card-text> - <v-skeleton-loader - v-if="!cachedTable" - type="list-item-three-line" - width="50%" /> <v-list - v-if="cachedTable" dense> - <v-list-item - :title="$t('pages.table.id.title')"> - {{ cachedTable.id }} - </v-list-item> <v-list-item :title="$t('pages.table.name.title')"> - {{ cachedTable.internal_name }} - </v-list-item> - <v-list-item - :title="$t('pages.table.visibility.title')"> - {{ databaseVisibility }} + {{ table.internal_name }} </v-list-item> <v-list-item - v-if="table" :title="$t('pages.table.size.title')"> {{ sizeToHumanLabel(table.data_length) }} </v-list-item> <v-list-item - v-if="table" + v-if="canRead && table.num_rows" :title="$t('pages.table.rows.title')"> {{ table.num_rows }} </v-list-item> <v-list-item :title="$t('pages.table.description.title')"> - {{ hasDescription ? cachedTable.description : $t('pages.table.description.empty') }} - </v-list-item> - <v-list-item - :title="$t('pages.table.owner.title')"> - <UserBadge - v-if="table" - :user="table.owner" - :other-user="user" /> + {{ hasDescription ? table.description : $t('pages.table.description.empty') }} </v-list-item> <v-list-item v-if="accessDescription" @@ -80,6 +60,12 @@ </span> </span> </v-list-item> + <v-list-item + :title="$t('pages.table.owner.title')"> + <UserBadge + :user="table.owner" + :other-user="user" /> + </v-list-item> </v-list> </v-card-text> </v-card> @@ -128,49 +114,15 @@ </v-list> </v-card-text> </v-card> - <v-divider /> - <v-card - :title="$t('pages.database.title')" - variant="flat"> - <v-card-text> - <v-list dense> - <v-list-item - v-if="database" - :title="$t('pages.database.visibility.title')"> - {{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }} - </v-list-item> - <v-list-item - v-if="database" - :title="$t('pages.database.name.title')"> - <NuxtLink - class="text-primary" - :to="`/database/${database.id}`"> - {{ database.internal_name }} - </NuxtLink> - </v-list-item> - </v-list> - </v-card-text> - </v-card> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> -<script setup> -const config = useRuntimeConfig() -const { database_id, table_id } = useRoute().params -const { data } = await useFetch(`${config.public.api.server}/api/database/${database_id}/table/${table_id}`) -if (data.value) { - const identifierService = useIdentifierService() - useServerHead(identifierService.tableToServerHead(data.value)) - useServerSeoMeta(identifierService.tableToServerSeoMeta(data.value)) -} -</script> <script> import TableToolbar from '@/components/table/TableToolbar.vue' import Select from '@/components/identifier/Select.vue' import Summary from '@/components/identifier/Summary.vue' import UserBadge from '@/components/user/UserBadge.vue' -import { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils' import { useUserStore } from '@/stores/user' import { useCacheStore } from '@/stores/cache' @@ -185,7 +137,6 @@ export default { return { selection: [], consumers: [], - table: null, items: [ { title: this.$t('navigation.databases'), @@ -228,7 +179,7 @@ export default { database () { return this.cacheStore.getDatabase }, - cachedTable () { + table () { return this.cacheStore.getTable }, roles () { @@ -243,17 +194,32 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' }, + canViewSchema () { + if (this.error) { + return false + } + if (!this.table) { + return false + } + if (this.table.is_schema_public || this.table.is_public) { + return true + } + if (!this.user) { + return false + } + return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id + }, canWrite () { if (!this.table || !this.user || !this.access) { return false } - return (this.access.type === 'write_own' && this.cachedTable.owned_by === this.user.id) || this.access.type === 'write_all' + return (this.access.type === 'write_own' && this.table.owned_by === this.user.id) || this.access.type === 'write_all' }, access () { return this.userStore.getAccess }, hasDescription () { - return this.table && this.cachedTable.description + return this.table && this.table.description }, canWriteQueues () { if (!this.roles) { @@ -317,40 +283,6 @@ export default { } else if (this.canRead) { return this.$t('pages.table.connection.permissions.read') } - }, - databaseVisibility () { - if (!this.database) { - return null - } - if (this.database.is_public && this.cachedTable.is_schema_public) { - return this.$t('pages.table.visibility.open') - } - if (!this.database.is_public && !this.cachedTable.is_schema_public) { - return this.$t('pages.table.visibility.closed') - } - return this.database.is_public ? this.$t('pages.database.visibility.data') : this.$t('pages.database.visibility.schema') - } - }, - mounted () { - this.fetchTable() - }, - methods: { - fetchTable () { - this.loading = true - const tableService = useTableService() - tableService.findOne(this.$route.params.database_id, this.$route.params.table_id) - .then((table) => { - this.loading = false - this.table = table - }) - .catch(({code}) => { - this.loading = false - const toast = useToastInstance() - toast.error(this.$t(code)) - }) - .finally(() => { - this.loading = false - }) } } } diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue index 076b46217d4f280e5ded0e1cb94ca8c6c4110881..d444ca4e6229886522e39c0ad8a35b3988fb022e 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue @@ -1,14 +1,15 @@ <template> - <div v-if="canCreateIdentifier || canUpdateIdentifier"> + <div + v-if="canCreateIdentifier || canUpdateIdentifier"> <Persist type="table" :database="database" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' export default { components: { diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue index 8ab4f83a25293ee0d9338f87c0c35b378a123a6f..af5b613df9673387bc4ab660487de4717524ab02 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue @@ -12,9 +12,9 @@ </template> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' export default { components: { @@ -75,5 +75,3 @@ export default { } } </script> -<style> -</style> diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue index 5364b6c8997e4e336852f02747f2b7bfc6b08ee7..0c92401672bf743943dc1f35bdef3d42cd0df3d0 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue @@ -160,7 +160,7 @@ export default { ], headers: [ { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') }, - { value: 'column_type', title: this.$t('pages.table.subpages.schema.column-type.title') }, + { value: 'type', title: this.$t('pages.table.subpages.schema.column-type.title') }, { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') }, { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, @@ -195,6 +195,9 @@ export default { return this.userStore.getRoles }, canViewSchema () { + if (this.error) { + return false + } if (!this.table) { return false } @@ -204,7 +207,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.table.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id }, primaryKeysColumns () { return this.table.constraints.primary_key.map(pk => pk.column.internal_name).join(', ') @@ -236,9 +239,9 @@ export default { }, methods: { extra (column) { - if (column.column_type === 'float') { + if (column.type === 'float') { return `precision=${column.size}` - } else if (['decimal', 'double'].includes(column.column_type)) { + } else if (['decimal', 'double'].includes(column.type)) { let extra = '' if (column.size !== null) { extra += `size=${column.size}` @@ -250,11 +253,11 @@ export default { extra += `d=${column.d}` } return extra - } else if (column.column_type === 'enum') { + } else if (column.type === 'enum') { return `(${column.enums.join(', ')})` - } else if (column.column_type === 'set') { + } else if (column.type === 'set') { return `(${column.sets.join(', ')})` - } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.column_type)) { + } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.type)) { return column.size !== null ? `size=${column.size}` : '' } return null diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..201917c5c051ffd63028fdb7f6f631e9b0dafce7 --- /dev/null +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue @@ -0,0 +1,344 @@ +<template> + <div + v-if="canUpdateTable"> + <TableToolbar /> + <v-window + v-if="user" + v-model="tab"> + <v-window-item> + <v-form + ref="form" + v-model="valid" + autocomplete="off" + @submit.prevent="submit"> + <v-card + variant="flat" + rounded="0" + :title="$t('pages.table.settings.title')" + :subtitle="$t('pages.table.settings.subtitle')"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-textarea + v-model="modify.description" + rows="2" + :rules="[ + v => !max(v, 180) || ($t('validation.max-length') + 180), + ]" + clearable + counter="180" + persistent-counter + persistent-hint + :variant="inputVariant" + :hint="$t('pages.table.subpages.import.description.hint')" + :label="$t('pages.table.subpages.import.description.label')"/> + </v-col> + </v-row> + <v-row + dense> + <v-col + md="4"> + <v-select + v-model="modify.is_public" + :items="dataOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'table' })" /> + </v-col> + <v-col + md="4"> + <v-select + v-model="modify.is_schema_public" + :items="schemaOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'table', schema: 'columns' })" /> + </v-col> + </v-row> + <v-row> + <v-col> + <v-btn + id="database" + variant="flat" + size="small" + :disabled="!valid || !isChange" + :color="buttonColor" + :loading="loading" + type="submit" + :text="$t('navigation.modify')" + @click="update" /> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-form> + <v-divider + v-if="canDropTable" /> + <v-card + v-if="canDropTable" + variant="flat" + rounded="0" + :title="$t('pages.table.delete.title')" + :subtitle="$t('pages.table.delete.subtitle', { table: table.internal_name })"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-btn + size="small" + variant="flat" + color="error" + @click="askDelete"> + {{ $t('navigation.delete')}} + </v-btn> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-window-item> + </v-window> + <v-breadcrumbs + :items="items" + class="pa-0 mt-2" /> + </div> +</template> + +<script> +import TableToolbar from '@/components/table/TableToolbar.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' +import { max } from '@/utils' + +export default { + components: { + TableToolbar + }, + data () { + return { + tab: 0, + valid: false, + loading: false, + modify: { + description: null, + is_public: null, + is_schema_public: null + }, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, + ], + items: [ + { + title: this.$t('navigation.databases'), + to: '/database' + }, + { + title: `${this.$route.params.database_id}`, + to: `/database/${this.$route.params.database_id}/info` + }, + { + title: this.$t('navigation.tables'), + to: `/database/${this.$route.params.database_id}/table` + }, + { + title: `${this.$route.params.table_id}`, + to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}` + }, + { + title: this.$t('navigation.settings'), + to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/settings`, + disabled: true + } + ], + headers: [ + { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') }, + { value: 'type', title: this.$t('pages.table.subpages.schema.column-type.title') }, + { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') }, + { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, + { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, + { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') }, + { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, + ], + dateColumns: [], + userStore: useUserStore(), + cacheStore: useCacheStore() + } + }, + computed: { + user () { + return this.userStore.getUser + }, + database () { + return this.cacheStore.getDatabase + }, + table () { + return this.cacheStore.getTable + }, + access () { + return this.userStore.getAccess + }, + hasReadAccess () { + if (!this.access) { + return false + } + return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' + }, + roles () { + return this.userStore.getRoles + }, + isChange () { + if (!this.table) { + return false + } + if (this.table.is_public !== this.modify.is_public) { + return true + } + return this.table.is_schema_public !== this.modify.is_schema_public + }, + canUpdateTable () { + if (!this.roles || !this.user || !this.table) { + return false + } + return this.roles.includes('update-table') && this.table.owner.id === this.user.id + }, + canModifyVisibility () { + if (!this.roles || !this.user || !this.table) { + return false + } + return this.roles.includes('update-table') && this.table.owner.id === this.user.id + }, + canDropTable () { + if (!this.roles || !this.table || !this.user) { + return false + } + if (this.roles.includes('delete-foreign-table')) { + return true + } + const tableService = useTableService() + return tableService.isOwner(this.table, this.user) && this.roles.includes('delete-table') && this.table.identifiers.length === 0 + }, + inputVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal + }, + buttonVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal + }, + buttonColor () { + return !this.isChange ? null : 'warning' + } + }, + mounted() { + if (!this.table) { + return + } + this.modify.is_public = this.table.is_public + this.modify.is_schema_public = this.table.is_schema_public + this.modify.description = this.table.description + }, + methods: { + max, + submit () { + this.$refs.form.validate() + }, + extra (column) { + if (column.type === 'float') { + return `precision=${column.size}` + } else if (['decimal', 'double'].includes(column.type)) { + let extra = '' + if (column.size !== null) { + extra += `size=${column.size}` + } + if (column.d !== null) { + if (extra.length > 0) { + extra += ', ' + } + extra += `d=${column.d}` + } + return extra + } else if (column.type === 'enum') { + return `(${column.enums.join(', ')})` + } else if (column.type === 'set') { + return `(${column.sets.join(', ')})` + } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.type)) { + return column.size !== null ? `size=${column.size}` : '' + } + return null + }, + closed (event) { + const { success } = event + console.debug('closed dialog', event) + if (success) { + const toast = useToastInstance() + toast.success(this.$t('success.table.semantics')) + this.cacheStore.reloadTable() + } + this.dialogSemantic = false + }, + update () { + this.loading = true + const tableService = useTableService() + tableService.update(this.$route.params.database_id, this.$route.params.table_id, this.modify) + .then(() => { + this.loading = false + const toast = useToastInstance() + toast.success(this.$t('success.table.updated', { table: this.table.internal_name })) + this.$emit('close', { success: true }) + this.cacheStore.reloadTable() + }) + .catch(({ code }) => { + this.loading = false + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) + }) + .finally(() => { + this.loading = false + }) + }, + askDelete () { + if (!confirm(this.$t('pages.table.delete.subtitle', { table: this.table.internal_name }))) { + return + } + this.loadingDelete = true + const tableService = useTableService() + tableService.remove(this.database.id, this.table.id) + .then(() => { + console.info('Deleted table with id ', this.table.id) + this.cacheStore.reloadDatabase() + const toast = useToastInstance() + toast.success('Successfully deleted table with id ' + this.table.id) + this.$router.push(`/database/${this.$route.params.database_id}/table`) + }) + .catch(({code, message}) => { + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) + }) + .finally(() => { + this.loadingDelete = false + }) + } + } +} +</script> diff --git a/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue b/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue index 29773c24d98801f1c710a87e2cf513a842f562eb..b031c846ea41b1e3932197401aba95afc9acbb9e 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue @@ -1,5 +1,6 @@ <template> - <div v-if="canInsertTableData"> + <div + v-if="canInsertTableData"> <v-toolbar flat> <v-btn class="mr-2" @@ -10,214 +11,219 @@ <v-toolbar-title :text="$t('pages.table.subpages.import.title')"/> </v-toolbar> - <v-card - variant="flat" - rounded="0"> - <v-card-text> - <v-row> - <v-col - md="8"> - <v-alert - border="start" - color="info"> - {{ $t('pages.table.subpages.import.dataset.text') }} - <NuxtLink - :href="`/database/${$route.params.database_id}/table/create/schema`"> - {{ $t('pages.table.subpages.import.schema.text') }} - </NuxtLink> - </v-alert> - </v-col> - </v-row> - </v-card-text> - <v-card-text> - <v-stepper - vertical - variant="flat"> - <v-stepper-header> - <v-stepper-item - :title="$t('pages.table.subpages.import.metadata.title')" - :complete="validStep1" - :value="1"/> - </v-stepper-header> - <v-stepper-window - direction="vertical"> - <v-form - ref="form" - v-model="validStep1" - :disabled="step > 4" - @submit.prevent="submit"> + <v-form + ref="form" + v-model="valid" + @submit.prevent="submit"> + <v-card + variant="flat" + rounded="0"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-alert + border="start" + color="info"> + {{ $t('pages.table.subpages.import.dataset.text') }} + <NuxtLink + :href="`/database/${$route.params.database_id}/table/create/schema`"> + {{ $t('pages.table.subpages.import.schema.text') }} + </NuxtLink> + </v-alert> + </v-col> + </v-row> + </v-card-text> + <v-card-text> + <v-stepper + vertical + variant="flat"> + <v-stepper-header> + <v-stepper-item + :title="$t('pages.table.subpages.import.metadata.title')" + :complete="validStep1" + :value="1"/> + </v-stepper-header> + <v-stepper-window + direction="vertical"> + <v-form + ref="form" + v-model="validStep1" + :disabled="step > 4" + @submit.prevent="submit"> + <v-container> + <v-row + dense> + <v-col md="4"> + <v-text-field + v-model="tableCreate.name" + :rules="[ + v => notEmpty(v) || $t('validation.required'), + v => generatedTableName.length <= 64 || ($t('validation.max-length') + 64), + ]" + required + clearable + :error-messages="!validTableName ? [$t('validation.table.exists')] : []" + persistent-hint + :variant="inputVariant" + :hint="$t('pages.table.subpages.import.name.hint')" + :label="$t('pages.table.subpages.import.name.label')"/> + </v-col> + <v-col md="4"> + <v-text-field + v-model="generatedTableName" + :rules="[ + v => notEmpty(v) || $t('validation.required'), + v => generatedTableName.length <= 64 || ($t('validation.max-length') + 64), + ]" + disabled + clearable + counter="64" + persistent-counter + persistent-hint + :variant="inputVariant" + :hint="$t('pages.table.subpages.import.generated.hint')" + :label="$t('pages.table.subpages.import.generated.label')"/> + </v-col> + </v-row> + <v-row + dense> + <v-col md="8"> + <v-textarea + v-model="tableCreate.description" + rows="2" + :rules="[ + v => (!!v || v.length <= 180) || ($t('validation.max-length') + 180), + ]" + clearable + counter="180" + persistent-counter + persistent-hint + :variant="inputVariant" + :hint="$t('pages.table.subpages.import.description.hint')" + :label="$t('pages.table.subpages.import.description.label')"/> + </v-col> + </v-row> + <v-row + dense> + <v-col + md="4"> + <v-select + v-model="tableCreate.is_public" + name="public" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'table' })" + persistent-hint + :variant="inputVariant" + :items="dataOptions" + item-title="title" + item-value="value" + :rules="[v => v !== null || $t('validation.required')]" + required> + </v-select> + </v-col> + <v-col + md="4"> + <v-select + v-model="tableCreate.is_schema_public" + name="schema-public" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'table', schema: 'columns' })" + persistent-hint + :variant="inputVariant" + :items="schemaOptions" + item-title="title" + item-value="value" + :rules="[v => v !== null || $t('validation.required')]" + required> + </v-select> + </v-col> + </v-row> + </v-container> + </v-form> + </v-stepper-window> + <TableImport + :create="true" + :disabled="!validStep1 || step > 4" + :table="table" + @analyse="onAnalyse"/> + <v-stepper-header> + <v-stepper-item + :title="$t('pages.table.subpages.import.preview.title')" + :complete="validStep4" + :value="4"/> + </v-stepper-header> + <v-stepper-window + direction="vertical"> + <v-container + v-if="step >= 4"> + <TableSchema + ref="schema" + :back="false" + :disabled="step > 4" + :loading="loading" + :submit-text="$t('navigation.continue')" + :columns="tableCreate.columns" + @close="createEmptyTableAndImport"/> + </v-container> + </v-stepper-window> + <v-stepper-header> + <v-stepper-item + :title="$t('pages.table.subpages.import.summary.title')" + :value="5"/> + </v-stepper-header> + <v-stepper-window + v-if="step >= 5" + direction="vertical"> <v-container> - <v-row - dense> - <v-col md="4"> - <v-text-field - v-model="tableCreate.name" - :rules="[ - v => notEmpty(v) || $t('validation.required'), - v => generatedTableName.length <= 64 || ($t('validation.max-length') + 64), - ]" - required - clearable - :error-messages="!validTableName ? [$t('validation.table.exists')] : []" - persistent-hint - :variant="inputVariant" - :hint="$t('pages.table.subpages.import.name.hint')" - :label="$t('pages.table.subpages.import.name.label')"/> - </v-col> - <v-col md="4"> - <v-text-field - v-model="generatedTableName" - :rules="[ - v => notEmpty(v) || $t('validation.required'), - v => generatedTableName.length <= 64 || ($t('validation.max-length') + 64), - ]" - disabled - clearable - counter="64" - persistent-counter - persistent-hint - :variant="inputVariant" - :hint="$t('pages.table.subpages.import.generated.hint')" - :label="$t('pages.table.subpages.import.generated.label')"/> - </v-col> - </v-row> - <v-row - dense> - <v-col md="8"> - <v-textarea - v-model="tableCreate.description" - rows="2" - :rules="[ - v => (!!v || v.length <= 180) || ($t('validation.max-length') + 180), - ]" - clearable - counter="180" - persistent-counter - persistent-hint - :variant="inputVariant" - :hint="$t('pages.table.subpages.import.description.hint')" - :label="$t('pages.table.subpages.import.description.label')"/> - </v-col> - </v-row> - <v-row - dense> + <v-row dense> <v-col - md="4"> - <v-select - v-model="tableCreate.is_public" - name="public" - :label="$t('pages.database.subpages.create.data.label')" - :hint="$t('pages.database.subpages.create.data.hint')" - persistent-hint - :variant="inputVariant" - :items="visibilityOptions" - item-title="name" - item-value="value" - :rules="[v => v !== null || $t('validation.required')]" - required> - </v-select> + md="8"> + <v-alert + border="start" + color="success"> + {{ $t('pages.table.subpages.create.summary.text') }} + <strong> + {{ table.internal_name }} + </strong> + </v-alert> </v-col> - <v-col - md="4"> - <v-select - v-model="tableCreate.is_schema_public" - name="schema-public" - :label="$t('pages.database.subpages.create.schema.label')" - :hint="$t('pages.database.subpages.create.schema.hint')" - persistent-hint - :variant="inputVariant" - :items="visibilityOptions" - item-title="name" - item-value="value" - :rules="[v => v !== null || $t('validation.required')]" - required> - </v-select> + </v-row> + <v-row> + <v-col> + <v-btn + class="mb-1 mr-2" + color="tertiary" + size="small" + variant="flat" + :loading="loadingImport" + :text="$t('navigation.import')" + @click="onImport"/> + <v-btn + class="mb-1" + color="secondary" + size="small" + variant="flat" + :loading="loadingContinue" + :text="$t('navigation.view')" + @click="onContinue"/> </v-col> </v-row> </v-container> - </v-form> - </v-stepper-window> - <TableImport - :create="true" - :disabled="!validStep1 || step > 4" - :table="table" - @analyse="onAnalyse"/> - <v-stepper-header> - <v-stepper-item - :title="$t('pages.table.subpages.import.preview.title')" - :complete="validStep4" - :value="4"/> - </v-stepper-header> - <v-stepper-window - direction="vertical"> - <v-container - v-if="step >= 4"> - <TableSchema - ref="schema" - :back="false" - :disabled="step > 4" - :loading="loading" - :submit-text="$t('navigation.continue')" - :columns="tableCreate.columns" - @close="createEmptyTableAndImport"/> - </v-container> - </v-stepper-window> - <v-stepper-header> - <v-stepper-item - :title="$t('pages.table.subpages.import.summary.title')" - :value="5"/> - </v-stepper-header> - <v-stepper-window - v-if="step >= 5" - direction="vertical"> - <v-container> - <v-row dense> - <v-col - md="8"> - <v-alert - border="start" - color="success"> - {{ $t('pages.table.subpages.create.summary.text') }} - <strong> - {{ table.internal_name }} - </strong> - </v-alert> - </v-col> - </v-row> - <v-row> - <v-col> - <v-btn - class="mb-1 mr-2" - color="tertiary" - size="small" - variant="flat" - :loading="loadingImport" - :text="$t('navigation.import')" - @click="onImport"/> - <v-btn - class="mb-1" - color="secondary" - size="small" - variant="flat" - :loading="loadingContinue" - :text="$t('navigation.view')" - @click="onContinue"/> - </v-col> - </v-row> - </v-container> - </v-stepper-window> - </v-stepper> - </v-card-text> - </v-card> + </v-stepper-window> + </v-stepper> + </v-card-text> + </v-card> + </v-form> <v-breadcrumbs :items="items" class="pa-0 mt-2"/> </div> </template> <script> import TableSchema from '@/components/table/TableSchema.vue' -import {notEmpty} from '@/utils' -import {useUserStore} from '@/stores/user' -import {useCacheStore} from '@/stores/cache' +import { notEmpty } from '@/utils' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' export default { components: { @@ -226,6 +232,7 @@ export default { data() { return { step: 1, + valid: false, validStep1: false, validStep2: false, validStep3: false, @@ -235,15 +242,13 @@ export default { loadingImport: false, fileModel: null, rowCount: null, - visibilityOptions: [ - { - name: this.$t('toolbars.database.public'), - value: true - }, - { - name: this.$t('toolbars.database.private'), - value: false - } + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, ], file: { filename: null, @@ -376,7 +381,7 @@ export default { .then((table) => { this.table = table const toast = useToastInstance() - toast.success(this.$t('success.table.created')) + toast.success(this.$t('success.table.created', { table: table.internal_name })) this.step = 5 }) .catch(({code, message}) => { diff --git a/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue index 458294d1c710c35b6ed2e6e8638ce8710996d890..5f433013bf30d4a450efba6228eb9f693673514f 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue @@ -1,5 +1,6 @@ <template> - <div v-if="canCreateTable"> + <div + v-if="canCreateTable"> <v-toolbar flat> <v-btn @@ -81,6 +82,41 @@ :label="$t('pages.table.subpages.import.description.label')" /> </v-col> </v-row> + <v-row + dense> + <v-col + md="4"> + <v-select + v-model="tableCreate.is_public" + name="public" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'table' })" + persistent-hint + :variant="inputVariant" + :items="dataOptions" + item-title="title" + item-value="value" + :rules="[v => v !== null || $t('validation.required')]" + required> + </v-select> + </v-col> + <v-col + md="4"> + <v-select + v-model="tableCreate.is_schema_public" + name="schema-public" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'table', schema: 'columns' })" + persistent-hint + :variant="inputVariant" + :items="schemaOptions" + item-title="title" + item-value="value" + :rules="[v => v !== null || $t('validation.required')]" + required> + </v-select> + </v-col> + </v-row> </v-container> </v-form> </v-stepper-window> @@ -171,10 +207,20 @@ export default { step: 1, table: null, error: false, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, + ], tableCreate: { name: null, description: null, columns: [], + is_public: true, + is_schema_public: true, constraints: { uniques: [], foreign_keys: [], @@ -253,6 +299,11 @@ export default { } }, mounted () { + if (!this.database) { + return + } + this.tableCreate.is_public = this.database.is_public + this.tableCreate.is_schema_public = this.database.is_schema_public }, methods: { notEmpty, @@ -273,6 +324,9 @@ export default { .catch(({code, message}) => { this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(`${code}: ${message}`)) }) .finally(() => { diff --git a/dbrepo-ui/pages/database/[database_id]/table/index.vue b/dbrepo-ui/pages/database/[database_id]/table/index.vue index 7198c88cf31ab8203f711cd8e7982805524ecff9..2f1cf87ec800162f2be19e05916cc99224f26c4a 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/index.vue @@ -1,15 +1,21 @@ <template> - <div> + <div + v-if="canViewSchema"> <DatabaseToolbar /> - <v-window v-model="tab"> + <v-window + v-model="tab"> <TableList /> </v-window> - <v-breadcrumbs :items="items" class="pa-0 mt-2" /> + <v-breadcrumbs + :items="items" + class="pa-0 mt-2" /> </div> </template> + <script> import TableList from '@/components/table/TableList.vue' import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' +import { useCacheStore } from '@/stores/cache' export default { name: 'Tables', @@ -19,7 +25,7 @@ export default { }, data () { return { - db: null, + tab: 0, items: [ { title: this.$t('navigation.databases'), @@ -34,12 +40,19 @@ export default { to: `/database/${this.$route.params.database_id}/table`, disabled: true } - ] + ], + cacheStore: useCacheStore() } }, computed: { - tab () { - return 1 + database () { + return this.cacheStore.getDatabase + }, + canViewSchema () { + if (this.error) { + return false + } + return this.database } } } diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue index 9751fce5b7843b27043ea9e103003a01a3dcfbb4..f4c81f43f0bdd08a1984e5cd23c8af8c1bb003e4 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue @@ -2,20 +2,20 @@ <div v-if="canReadData"> <ViewToolbar - v-if="cachedView" /> + v-if="view" /> <v-toolbar color="secondary" :title="$t('toolbars.database.current')" flat> <v-btn - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-download' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-download' : null" variant="flat" :loading="downloadLoading" :text="$t('toolbars.table.data.download')" class="mr-2" @click.stop="download" /> <v-btn - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-refresh' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-refresh' : null" variant="flat" :text="$t('toolbars.table.data.refresh')" class="mr-2" @@ -37,6 +37,7 @@ <script> import TimeDrift from '@/components/TimeDrift.vue' import QueryResults from '@/components/subset/Results.vue' +import { useUserStore } from '@/stores/user' export default { components: { @@ -80,11 +81,8 @@ export default { database () { return this.cacheStore.getDatabase }, - cachedView () { - if (!this.database) { - return null - } - return this.database.views.filter(v => v.id === Number(this.$route.params.view_id))[0] + view () { + return this.cacheStore.getView }, access () { return this.userStore.getAccess @@ -96,10 +94,10 @@ export default { return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' }, canReadData () { - if (!this.cachedView) { + if (!this.view) { return false } - if (this.cachedView.is_public) { + if (this.view.is_public) { return true } if (!this.user) { @@ -135,6 +133,9 @@ export default { .catch(({code}) => { this.downloadLoading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { 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 364516f45f29209c56748add8bff0da310de7d75..43bfb2b39028857833ba0c15ce09a125141a28f3 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 @@ -1,10 +1,11 @@ <template> - <div> + <div + v-if="canViewView"> <ViewToolbar /> <v-window v-model="tab"> <v-window-item - v-if="cachedView"> + v-if="view"> <v-card variant="flat"> <Summary v-if="hasIdentifier" @@ -23,15 +24,15 @@ variant="flat"> <v-card-text> <v-list - v-if="cachedView" + v-if="view" dense> <v-list-item :title="$t('pages.view.name.title')"> - {{ cachedView.internal_name }} + {{ view.internal_name }} </v-list-item> <v-list-item :title="$t('pages.view.query.title')"> - <pre>{{ cachedView.query }}</pre> + <pre>{{ view.query }}</pre> </v-list-item> <v-list-item :title="$t('pages.view.owner.title')"> @@ -45,34 +46,9 @@ width="200" /> </v-list-item> <v-list-item - v-if="cachedView.created" + v-if="view.created" :title="$t('pages.view.creation.title')"> - {{ formatUTC(cachedView.created) }} - </v-list-item> - <v-list-item - :title="$t('pages.view.visibility.title')"> - {{ viewVisibility }} - </v-list-item> - </v-list> - </v-card-text> - </v-card> - <v-divider /> - <v-card - :title="$t('pages.database.title')" - variant="flat"> - <v-card-text> - <v-list dense> - <v-list-item - :title="$t('pages.database.visibility.title')"> - {{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }} - </v-list-item> - <v-list-item - :title="$t('pages.database.name.title')"> - <NuxtLink - class="text-primary" - :to="`/database/${database.id}`"> - {{ database.internal_name }} - </NuxtLink> + {{ formatUTC(view.created) }} </v-list-item> </v-list> </v-card-text> @@ -83,16 +59,6 @@ </div> </template> -<script setup> -const config = useRuntimeConfig() -const { database_id, view_id } = useRoute().params -const { data } = await useFetch(`${config.public.api.server}/api/database/${database_id}/view/${view_id}`) -if (data.value) { - const identifierService = useIdentifierService() - useServerHead(identifierService.viewToServerHead(data.value)) - useServerSeoMeta(identifierService.viewToServerSeoMeta(data.value)) -} -</script> <script> import ViewToolbar from '@/components/view/ViewToolbar.vue' import Summary from '@/components/identifier/Summary.vue' @@ -113,7 +79,6 @@ export default { return { tab: 0, loadingView: false, - view: null, items: [ { title: this.$t('navigation.databases'), @@ -152,15 +117,18 @@ export default { database () { return this.cacheStore.getDatabase }, - cachedView () { - if (!this.database) { - return null - } - return this.database.views.filter(v => v.id === Number(this.$route.params.view_id))[0] - }, access () { return this.userStore.getAccess }, + view () { + return this.cacheStore.getView + }, + hasReadAccess () { + if (!this.access) { + return false + } + return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' + }, identifiers () { if (!this.view) { return [] @@ -174,7 +142,7 @@ export default { if (!this.user) { return this.identifiers.filter(i => i.status === 'published') } - return this.identifiers.filter(i => i.status === 'published' || i.creator.id === this.user.id) + return this.identifiers.filter(i => i.status === 'published' || i.owner.id === this.user.id) }, identifier () { if (this.pid) { @@ -204,42 +172,22 @@ export default { const userService = useUserService() return userService.userToFullName(this.view.creator) }, - viewVisibility () { - if (!this.cachedView) { - return null + canViewView () { + if (!this.view) { + return false } - if (this.cachedView.is_public && this.cachedView.is_schema_public) { - return this.$t('pages.database.visibility.open') + if (this.view.is_public) { + return true } - if (!this.cachedView.is_public && !this.cachedView.is_schema_public) { - return this.$t('pages.database.visibility.closed') + if (!this.user) { + return false } - return this.cachedView.is_public ? this.$t('pages.database.visibility.data') : this.$t('pages.database.visibility.schema') + return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id } }, - mounted () { - this.fetchView() - }, methods: { formatUTC (timestamp) { return formatTimestampUTCLabel(timestamp) - }, - fetchView () { - this.loadingView = true - const viewService = useViewService() - viewService.findOne(this.$route.params.database_id, this.$route.params.view_id) - .then((view) => { - this.view = view - this.loadingView = false - }) - .catch(({code}) => { - this.loadingView = false - const toast = useToastInstance() - toast.error(this.$t(code)) - }) - .finally(() => { - this.loadingView = false - }) } } } diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue index 772910ec0953281912a615bc397790b96fd113e9..86db06f1963fb3e491a939ca389d913db7da473d 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue @@ -1,14 +1,17 @@ <template> - <div v-if="canCreateIdentifier || canUpdateIdentifier"> - <Persist type="view" :database="database" /> + <div + v-if="canCreateIdentifier || canUpdateIdentifier"> + <Persist + type="view" + :database="database" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' export default { components: { diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue index a0c91a1a4e04802b699c83c1d6b5de9794997efe..f3a3e18f9df142e3f136caf3d022c218676dfb41 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue @@ -1,14 +1,18 @@ <template> - <div v-if="canPersistView"> - <Persist type="view" :database="database" :view="view" /> + <div + v-if="canPersistView"> + <Persist + type="view" + :database="database" + :view="view" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' export default { components: { @@ -71,5 +75,3 @@ export default { } } </script> -<style> -</style> diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue index b3352010b26653c7b3cb766734b6eb0a2e64dc44..e126e19d9050c23b4299f9799b2895490813f33f 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue @@ -63,7 +63,6 @@ export default { data () { return { loading: false, - view: null, items: [ { title: this.$t('navigation.databases'), @@ -89,7 +88,7 @@ export default { ], headers: [ { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') }, - { value: 'column_type', title: this.$t('pages.table.subpages.schema.column-type.title') }, + { value: 'type', title: this.$t('pages.table.subpages.schema.column-type.title') }, { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') }, { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, @@ -100,9 +99,6 @@ export default { cacheStore: useCacheStore() } }, - mounted () { - this.fetchView() - }, computed: { user () { return this.userStore.getUser @@ -110,6 +106,9 @@ export default { database () { return this.cacheStore.getDatabase }, + view () { + return this.cacheStore.getView + }, access () { return this.userStore.getAccess }, @@ -119,23 +118,17 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, - cachedView () { - if (!this.database) { - return null - } - return this.database.views.filter(v => v.id === Number(this.$route.params.view_id))[0] - }, canViewSchema () { - if (!this.cachedView) { + if (!this.view) { return false } - if (this.cachedView.is_schema_public) { + if (this.view.is_schema_public) { return true } if (!this.user) { return false } - return this.hasReadAccess || this.cachedView.owned_by === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id }, roles () { return this.userStore.getRoles @@ -151,9 +144,9 @@ export default { }, methods: { extra (column) { - if (column.column_type === 'float') { + if (column.type === 'float') { return `precision=${column.size}` - } else if (['decimal', 'double'].includes(column.column_type)) { + } else if (['decimal', 'double'].includes(column.type)) { let extra = '' if (column.size !== null) { extra += `size=${column.size}` @@ -165,11 +158,11 @@ export default { extra += `d=${column.d}` } return extra - } else if (column.column_type === 'enum') { + } else if (column.type === 'enum') { return `(${column.enums.join(', ')})` - } else if (column.column_type === 'set') { + } else if (column.type === 'set') { return `(${column.sets.join(', ')})` - } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.column_type)) { + } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.type)) { return column.size !== null ? `size=${column.size}` : '' } return null @@ -179,23 +172,6 @@ export default { }, hasConcept (item) { return item.concept && 'uri' in item.concept - }, - fetchView () { - this.loading = true - const viewService = useViewService() - viewService.findOne(this.$route.params.database_id, this.$route.params.view_id) - .then((view) => { - this.view = view - this.loading = false - }) - .catch(({code}) => { - this.loading = false - const toast = useToastInstance() - toast.error(this.$t(code)) - }) - .finally(() => { - this.loading = false - }) } } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..27444c9e89aec8cb2f9fb915504f3f9a4aaa97f1 --- /dev/null +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue @@ -0,0 +1,311 @@ +<template> + <div + v-if="canViewSettings"> + <ViewToolbar /> + <v-form + v-if="canUpdateVisibility" + ref="form" + v-model="valid" + autocomplete="off" + @submit.prevent="submit"> + <v-card + variant="flat" + rounded="0" + :title="$t('pages.view.settings.title')" + :subtitle="$t('pages.view.settings.subtitle')"> + <v-card-text> + <v-row + dense> + <v-col + md="4"> + <v-select + v-model="modify.is_public" + :items="dataOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'view' })" /> + </v-col> + <v-col + md="4"> + <v-select + v-model="modify.is_schema_public" + :items="schemaOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'view', schema: 'query' })" /> + </v-col> + </v-row> + <v-row> + <v-col> + <v-btn + variant="flat" + size="small" + :disabled="!valid || !isChange" + :color="buttonColor" + :loading="loading" + type="submit" + :text="$t('navigation.modify')" + @click="update" /> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-form> + <v-divider + v-if="canDeleteView" /> + <v-card + v-if="canDeleteView" + variant="flat" + rounded="0" + :title="$t('pages.view.delete.title')" + :subtitle="$t('pages.view.delete.subtitle', { view: view.internal_name })"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-btn + size="small" + variant="flat" + color="error" + @click="askDelete"> + {{ $t('navigation.delete')}} + </v-btn> + </v-col> + </v-row> + </v-card-text> + </v-card> + <v-breadcrumbs + :items="items" + class="pa-0 mt-2" /> + </div> +</template> + +<script> +import ViewToolbar from '@/components/view/ViewToolbar.vue' +import { useUserStore } from '@/stores/user' +import { useCacheStore } from '@/stores/cache' + +export default { + components: { + ViewToolbar + }, + data () { + return { + valid: false, + loading: false, + modify: { + is_public: null, + is_schema_public: null + }, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, + ], + items: [ + { + title: this.$t('navigation.databases'), + to: '/database' + }, + { + title: `${this.$route.params.database_id}`, + to: `/database/${this.$route.params.database_id}/info` + }, + { + title: this.$t('navigation.views'), + to: `/database/${this.$route.params.database_id}/view` + }, + { + title: `${this.$route.params.view_id}`, + to: `/database/${this.$route.params.database_id}/view/${this.$route.params.view_id}` + }, + { + title: this.$t('navigation.settings'), + to: `/database/${this.$route.params.database_id}/view/${this.$route.params.view_id}/settings`, + disabled: true + } + ], + headers: [ + { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') }, + { value: 'type', title: this.$t('pages.table.subpages.schema.column-type.title') }, + { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') }, + { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, + { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, + { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') }, + { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, + ], + dateColumns: [], + userStore: useUserStore(), + cacheStore: useCacheStore() + } + }, + computed: { + user () { + return this.userStore.getUser + }, + database () { + return this.cacheStore.getDatabase + }, + view () { + return this.cacheStore.getView + }, + access () { + return this.userStore.getAccess + }, + hasReadAccess () { + if (!this.access) { + return false + } + return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' + }, + roles () { + return this.userStore.getRoles + }, + isChange () { + if (!this.view) { + return false + } + if (this.view.is_public !== this.modify.is_public) { + return true + } + return this.view.is_schema_public !== this.modify.is_schema_public + }, + canUpdateVisibility () { + if (!this.roles || !this.user || !this.view) { + return false + } + return this.roles.includes('modify-view-visibility') && this.view.owner.id === this.user.id + }, + canDeleteView () { + if (!this.roles || !this.user || !this.view) { + return false + } + return this.roles.includes('delete-database-view') && this.view.owner.id === this.user.id + }, + canViewSettings () { + if (!this.user || !this.view) { + return false + } + return this.view.owner.id === this.user.id + }, + inputVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal + }, + buttonVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal + }, + buttonColor () { + return !this.isChange ? null : 'warning' + } + }, + mounted() { + if (!this.view) { + return + } + this.modify.is_public = this.view.is_public + this.modify.is_schema_public = this.view.is_schema_public + this.modify.description = this.view.description + }, + methods: { + submit () { + this.$refs.form.validate() + }, + extra (column) { + if (column.type === 'float') { + return `precision=${column.size}` + } else if (['decimal', 'double'].includes(column.type)) { + let extra = '' + if (column.size !== null) { + extra += `size=${column.size}` + } + if (column.d !== null) { + if (extra.length > 0) { + extra += ', ' + } + extra += `d=${column.d}` + } + return extra + } else if (column.type === 'enum') { + return `(${column.enums.join(', ')})` + } else if (column.type === 'set') { + return `(${column.sets.join(', ')})` + } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.type)) { + return column.size !== null ? `size=${column.size}` : '' + } + return null + }, + closed (event) { + const { success } = event + console.debug('closed dialog', event) + if (success) { + const toast = useToastInstance() + toast.success(this.$t('success.table.semantics')) + this.cacheStore.reloadTable() + } + this.dialogSemantic = false + }, + askDelete () { + if (!confirm(this.$t('pages.view.delete.subtitle', { view: this.view.internal_name }))) { + return + } + this.loadingDelete = true + const viewService = useViewService() + viewService.remove(this.database.id, this.view.id) + .then(() => { + console.info('Deleted view with id ', this.view.id) + this.cacheStore.reloadDatabase() + const toast = useToastInstance() + toast.success('Successfully deleted view with id ' + this.view.id) + this.$router.push(`/database/${this.$route.params.database_id}/view`) + }) + .catch(({code, message}) => { + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) + }) + .finally(() => { + this.loadingDelete = false + }) + }, + update () { + this.loading = true + const viewService = useViewService() + viewService.update(this.$route.params.database_id, this.$route.params.view_id, this.modify) + .then(() => { + this.loading = false + const toast = useToastInstance() + toast.success(this.$t('success.view.modified')) + this.cacheStore.reloadView() + }) + .catch(({code, message}) => { + this.loading = false + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(message) + }) + .finally(() => { + this.loading = false + }) + } + } +} +</script> diff --git a/dbrepo-ui/pages/database/[database_id]/view/create.vue b/dbrepo-ui/pages/database/[database_id]/view/create.vue index 839b79e243d4ceb7903e8a81ee9da0306d29697a..060d186252e1192b3264af89b92b85293ad14d09 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/create.vue @@ -1,5 +1,6 @@ <template> - <div v-if="canCreateView"> + <div + v-if="canCreateView"> <Builder mode="view" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> @@ -7,6 +8,7 @@ <script> import Builder from '@/components/subset/Builder.vue' +import { useUserStore } from '@/stores/user' export default { components: { diff --git a/dbrepo-ui/pages/database/[database_id]/view/index.vue b/dbrepo-ui/pages/database/[database_id]/view/index.vue index dc87510ae887285ac36fc647e8f2a172cb708784..4172797328151393813f683200652c2753e783ed 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/index.vue @@ -1,16 +1,21 @@ <template> - <div> + <div + v-if="canViewSchema"> <DatabaseToolbar /> - <v-window v-model="tab"> + <v-window + v-model="tab"> <ViewList /> </v-window> - <v-breadcrumbs :items="items" class="pa-0 mt-2" /> + <v-breadcrumbs + :items="items" + class="pa-0 mt-2" /> </div> </template> <script> import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import ViewList from '@/components/view/ViewList.vue' +import { useCacheStore } from '@/stores/cache' export default { name: 'Views', @@ -20,7 +25,7 @@ export default { }, data () { return { - db: null, + tab: 0, items: [ { title: this.$t('navigation.databases'), @@ -35,20 +40,20 @@ export default { to: `/database/${this.$route.params.database_id}/view`, disabled: true } - ] + ], + cacheStore: useCacheStore() } }, computed: { - tab () { - return 1 + database () { + return this.cacheStore.getDatabase + }, + canViewSchema () { + if (this.error) { + return false + } + return this.database } - }, - mounted () { - }, - methods: { } } </script> - -<style scoped> -</style> diff --git a/dbrepo-ui/pages/index.vue b/dbrepo-ui/pages/index.vue index 037f5b9410f316cce4e24ec2a9d45c6d6615a741..6e71854c0dc72ce8f68f75772befc72fcbbf3279 100644 --- a/dbrepo-ui/pages/index.vue +++ b/dbrepo-ui/pages/index.vue @@ -7,7 +7,7 @@ <v-spacer /> <v-btn v-if="canCreateDatabase" - class="mr-4" + class="mr-2" prepend-icon="mdi-plus" variant="flat" :text="$t('toolbars.database.create.text')" diff --git a/dbrepo-ui/pages/login.vue b/dbrepo-ui/pages/login.vue index 8a35efe59da3aa75da3ec5f23e4800fe92ea99ef..e1b255ed8bc51e2963bb7fb2065d444ef243b8cf 100644 --- a/dbrepo-ui/pages/login.vue +++ b/dbrepo-ui/pages/login.vue @@ -117,7 +117,7 @@ export default { userService.findOne(userId) .then((user) => { const toast = useToastInstance() - toast.success(this.$t('success.user.login')) + toast.success(this.$t('success.user.login', { username : user.username })) switch (user.attributes.theme) { case 'dark': this.$vuetify.theme.global.name = 'tuwThemeDark' @@ -137,12 +137,18 @@ export default { }) .catch(({code}) => { const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) }) .catch(({code}) => { this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { diff --git a/dbrepo-ui/pages/search.vue b/dbrepo-ui/pages/search.vue index ebe16ecec1c159de639a6c735b8f806dda1da21f..b23c896448e12845d0d4b3f92ce0284b5886bd55 100644 --- a/dbrepo-ui/pages/search.vue +++ b/dbrepo-ui/pages/search.vue @@ -8,7 +8,7 @@ <v-spacer /> <v-btn v-if="canCreateDatabase" - class="mr-4" + class="mr-2" prepend-icon="mdi-plus" color="secondary" variant="flat" @@ -27,7 +27,8 @@ v-if="isDatabaseSearch" :loading="loading" :databases="results" /> - <div> + <div + v-else> <v-card v-for="(result, idx) in results" :key="idx" @@ -38,10 +39,13 @@ <v-divider class="mx-4" /> <v-card-title class="text-primary text-decoration-underline"> - <a v-if="link(result)" :href="link(result)"> + <a + v-if="link(result)" + :href="link(result)"> {{ title(result) }} </a> - <span v-else> + <span + v-else> {{ title(result) }} </span> </v-card-title> @@ -52,6 +56,8 @@ <div v-if="tags(result).length > 0" class="mt-2 db-tags"> + <ResourceStatus + :resource="result" /> <v-chip v-for="(tag, i) in tags(result)" :key="i" @@ -64,23 +70,15 @@ </v-card-text> </v-card> </div> - <v-dialog - v-model="createDbDialog" - persistent - max-width="640"> - <DatabaseCreate @close="closed" /> - </v-dialog> </div> </template> <script> -import DatabaseCreate from '@/components/database/DatabaseCreate.vue' import AdvancedSearch from '@/components/search/AdvancedSearch.vue' import { useUserStore } from '@/stores/user' export default { components: { - DatabaseCreate, AdvancedSearch }, data () { @@ -88,7 +86,6 @@ export default { results: [], type: 'database', loading: false, - createDbDialog: null, userStore: useUserStore() } }, @@ -134,10 +131,13 @@ export default { if (!queryKeys || queryKeys.length !== 1 || !queryKeys.includes('q')) { return } + if (!this.q) { + return + } this.loading = true const searchService = useSearchService() searchService.fuzzy_search(this.q) - .then(({results}) => { + .then((results) => { this.results = results this.loading = false }) @@ -196,12 +196,6 @@ export default { } return this.type === 'identifier' }, - isPublic (item) { - if (this.isDatabase(item) || this.isTable(item) || this.isColumn(item) || this.isView(item) || this.isIdentifier(item)) { - return item.is_public - } - return null - }, title (item) { if (this.isDatabase(item) || this.isTable(item) || this.isColumn(item) || this.isView(item)) { return item.name @@ -215,7 +209,7 @@ export default { } return title } else if (this.isUser(item)) { - return item.creator.qualified_name + return item.owner.qualified_name } return null }, @@ -230,7 +224,7 @@ export default { } return description } else if (this.isColumn(item)) { - let text = item.column_type + let text = item.type if (item.size) { text += `(${item.size}${item.d ? ',' + item.d : ''})` } @@ -260,10 +254,6 @@ export default { }, tags (item) { const tags = [] - if (this.isPublic(item) === true || this.isPublic(item) === false) { - const text = this.isPublic(item) ? this.$t('toolbars.database.public') : this.$t('toolbars.database.private') - tags.push({ color: this.isPublic(item) ? 'success' : null, text }) - } if (this.isDatabase(item)) { } else if (this.isTable(item)) { } else if (this.isColumn(item)) { @@ -296,25 +286,14 @@ export default { } else if (this.isUnit(item)) { } else if (this.isConcept(item)) { } else if (this.isUser(item)) { - if (item.creator.attributes.orcid) { + if (item.owner.attributes.orcid) { tags.push({ text: 'ORCID', color: 'success' }) } } return tags }, - closed (event) { - this.dialog = false - if (event.success) { - this.$router.push(`/database/${event.database_id}/info`) - } - }, - onSearchResult ({results, type}) { + onSearchResult (results) { this.results = results - if (!type) { - return - } - console.debug('search for type', type, ':', results) - this.type = type }, capitalizeFirstLetter(string) { if (!string) { diff --git a/dbrepo-ui/pages/signup.vue b/dbrepo-ui/pages/signup.vue index 2548a6dfa9b749853ca24b6784235fc14fcb1b78..54c00602256c7815d8aff0b255214e66836bc727 100644 --- a/dbrepo-ui/pages/signup.vue +++ b/dbrepo-ui/pages/signup.vue @@ -130,6 +130,9 @@ export default { .catch(({code}) => { this.loading = false const toast = useToastInstance() + if (typeof code !== 'string') { + return + } toast.error(this.$t(code)) }) .finally(() => { diff --git a/dbrepo-ui/pages/user/info.vue b/dbrepo-ui/pages/user/info.vue index 3501818ca0408474e81a9038f15a84d61fb662ff..d2d1b2c8fe44aba72c45beabacff9ca5fc140c2e 100644 --- a/dbrepo-ui/pages/user/info.vue +++ b/dbrepo-ui/pages/user/info.vue @@ -14,11 +14,9 @@ <v-col md="6"> <v-text-field v-model="model.id" - readonly + disabled :variant="inputVariant" - :label="$t('pages.user.subpages.info.id.label')" - append-inner-icon="mdi-content-copy" - @click:append-inner="copy" /> + :label="$t('pages.user.subpages.info.id.label')" /> </v-col> </v-row> <v-row dense> @@ -284,11 +282,6 @@ export default { .finally(() => { this.orcidLoading = false }) - }, - copy () { - navigator.clipboard.writeText(this.model.id) - const toast = useToastInstance() - toast.success(this.$t('success.clipboard.user')) } } } diff --git a/dbrepo-ui/stores/cache.js b/dbrepo-ui/stores/cache.js index 5004b1beb0170862f5062627656fcf6e8844dd7a..3574b24d7c6300b884f7874726254e3c805393b3 100644 --- a/dbrepo-ui/stores/cache.js +++ b/dbrepo-ui/stores/cache.js @@ -6,6 +6,8 @@ export const useCacheStore = defineStore('cache', { return { database: null, table: null, + view: null, + subset: null, ontologies: [], messages: [], uploadProgress: null @@ -14,24 +16,32 @@ export const useCacheStore = defineStore('cache', { getters: { getDatabase: (state) => state.database, getTable: (state) => state.table, + getView: (state) => state.view, + getSubset: (state) => state.subset, getOntologies: (state) => state.ontologies, getMessages: (state) => state.messages, getUploadProgress: (state) => state.uploadProgress, }, actions: { - setDatabase (database) { + setDatabase(database) { this.database = database }, - setTable (table) { + setTable(table) { this.table = table }, - setOntologies (ontologies) { + setView(view) { + this.view = view + }, + setSubset(subset) { + this.subset = subset + }, + setOntologies(ontologies) { this.ontologies = ontologies }, - setUploadProgress (uploadProgress) { + setUploadProgress(uploadProgress) { this.uploadProgress = uploadProgress }, - reloadMessages () { + reloadMessages() { const messageService = useMessageService() messageService.findAll('active') .then(messages => this.messages = messages) @@ -39,7 +49,7 @@ export const useCacheStore = defineStore('cache', { console.error('Failed to reload messages', error) }) }, - reloadOntologies () { + reloadOntologies() { const ontologyService = useOntologyService() ontologyService.findAll() .then(ontologies => this.ontologies = ontologies) @@ -47,7 +57,7 @@ export const useCacheStore = defineStore('cache', { console.error('Failed to reload ontologies', error) }) }, - reloadDatabase () { + reloadDatabase() { const databaseService = useDatabaseService() databaseService.findOne(this.database.id) .then(database => this.database = database) @@ -55,7 +65,7 @@ export const useCacheStore = defineStore('cache', { console.error('Failed to reload database', error) }) }, - reloadTable () { + reloadTable() { const tableService = useTableService() tableService.findOne(this.table.database_id, this.table.id) .then(table => this.table = table) @@ -63,19 +73,33 @@ export const useCacheStore = defineStore('cache', { console.error('Failed to reload table', error) }) }, - setRouteDatabase (databaseId) { - if (!databaseId) { - this.database = null - return - } - const databaseService = useDatabaseService() - databaseService.findOne(databaseId) - .then(database => this.database = database) + reloadView() { + const viewService = useViewService() + viewService.findOne(this.table.database_id, this.view.id) + .then(view => this.view = view) .catch((error) => { - console.error('Failed to set route database', error) + console.error('Failed to reload view', error) }) }, - setRouteTable (databaseId, tableId) { + setRouteDatabase (databaseId) { + return new Promise((resolve, reject) => { + if (!databaseId) { + this.database = null + reject() + } + const databaseService = useDatabaseService() + databaseService.findOne(databaseId, true) + .then((database) => { + this.database = database + resolve(database) + }) + .catch((error) => { + this.database = null + reject(error) + }) + }) + }, + setRouteTable(databaseId, tableId) { if (!databaseId || !tableId) { this.table = null console.error('Cannot set route table: missing database id', databaseId, 'or table id', tableId) @@ -84,9 +108,26 @@ export const useCacheStore = defineStore('cache', { const tableService = useTableService() tableService.findOne(databaseId, tableId) .then(table => this.table = table) - .catch((error) => { - console.error('Failed to set route table', error) - }) + }, + setRouteView(databaseId, viewId) { + if (!databaseId || !viewId) { + this.view = null + console.error('Cannot set route view: database view id', databaseId, 'or view id', viewId) + return + } + const viewService = useViewService() + viewService.findOne(databaseId, viewId) + .then(view => this.view = view) + }, + setRouteSubset(databaseId, subsetId) { + if (!databaseId || !subsetId) { + this.subset = null + console.error('Cannot set route subset: missing database id', databaseId, 'or subset id', subsetId) + return + } + const subsetService = useQueryService() + subsetService.findOne(databaseId, subsetId) + .then(subset => this.subset = subset) } }, }) diff --git a/dbrepo-ui/utils/index.ts b/dbrepo-ui/utils/index.ts index 4f30d8953405445c152dee0b6afd4dc6b44cba3a..5876f4ec2d456d5d4d96d52ecb054e8e51d9ed9b 100644 --- a/dbrepo-ui/utils/index.ts +++ b/dbrepo-ui/utils/index.ts @@ -1,6 +1,7 @@ -import { format } from 'date-fns' import moment from 'moment' -import type {AxiosError} from 'axios' +import {AxiosError, type AxiosResponse, type InternalAxiosRequestConfig} from 'axios' +import { format } from 'date-fns' +import { getStatusText } from 'http-status-codes' export function notEmpty(str: string) { @@ -10,6 +11,13 @@ export function notEmpty(str: string) { return str.trim().length > 0 } +export function max(str: string, len: number) { + if (str === null) { + return false + } + return str.trim().length <= len +} + export function notFile(files: [File[]]) { if (!files) { return false @@ -17,6 +25,43 @@ export function notFile(files: [File[]]) { return files.length === 1 } +export function makeError(status: number, code: string | null, message: string | null ): AxiosError { + const config: InternalAxiosRequestConfig = {} + const response: AxiosResponse = { + data: { + status: getStatusText(status).toUpperCase() + }, + status, + statusText: getStatusText(status).toUpperCase(), + config, + headers: {} + } + return new AxiosError(message, code, undefined, null, response) +} + +export function errorCodeKey(error: AxiosError): any { + switch (error?.response?.status) { + case 404: + return { + title: 'error.missing.title', + subtitle: 'ERR_' + error?.response?.data?.status, + text: 'error.missing.text' + } + case 403: + return { + title: 'error.permission.title', + subtitle: 'ERR_' + error?.response?.data?.status, + text: 'error.permission.text' + } + default: + return { + title: 'error.gone.title', + subtitle: 'ERR_' + error?.response?.data?.status, + text: 'error.gone.text' + } + } +} + export function castNumberOptional(str: string): string | number { const num = Number(str) const ss = String(num) @@ -1048,6 +1093,14 @@ export function isActiveMessage(message: any) { } export function axiosErrorToApiError(error: AxiosError): ApiErrorDto { + if (!error || !('data' in error.response)) { + const errorObj: ApiErrorDto = { + status: 'NOT_SET', + code: 'error.axios.connection', + message: '' + } + return errorObj + } if (error.code === 'ECONNABORTED') { /* timeout */ const errorObj: ApiErrorDto = { @@ -1057,15 +1110,7 @@ export function axiosErrorToApiError(error: AxiosError): ApiErrorDto { } return errorObj } - if ('data' in error.response) { - const errorObj: ApiErrorDto = (error.response.data as ApiErrorDto) - return errorObj - } - const errorObj: ApiErrorDto = { - status: error.code ? error.code : 'NOT_SET', - code: 'error.axios.connection', - message: error.message - } + const errorObj: ApiErrorDto = (error.response.data as ApiErrorDto) return errorObj } diff --git a/dbrepo-upload-service/pom.xml b/dbrepo-upload-service/pom.xml index db626827a1e4b98662866815b8a6cf4c87e2d5c8..f2bea092361406c7f933a5c26f8eadb0ecbcb131 100644 --- a/dbrepo-upload-service/pom.xml +++ b/dbrepo-upload-service/pom.xml @@ -11,9 +11,9 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-upload-service</artifactId> <name>dbrepo-upload-service</name> - <version>1.6.0</version> + <version>1.6.1</version> - <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/</url> + <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/</url> <developers> <developer> <name>Martin Weise</name> diff --git a/docker-compose.yml b/docker-compose.yml index 7159ff58cbb59eec4d114603c71c5ea4c52d51b1..315f6bf1884c1e49d2ac870ab53f50d7a6b8c449 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -303,12 +303,14 @@ services: AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} COLLECTION: ${COLLECTION:-['database','table','column','identifier','unit','concept','user','view']} + LOG_LEVEL: ${LOG_LEVEL:-info} 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} - LOG_LEVEL: ${LOG_LEVEL:-info} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: test: curl -sSL localhost:8080/health | grep 'UP' || exit 1 interval: 10s @@ -402,11 +404,14 @@ services: context: ./dbrepo-search-service/init network: host environment: + LOG_LEVEL: ${LOG_LEVEL:-info} 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} + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" depends_on: dbrepo-search-db: condition: service_healthy diff --git a/helm/dbrepo/Chart.lock b/helm/dbrepo/Chart.lock index f452f870386be707d92e9f19498b4c24f004e6c1..0ae700f9d6f0a4674036ae4fb26c4aafc6ee1a5f 100644 --- a/helm/dbrepo/Chart.lock +++ b/helm/dbrepo/Chart.lock @@ -6,25 +6,25 @@ dependencies: repository: https://charts.bitnami.com/bitnami version: 21.6.1 - name: mariadb-galera - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 13.2.7 - name: mariadb-galera - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 13.2.7 - name: rabbitmq - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 14.0.0 - name: seaweedfs repository: file://../seaweedfs version: 4.2.1 - name: grafana - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 11.4.2 - name: prometheus - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 1.3.22 - name: nginx - repository: https://charts.bitnami.com/bitnami + repository: oci://registry-1.docker.io/bitnamicharts version: 18.3.1 -digest: sha256:414c043a3751945d7bd5b02fa00ee0464bee7f08efb469e00a5f059cdbff03b5 -generated: "2025-01-01T15:06:18.720941571+01:00" +digest: sha256:f244730fab10d52050634ce3286413d378b92e4dc97b0ad2951295c0d2971146 +generated: "2025-01-14T16:48:00.637443736+01:00" diff --git a/helm/dbrepo/Chart.yaml b/helm/dbrepo/Chart.yaml index 2145c0461e025784e1664f6b537a15456a37f86d..22d1865df5866213c931df8b2b522af33137c1e6 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.6.0" -appVersion: "1.6.0" +version: "1.6.1" +appVersion: "1.6.1" keywords: - dbrepo maintainers: diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index ead25253597ec98f167ed0ebc892f09c692969a4..8c03ed1801a819673a1af37dcf6de45a3265d55d 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.6.0" +helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" --values ./values.yaml --version "1.6.1" ``` ## Prerequisites @@ -28,7 +28,7 @@ helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" 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.6.0" +helm install my-release "oci://oci://registry.datalab.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.6.1" ``` The command deploys DBRepo on the Kubernetes cluster in the default configuration. The Parameters section lists the diff --git a/helm/dbrepo/charts/mariadb-galera-13.2.7.tgz b/helm/dbrepo/charts/mariadb-galera-13.2.7.tgz index 377afe25d2435c5788c26592b39797aa1378e966..92bfce78d9c52d62ca9d7e4816c51dccece8af2b 100644 Binary files a/helm/dbrepo/charts/mariadb-galera-13.2.7.tgz and b/helm/dbrepo/charts/mariadb-galera-13.2.7.tgz differ diff --git a/helm/dbrepo/charts/prometheus-1.3.22.tgz b/helm/dbrepo/charts/prometheus-1.3.22.tgz index 3d81a5e625af76257c1a7bc032e889005bc66607..5c26eda5dfb6ec24a8e3cf1b22e1b3aee10d838e 100644 Binary files a/helm/dbrepo/charts/prometheus-1.3.22.tgz and b/helm/dbrepo/charts/prometheus-1.3.22.tgz differ diff --git a/helm/dbrepo/charts/rabbitmq-14.0.0.tgz b/helm/dbrepo/charts/rabbitmq-14.0.0.tgz index 39ea3aaef2a94fe507a08242bbfe37209eb9fa53..e858784faeff04c04a34ebad05885197f565c1e0 100644 Binary files a/helm/dbrepo/charts/rabbitmq-14.0.0.tgz and b/helm/dbrepo/charts/rabbitmq-14.0.0.tgz differ diff --git a/helm/dbrepo/charts/seaweedfs-4.2.1.tgz b/helm/dbrepo/charts/seaweedfs-4.2.1.tgz index 480c5468d22ef48a84068eb63029f0b45a4d8873..fece394e7c53ae6f207c913485155b278314ad1c 100644 Binary files a/helm/dbrepo/charts/seaweedfs-4.2.1.tgz and b/helm/dbrepo/charts/seaweedfs-4.2.1.tgz differ diff --git a/helm/dbrepo/files/01-setup-schema.sql b/helm/dbrepo/files/01-setup-schema.sql index 0a43ef604460e8deb4e4fee4f457c0ca833fc6a2..c9ce89d1be71f4791c5e55dbb7c24f46e979355a 100644 --- a/helm/dbrepo/files/01-setup-schema.sql +++ b/helm/dbrepo/files/01-setup-schema.sql @@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS `mdb_users` email character varying(255) NOT NULL, orcid character varying(255), affiliation character varying(255), + is_internal BOOLEAN NOT NULL DEFAULT FALSE, mariadb_password character varying(255) NOT NULL, theme character varying(255) NOT NULL default ('light'), language character varying(3) NOT NULL default ('en'), @@ -95,7 +96,6 @@ CREATE TABLE IF NOT EXISTS `mdb_databases` PRIMARY KEY (id), FOREIGN KEY (cid) REFERENCES mdb_containers (id), FOREIGN KEY (owned_by) REFERENCES mdb_users (id), - FOREIGN KEY (owned_by) REFERENCES mdb_users (id), FOREIGN KEY (contact_person) REFERENCES mdb_users (id) ) WITH SYSTEM VERSIONING; @@ -135,7 +135,6 @@ CREATE TABLE IF NOT EXISTS `mdb_tables` PRIMARY KEY (ID), UNIQUE (tDBID, internal_name), FOREIGN KEY (tDBID) REFERENCES mdb_databases (id), - FOREIGN KEY (owned_by) REFERENCES mdb_users (id), FOREIGN KEY (owned_by) REFERENCES mdb_users (id) ) WITH SYSTEM VERSIONING; diff --git a/helm/dbrepo/templates/search-secret.yaml b/helm/dbrepo/templates/search-secret.yaml index 6bbc747123f6f5aa8d0e669dd991b43baa135a67..08ed410c06442ae4fce27295d129b578f772795a 100644 --- a/helm/dbrepo/templates/search-secret.yaml +++ b/helm/dbrepo/templates/search-secret.yaml @@ -24,4 +24,6 @@ stringData: OPENSEARCH_PORT: "{{ .Values.searchdb.port }}" OPENSEARCH_USERNAME: "{{ .Values.searchdb.security.adminUsername }}" OPENSEARCH_PASSWORD: "{{ .Values.searchdb.security.adminPassword }}" + SYSTEM_USERNAME: "{{ .Values.identityservice.users }}" + SYSTEM_PASSWORD: "{{ .Values.identityservice.userPasswords }}" {{- end }} diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index e1a6e87cdc12adc73b29be493f7c065b53555d1b..9afc47022d690ba679276c2cd5b4c76c4e7a34be 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -112,7 +112,7 @@ authservice: init: image: ## @skip authservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.6.1 ## @param authservice.init.resourcesPreset The container resource preset resourcesPreset: "nano" ## @param authservice.init.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) @@ -383,7 +383,7 @@ analyseservice: enabled: true image: ## @skip analyseservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.1 ## 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 @@ -444,7 +444,7 @@ metadataservice: enabled: true image: ## @skip metadataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.1 ## 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 @@ -541,7 +541,7 @@ dataservice: endpoint: http://data-service image: ## @skip dataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.1 ## 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 @@ -627,7 +627,7 @@ searchservice: endpoint: http://search-service image: ## @skip searchservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.1 ## 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 @@ -674,7 +674,7 @@ searchservice: init: image: ## @skip searchservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.1 ## @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) @@ -735,7 +735,7 @@ storageservice: init: image: ## @skip storageservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.1 s3: ## @param storageservice.init.s3.endpoint The S3-capable endpoint the microservice connects to. endpoint: http://storage-service-s3:8333 @@ -844,7 +844,7 @@ ui: enabled: true image: ## @skip ui.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.0 + name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.1 ## 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 @@ -962,6 +962,9 @@ dashboardservice: ## @skip dashboardservice.ldap.secretName secretName: dashboard-service-secret grafana: + updateStrategy: + ## @skip dashboardservice.grafana.updateStrategy.type + type: Recreate ## @skip dashboardservice.grafana.extraEnvVarsSecret extraEnvVarsSecret: dashboard-service-secret ## @skip dashboardservice.grafana.extraConfigmaps diff --git a/helm/seaweedfs/Chart.lock b/helm/seaweedfs/Chart.lock index c973082620a92115ed6d4b5f96147ed8ab5d7984..edcc38c41f0c6b2b35f8d740566918ddb16f17fc 100644 --- a/helm/seaweedfs/Chart.lock +++ b/helm/seaweedfs/Chart.lock @@ -4,9 +4,9 @@ dependencies: version: 20.2.1 - name: postgresql repository: oci://registry-1.docker.io/bitnamicharts - version: 16.3.4 + version: 16.4.3 - name: common repository: oci://registry-1.docker.io/bitnamicharts - version: 2.28.0 -digest: sha256:98a68ef67facda82298174f5bae4e07abd0998e0440002390583a1be97b17aee -generated: "2025-01-01T15:05:43.198633687+01:00" + version: 2.29.0 +digest: sha256:4c967f771b303ca0db9ba2e355790152448c77a05d3f6c69eda6c234bc3f60c6 +generated: "2025-01-17T15:24:18.141765362+01:00" diff --git a/helm/seaweedfs/charts/common-2.28.0.tgz b/helm/seaweedfs/charts/common-2.28.0.tgz deleted file mode 100644 index 21c0e76d36a29f77c0b874d747424dfa653b4971..0000000000000000000000000000000000000000 Binary files a/helm/seaweedfs/charts/common-2.28.0.tgz and /dev/null differ diff --git a/helm/seaweedfs/charts/common-2.29.0.tgz b/helm/seaweedfs/charts/common-2.29.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..f36e9e24ec32ce1237d1ee774541c5586fce222d Binary files /dev/null and b/helm/seaweedfs/charts/common-2.29.0.tgz differ diff --git a/helm/seaweedfs/charts/mariadb-20.2.1.tgz b/helm/seaweedfs/charts/mariadb-20.2.1.tgz index 2f55cc750ba3907eebca3545636e8f9c8afd19d2..9bba8eed49e866977396c0076b1a9c5946ec88b1 100644 Binary files a/helm/seaweedfs/charts/mariadb-20.2.1.tgz and b/helm/seaweedfs/charts/mariadb-20.2.1.tgz differ diff --git a/helm/seaweedfs/charts/postgresql-16.3.4.tgz b/helm/seaweedfs/charts/postgresql-16.3.4.tgz deleted file mode 100644 index 66db70566af3bfd481f39e80e83ff61e22b9d493..0000000000000000000000000000000000000000 Binary files a/helm/seaweedfs/charts/postgresql-16.3.4.tgz and /dev/null differ diff --git a/helm/seaweedfs/charts/postgresql-16.4.3.tgz b/helm/seaweedfs/charts/postgresql-16.4.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..429f7ed063f6655796792fbe711b027e147ddda4 Binary files /dev/null and b/helm/seaweedfs/charts/postgresql-16.4.3.tgz differ diff --git a/install.sh b/install.sh index 1e7520e29bf7ed3ef1a5310a8c7027a47b1ec249..710e9d55a1d65ba99d66a1540180548614464559 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash # preset -VERSION="1.6.0" +VERSION="1.6.1" MIN_CPU=8 MIN_RAM=4 MIN_MAP_COUNT=262144 diff --git a/lib/python/dbrepo/RestClient.py b/lib/python/dbrepo/RestClient.py index f10cfdc0fb66b1a25fd92f92b2737d4a9dae73a8..bc6940b7d034bcb85fec9f9c31c3b5a8aff0dcc3 100644 --- a/lib/python/dbrepo/RestClient.py +++ b/lib/python/dbrepo/RestClient.py @@ -1,18 +1,17 @@ +import logging import os import sys -import logging import time import requests -from pydantic import TypeAdapter -from tusclient.client import TusClient from pandas import DataFrame +from pydantic import TypeAdapter from dbrepo.UploadClient import UploadClient from dbrepo.api.dto import * from dbrepo.api.exceptions import ResponseCodeError, UsernameExistsError, EmailExistsError, NotExistsError, \ ForbiddenError, MalformedError, NameExistsError, QueryStoreError, ExternalSystemError, \ - AuthenticationError, UploadError, FormatNotAvailable, RequestError, ServiceError, ServiceConnectionError + AuthenticationError, FormatNotAvailable, RequestError, ServiceError, ServiceConnectionError logging.basicConfig(format='%(asctime)s %(name)-12s %(levelname)-6s %(message)s', level=logging.INFO, stream=sys.stdout) @@ -172,7 +171,7 @@ class RestClient: raise ResponseCodeError(f'Failed to find users: response code: {response.status_code} is not ' f'200 (OK): {response.text}') - def get_units(self) -> List[Unit]: + def get_units(self) -> List[UnitBrief]: """ Get all units known to the metadata database. @@ -184,7 +183,7 @@ class RestClient: response = self._wrapper(method="get", url=url) if response.status_code == 200: body = response.json() - return TypeAdapter(List[Unit]).validate_python(body) + return TypeAdapter(List[UnitBrief]).validate_python(body) raise ResponseCodeError(f'Failed to find units: response code: {response.status_code} is not ' f'200 (OK): {response.text}') @@ -1940,7 +1939,7 @@ class RestClient: raise ResponseCodeError(f'Failed to get licenses: response code: {response.status_code} is not ' f'200 (OK): {response.text}') - def get_concepts(self) -> List[Concept]: + def get_concepts(self) -> List[ConceptBrief]: """ Get list of concepts known to the metadata database. @@ -1950,7 +1949,7 @@ class RestClient: response = self._wrapper(method="get", url=url) if response.status_code == 200: body = response.json() - return TypeAdapter(List[Concept]).validate_python(body) + return TypeAdapter(List[ConceptBrief]).validate_python(body) raise ResponseCodeError(f'Failed to get concepts: response code: {response.status_code} is not ' f'200 (OK): {response.text}') diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 5100a7ae4e7c84ba16e51750a88b15ae5406d381..fa7eb063fc453c3dd8fabef04f141d07012c94a3 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -5,7 +5,7 @@ from dataclasses import field from enum import Enum from typing import List, Optional, Annotated -from pydantic import BaseModel, PlainSerializer, Field +from pydantic import BaseModel, PlainSerializer Timestamp = Annotated[ datetime.datetime, PlainSerializer(lambda v: v.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z', return_type=str) @@ -117,7 +117,7 @@ class ColumnBrief(BaseModel): database_id: int table_id: int internal_name: str - column_type: ColumnType + type: ColumnType class TableBrief(BaseModel): @@ -656,7 +656,7 @@ class ViewBrief(BaseModel): owned_by: str -class Concept(BaseModel): +class ConceptBrief(BaseModel): id: int uri: str name: Optional[str] = None @@ -691,7 +691,7 @@ class TableStatistics(BaseModel): columns: dict[str, ColumnStatistic] -class Unit(BaseModel): +class UnitBrief(BaseModel): id: int uri: str name: Optional[str] = None @@ -886,18 +886,18 @@ class Column(BaseModel): name: str database_id: int table_id: int + ord: int internal_name: str - column_type: ColumnType - is_public: bool is_null_allowed: bool + type: ColumnType alias: Optional[str] = None description: Optional[str] = None size: Optional[int] = None d: Optional[int] = None mean: Optional[float] = None median: Optional[float] = None - concept: Optional[Concept] = None - unit: Optional[Unit] = None + concept: Optional[ConceptBrief] = None + unit: Optional[UnitBrief] = None enums: Optional[List[str]] = field(default_factory=list) sets: Optional[List[str]] = field(default_factory=list) index_length: Optional[int] = None @@ -915,16 +915,15 @@ class ViewColumn(BaseModel): name: str database_id: int internal_name: str - column_type: ColumnType - is_public: bool + type: ColumnType is_null_allowed: bool alias: Optional[str] = None size: Optional[int] = None d: Optional[int] = None mean: Optional[float] = None median: Optional[float] = None - concept: Optional[Concept] = None - unit: Optional[Unit] = None + concept: Optional[ConceptBrief] = None + unit: Optional[UnitBrief] = None index_length: Optional[int] = None length: Optional[int] = None @@ -988,9 +987,10 @@ class DatabaseBrief(BaseModel): internal_name: str description: Optional[str] = None is_public: bool + is_schema_public: bool identifiers: Optional[List[Identifier]] = field(default_factory=list) contact: UserBrief - owner: UserBrief + owner_id: str class Unique(BaseModel): diff --git a/lib/python/docs/index.rst b/lib/python/docs/index.rst index 9c2ec5c590f65d75bcc2a2570146b8bb3e68cbcd..0a989f321fa9dbb644fba8c668cff807a1232826 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.6.0, earlier versions may be supported but are not tested for compatibility. + The SDK has been implemented and documented for DBRepo version 1.6.1, earlier versions may be supported but are not tested for compatibility. Quickstart ---------- diff --git a/lib/python/pyproject.toml b/lib/python/pyproject.toml index 382134d4df17fb712fb1c76b03bd47abf43625a8..33d1e52cc0a967a56e7e0a9ce639e5ceb53b42c6 100644 --- a/lib/python/pyproject.toml +++ b/lib/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dbrepo" -version = "1.6.0" +version = "1.6.1" description = "DBRepo Python Library" keywords = [ "DBRepo", diff --git a/lib/python/setup.py b/lib/python/setup.py index 705a48f08a84210af724a50c48acf174f041411b..027b8a5bb628da1cd03378d59d44ff8dc507c9a7 100644 --- a/lib/python/setup.py +++ b/lib/python/setup.py @@ -2,7 +2,7 @@ from distutils.core import setup setup(name="dbrepo", - version="1.6.0", + version="1.6.1", description="A library for communicating with DBRepo", url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/", author="Martin Weise", diff --git a/lib/python/tests/test_unit_database.py b/lib/python/tests/test_unit_database.py index affa94b496b1a8bf104fb12264256ad91e6fc8fb..eeeea68832ac33e2f013a3c2deaa3d4eec33122c 100644 --- a/lib/python/tests/test_unit_database.py +++ b/lib/python/tests/test_unit_database.py @@ -24,10 +24,11 @@ class DatabaseUnitTest(unittest.TestCase): DatabaseBrief( id=1, name='test', - owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + 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_public=True, + is_schema_public=True) ] with requests_mock.Mocker() as mock: # mock diff --git a/lib/python/tests/test_unit_table.py b/lib/python/tests/test_unit_table.py index 5d9e35294812c08adab7931c32337754fa17e3ee..4c4ad2af6aabbe6a36689fe3a44b50b8f6f625dc 100644 --- a/lib/python/tests/test_unit_table.py +++ b/lib/python/tests/test_unit_table.py @@ -2,14 +2,12 @@ import json import unittest import requests_mock -import datetime - -from dbrepo.RestClient import RestClient from pandas import DataFrame -from dbrepo.api.dto import Table, CreateTableConstraints, UserAttributes, User, Column, Constraints, ColumnType, \ - Concept, Unit, TableStatistics, ColumnStatistic, PrimaryKey, TableMinimal, ColumnMinimal, TableBrief, UserBrief -from dbrepo.api.exceptions import MalformedError, ForbiddenError, NotExistsError, NameExistsError, QueryStoreError, \ +from dbrepo.RestClient import RestClient +from dbrepo.api.dto import Table, CreateTableConstraints, Column, Constraints, ColumnType, ConceptBrief, UnitBrief, \ + TableStatistics, ColumnStatistic, PrimaryKey, TableMinimal, ColumnMinimal, TableBrief, UserBrief +from dbrepo.api.exceptions import MalformedError, ForbiddenError, NotExistsError, NameExistsError, \ AuthenticationError, ExternalSystemError @@ -35,13 +33,14 @@ class TableUnitTest(unittest.TestCase): column=ColumnMinimal(id=1, table_id=2, database_id=1))]), columns=[Column(id=1, + ord=0, name="ID", database_id=1, table_id=2, internal_name="id", auto_generated=True, is_primary_key=True, - column_type=ColumnType.BIGINT, + type=ColumnType.BIGINT, is_public=True, is_null_allowed=False)]) with requests_mock.Mocker() as mock: @@ -165,12 +164,13 @@ class TableUnitTest(unittest.TestCase): database_id=1))]), columns=[Column(id=1, name="ID", + ord=0, database_id=1, table_id=2, internal_name="id", auto_generated=True, is_primary_key=True, - column_type=ColumnType.BIGINT, + type=ColumnType.BIGINT, is_public=True, is_null_allowed=False)]) # mock @@ -487,20 +487,21 @@ class TableUnitTest(unittest.TestCase): def test_update_table_column_succeeds(self): with requests_mock.Mocker() as mock: exp = Column(id=1, + ord=0, name="ID", database_id=1, table_id=2, internal_name="id", auto_generated=True, is_primary_key=True, - column_type=ColumnType.BIGINT, + type=ColumnType.BIGINT, is_public=True, - concept=Concept(id=2, - uri="http://dbpedia.org/page/Category:Precipitation", - name="Precipitation"), - unit=Unit(id=2, - uri="http://www.wikidata.org/entity/Q119856947", - name="liters per square meter"), + concept=ConceptBrief(id=2, + uri="http://dbpedia.org/page/Category:Precipitation", + name="Precipitation"), + unit=UnitBrief(id=2, + uri="http://www.wikidata.org/entity/Q119856947", + name="liters per square meter"), is_null_allowed=False) # mock mock.put('/api/database/1/table/2/column/1', json=exp.model_dump(), status_code=202) diff --git a/lib/python/tests/test_unit_view.py b/lib/python/tests/test_unit_view.py index 865fc6a7148ec642b6bbca3cea3a23c9fc6b9896..52ea405b28369e20244b9fa111cb745580fb9d30 100644 --- a/lib/python/tests/test_unit_view.py +++ b/lib/python/tests/test_unit_view.py @@ -5,7 +5,7 @@ import requests_mock from pandas import DataFrame from dbrepo.RestClient import RestClient -from dbrepo.api.dto import UserAttributes, User, View, ViewColumn, ColumnType, UserBrief +from dbrepo.api.dto import View, ViewColumn, ColumnType, UserBrief from dbrepo.api.exceptions import ForbiddenError, NotExistsError, MalformedError, AuthenticationError @@ -31,8 +31,15 @@ class ViewUnitTest(unittest.TestCase): owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), is_public=True, is_schema_public=True, - columns=[ViewColumn(id=1, name="id", internal_name="id", database_id=1, auto_generated=False, - column_type=ColumnType.BIGINT, is_public=True, is_null_allowed=False)], + columns=[ViewColumn(id=1, + ord=0, + name="id", + internal_name="id", + database_id=1, + auto_generated=False, + type=ColumnType.BIGINT, + is_public=True, + is_null_allowed=False)], identifiers=[])] # mock mock.get('/api/database/1/view', json=[exp[0].model_dump()]) @@ -62,8 +69,15 @@ class ViewUnitTest(unittest.TestCase): owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), is_public=True, is_schema_public=True, - columns=[ViewColumn(id=1, name="id", internal_name="id", database_id=1, auto_generated=False, - column_type=ColumnType.BIGINT, is_public=True, is_null_allowed=False)], + columns=[ViewColumn(id=1, + ord=0, + name="id", + internal_name="id", + database_id=1, + auto_generated=False, + type=ColumnType.BIGINT, + is_public=True, + is_null_allowed=False)], identifiers=[]) # mock mock.get('/api/database/1/view/3', json=exp.model_dump()) @@ -103,8 +117,15 @@ class ViewUnitTest(unittest.TestCase): owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), is_public=True, is_schema_public=True, - columns=[ViewColumn(id=1, name="id", internal_name="id", database_id=1, auto_generated=False, - column_type=ColumnType.BIGINT, is_public=True, is_null_allowed=False)], + columns=[ViewColumn(id=1, + ord=0, + name="id", + internal_name="id", + database_id=1, + auto_generated=False, + type=ColumnType.BIGINT, + is_public=True, + is_null_allowed=False)], identifiers=[]) # mock mock.post('/api/database/1/view', json=exp.model_dump(), status_code=201) diff --git a/make/rel.mk b/make/rel.mk index 6a24d75a90a3abe6a887262b285262135c1688ce..0c4b2bb193f3618e3098d13fd283882701e29a20 100644 --- a/make/rel.mk +++ b/make/rel.mk @@ -6,6 +6,7 @@ tag-images: build-images ## Tag the docker images. docker tag dbrepo-dashboard-service:latest "${REPOSITORY_URL}/dashboard-service:${APP_VERSION}" docker tag dbrepo-ui:latest "${REPOSITORY_URL}/ui:${APP_VERSION}" docker tag dbrepo-data-service:latest "${REPOSITORY_URL}/data-service:${APP_VERSION}" + docker tag dbrepo-auth-service-init:latest "${REPOSITORY_URL}/auth-service-init:${APP_VERSION}" docker tag dbrepo-metadata-service:latest "${REPOSITORY_URL}/metadata-service:${APP_VERSION}" docker tag dbrepo-search-db:latest "${REPOSITORY_URL}/search-db:${APP_VERSION}" docker tag dbrepo-search-service:latest "${REPOSITORY_URL}/search-service:${APP_VERSION}" @@ -18,6 +19,7 @@ release-images: tag-images ## Release the docker images. docker push "${REPOSITORY_URL}/dashboard-service:${APP_VERSION}" docker push "${REPOSITORY_URL}/ui:${APP_VERSION}" docker push "${REPOSITORY_URL}/data-service:${APP_VERSION}" + docker push "${REPOSITORY_URL}/auth-service-init:${APP_VERSION}" docker push "${REPOSITORY_URL}/search-db:${APP_VERSION}" docker push "${REPOSITORY_URL}/metadata-service:${APP_VERSION}" docker push "${REPOSITORY_URL}/search-service:${APP_VERSION}" diff --git a/sonar-project.properties b/sonar-project.properties index fdbf030ef0e674288083ee1366822ea99d055e19..d354d54608a75063e0000cd577469dba69ae5eec 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.6.0 +sonar.projectVersion=1.6.1 # general sonar.qualitygate.wait=true sonar.projectCreation.mainBranchName=master