diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 0f675e47eb507fa1d2c6691f6e7708d4ffc414fd..f637eb4f8b30d5fa1d6d018ad7f692c61ec7d7e6 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -114,7 +114,7 @@ services: init: true restart: "no" container_name: dbrepo-auth-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.4 environment: AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} @@ -135,7 +135,7 @@ services: restart: "no" container_name: dbrepo-metadata-service hostname: metadata-service - image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.4 volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: @@ -198,7 +198,7 @@ services: restart: "no" container_name: dbrepo-analyse-service hostname: analyse-service - image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.4 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -253,7 +253,7 @@ services: restart: "no" container_name: dbrepo-search-db hostname: search-db - image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.6.4 healthcheck: test: curl -sSL localhost:9200/_plugins/_security/health | jq .status | grep UP interval: 10s @@ -277,7 +277,7 @@ services: restart: "no" container_name: dbrepo-search-service hostname: search-service - image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.4 environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -301,7 +301,7 @@ services: restart: "no" container_name: dbrepo-ui hostname: ui - image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.4 environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://gateway-service}" @@ -381,7 +381,7 @@ services: init: true container_name: dbrepo-search-service-init hostname: search-service-init - image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.4 environment: LOG_LEVEL: ${LOG_LEVEL:-info} METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} @@ -438,7 +438,7 @@ services: restart: "no" container_name: dbrepo-dashboard-service hostname: dashboard-service - image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.6.4 ports: - "3000:3000" volumes: @@ -465,7 +465,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.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.4 environment: S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-seaweedfsadmin} S3_BUCKET: "${S3_BUCKET:-dbrepo}" @@ -511,7 +511,7 @@ services: restart: "no" container_name: dbrepo-data-service hostname: data-service - image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.7.0 + image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.4 volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: diff --git a/.docs/.openapi/api.base.yaml b/.docs/.openapi/api.base.yaml index abadb218e7fa3b74a11caea3b01d3f73f2fa988a..f37d861b0955c50fd655e671716e0484d2d0502d 100644 --- a/.docs/.openapi/api.base.yaml +++ b/.docs/.openapi/api.base.yaml @@ -11,7 +11,7 @@ components: type: http externalDocs: description: Project Website - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/ info: contact: email: andreas.rauber@tuwien.ac.at @@ -24,7 +24,7 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 title: DBRepo REST API - version: 1.7.0 + version: 1.6.4 openapi: 3.1.0 servers: - description: Test Instance diff --git a/.docs/changelog.md b/.docs/changelog.md index efdb4dd291dbbc3194ffc3ec3168ed71befffee3..e1452dd12c4d6a6de98438087f61a1853e90779f 100644 --- a/.docs/changelog.md +++ b/.docs/changelog.md @@ -2,6 +2,17 @@ author: Martin Weise --- +## v1.6.4 (2025-02-13) + +[:simple-gitlab: GitLab Release](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tags/v1.6.4) + +### What's Changed + +#### Fixes + +* Fixed a bug where the users were not synced with the Metadata Database and the API Password was not recommended on + first login in [#489](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/489). + ## v1.6.3 (2025-02-05) [:simple-gitlab: GitLab Release](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tags/v1.6.3) diff --git a/.docs/index.md b/.docs/index.md index aa9c6e7693f3758fadcddbe05cd5904c5e92b7da..cf54cf46ccafc0bbf5c3d15b7d4c3e25b0c4975d 100644 --- a/.docs/index.md +++ b/.docs/index.md @@ -14,7 +14,7 @@ author: Martin Weise   -Documentation for version: [v1.7.0](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases). +Documentation for version: [v1.6.4](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 68f9bc16c1190a7f5d9827028d57757432aeb17d..ea377171d37d2538502faa3a65a61309681c3f16 100644 --- a/.docs/kubernetes.md +++ b/.docs/kubernetes.md @@ -14,7 +14,7 @@ helm upgrade --install dbrepo \ -n dbrepo \ "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" \ --values ./values.yaml \ - --version "1.7.0" \ + --version "1.6.4" \ --create-namespace \ --cleanup-on-fail ``` diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b20acd3f2a029594345b6992ef7deb625a608513..74cfb6df9a689e5a4a70469369c11a9da34cf8ea 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,9 +9,9 @@ variables: NODE_VERSION: "18" SONARQUBE_VERSION: "10.0" BUN_VERSION: "1.1.40" - DOC_VERSION: "1.7" - APP_VERSION: "1.7.0" - CHART_VERSION: "1.7.0" + DOC_VERSION: "1.6" + APP_VERSION: "1.6.4" + CHART_VERSION: "1.6.4" 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 e8f2553784f38ea5e656d776e34043886ed1ed4c..c81307ab1f26f6d77a1457301b764e751d7e837f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: all -APP_VERSION ?= 1.7.0 -CHART_VERSION ?= 1.7.0 +APP_VERSION ?= 1.6.4 +CHART_VERSION ?= 1.6.4 REPOSITORY_URL ?= registry.datalab.tuwien.ac.at/dbrepo .PHONY: all diff --git a/README.md b/README.md index 901d24dd06dd2863da84c5622f9aa8b157462171..628da3f3f3335717b5b4e0962a6ff45d36fed420 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ If you have [Docker](https://docs.docker.com/engine/install/) already installed with: ```bash -curl -sSL https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-1.7/install.sh | bash +curl -sSL https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-1.6/install.sh | bash ``` ## Documentation diff --git a/dbrepo-analyse-service/Pipfile b/dbrepo-analyse-service/Pipfile index 6b144eec80011a340dbbaabc0c3bce5894e3c654..3d7911147c825d17bebf78e8f5aeaa64050c7eb0 100644 --- a/dbrepo-analyse-service/Pipfile +++ b/dbrepo-analyse-service/Pipfile @@ -21,7 +21,7 @@ numpy = "*" pandas = "*" minio = "*" pydantic = "*" -dbrepo = {path = "./lib/dbrepo-1.7.0.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.6.4.tar.gz"} opensearch-py = "*" [dev-packages] diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index 83ed8a674de78d5f8c89365a355b19261abbada0..c3a282c98512ad5c6dd6d1bed525bf3b3060827b 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0af9d522f713554dd7996401992cffddf372ade320c11d7950bdcd5888aa1a03" + "sha256": "b24e4e03891018663e2746e2dbe5a9fe716f823be5ccb310c90e8e68b9ffd1d5" }, "pipfile-spec": 6, "requires": { @@ -180,20 +180,20 @@ }, "boto3": { "hashes": [ - "sha256:59bcf0c4b04d9cc36f8b418ad17ab3c4a99a21a175d2fad7096aa21cbe84630b", - "sha256:5ecae20e780a3ce9afb3add532b61c466a8cb8960618e4fa565b3883064c1346" + "sha256:7784590369a9d545bb07b2de56b6ce4d5a5e232883a957f704c3f842caeba155", + "sha256:8c2c2a4ccdfe35dd2611ee1b7473dd2383948415c777e42dc4e7f1ebe371fe8c" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.36.17" + "version": "==1.36.19" }, "botocore": { "hashes": [ - "sha256:069858b2fd693548035d7fd53a774e37e4260fea64e0ac9b8a3aee904f9321df", - "sha256:cec13e0a7ce78e71aad0b397581b4e81824c7981ef4c261d2e296d200c399b09" + "sha256:98882c106fec4c08678ea028199f7f5119550fab95d682b30846f7aae04b7bec", + "sha256:cdf6729f601f82b1acdb9004b1f88b57cfb470f576394cdb3bbf5150f7fafb5b" ], "markers": "python_version >= '3.8'", - "version": "==1.36.17" + "version": "==1.36.19" }, "certifi": { "hashes": [ @@ -421,9 +421,9 @@ }, "dbrepo": { "hashes": [ - "sha256:f25d5adbd618bf2906578e671af2bf3bcc24d738ef8bc791c220e7e5b714e2f7" + "sha256:a518aee79540d9e302b161e7e10072f50730489da19368f00a1e68204009ce44" ], - "path": "./lib/dbrepo-1.7.0.tar.gz" + "path": "./lib/dbrepo-1.6.4.tar.gz" }, "events": { "hashes": [ @@ -1621,7 +1621,7 @@ "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" ], - "markers": "python_version >= '3.10'", + "markers": "python_version >= '3.9'", "version": "==2.3.0" }, "werkzeug": { @@ -2246,7 +2246,7 @@ "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" ], - "markers": "python_version >= '3.10'", + "markers": "python_version >= '3.9'", "version": "==2.3.0" }, "wrapt": { diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.4-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.6.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d083b0bafc937528fdcc09634c41132578cbf345 Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.6.4-py3-none-any.whl differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.4.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.6.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..87e9a503ebc621238ebe7efca15f2bdf0a6e1a85 Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.6.4.tar.gz differ diff --git a/dbrepo-auth-service/dbrepo-realm.json b/dbrepo-auth-service/dbrepo-realm.json index 1c703b83750c5aa21d4da06c7895d74211122ae9..bac2ddc9782822da0fac897c7bbc9a2f8ae84ed6 100644 --- a/dbrepo-auth-service/dbrepo-realm.json +++ b/dbrepo-auth-service/dbrepo-realm.json @@ -1475,6 +1475,39 @@ "claim.name" : "language", "jsonType.label" : "String" } + }, { + "id" : "9bdc3e60-09b8-4241-915e-29f083434026", + "name" : "provider", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "identity_provider", + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "lightweight.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "identity_provider", + "jsonType.label" : "String", + "access.tokenResponse.claim" : "false" + } + }, { + "id" : "e567cb5c-8856-4124-8b86-f19cd53d7c71", + "name" : "setup_finished", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "SETUP_FINISHED", + "id.token.claim" : "true", + "lightweight.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "setup_finished", + "jsonType.label" : "boolean" + } }, { "id" : "b817424d-7f91-43d8-b7d0-6a32582377fb", "name" : "family name", @@ -2376,7 +2409,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper" ] } }, { "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", @@ -2402,7 +2435,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-address-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-address-mapper" ] } } ], "org.keycloak.userprofile.UserProfileProvider" : [ { @@ -2426,8 +2459,8 @@ "config" : { "ldap.attribute" : [ "createTimestamp" ], "is.mandatory.in.ldap" : [ "false" ], - "always.read.value.from.ldap" : [ "true" ], "read.only" : [ "true" ], + "always.read.value.from.ldap" : [ "true" ], "user.model.attribute" : [ "createTimestamp" ] } }, { @@ -2438,8 +2471,8 @@ "config" : { "ldap.attribute" : [ "sn" ], "is.mandatory.in.ldap" : [ "true" ], - "read.only" : [ "false" ], "always.read.value.from.ldap" : [ "true" ], + "read.only" : [ "false" ], "user.model.attribute" : [ "lastName" ] } }, { @@ -2450,8 +2483,8 @@ "config" : { "ldap.attribute" : [ "cn" ], "is.mandatory.in.ldap" : [ "true" ], - "always.read.value.from.ldap" : [ "true" ], "read.only" : [ "false" ], + "always.read.value.from.ldap" : [ "true" ], "user.model.attribute" : [ "firstName" ] } }, { @@ -2462,8 +2495,8 @@ "config" : { "ldap.attribute" : [ "mail" ], "is.mandatory.in.ldap" : [ "false" ], - "always.read.value.from.ldap" : [ "false" ], "read.only" : [ "false" ], + "always.read.value.from.ldap" : [ "false" ], "user.model.attribute" : [ "email" ] } }, { @@ -2476,15 +2509,15 @@ "membership.attribute.type" : [ "DN" ], "user.roles.retrieve.strategy" : [ "LOAD_GROUPS_BY_MEMBER_ATTRIBUTE" ], "group.name.ldap.attribute" : [ "cn" ], - "membership.user.ldap.attribute" : [ "uid" ], - "ignore.missing.groups" : [ "false" ], "preserve.group.inheritance" : [ "false" ], "membership.ldap.attribute" : [ "member" ], - "memberof.ldap.attribute" : [ "memberOf" ], - "group.object.classes" : [ "groupOfNames" ], + "ignore.missing.groups" : [ "false" ], + "membership.user.ldap.attribute" : [ "uid" ], "groups.dn" : [ "ou=users,dc=dbrepo,dc=at" ], - "groups.path" : [ "/" ], - "drop.non.existing.groups.during.sync" : [ "false" ] + "group.object.classes" : [ "groupOfNames" ], + "memberof.ldap.attribute" : [ "memberOf" ], + "drop.non.existing.groups.during.sync" : [ "false" ], + "groups.path" : [ "/" ] } }, { "id" : "b6ff3285-35af-4e86-8bb4-d94b8e0d70bb", @@ -2518,8 +2551,8 @@ "fullSyncPeriod" : [ "-1" ], "pagination" : [ "false" ], "startTls" : [ "false" ], - "connectionPooling" : [ "true" ], "usersDn" : [ "ou=users,dc=dbrepo,dc=at" ], + "connectionPooling" : [ "true" ], "cachePolicy" : [ "DEFAULT" ], "useKerberosForPasswordAuthentication" : [ "false" ], "importEnabled" : [ "true" ], @@ -2531,8 +2564,8 @@ "lastSync" : [ "1719252666" ], "vendor" : [ "other" ], "uuidLDAPAttribute" : [ "entryUUID" ], - "allowKerberosAuthentication" : [ "false" ], "connectionUrl" : [ "ldap://identity-service:1389" ], + "allowKerberosAuthentication" : [ "false" ], "syncRegistrations" : [ "true" ], "authType" : [ "simple" ], "useTruststoreSpi" : [ "always" ], diff --git a/dbrepo-auth-service/listeners/src/main/java/at/tuwien/Client.java b/dbrepo-auth-service/listeners/src/main/java/at/tuwien/Client.java index 769ec49097223e5fd49f76d855d9acef1cfbe35c..c63e88618b792f4d85e52b4aee55c80e1a2f1db8 100644 --- a/dbrepo-auth-service/listeners/src/main/java/at/tuwien/Client.java +++ b/dbrepo-auth-service/listeners/src/main/java/at/tuwien/Client.java @@ -31,8 +31,7 @@ public class Client { if (systemPassword == null || systemPassword.isEmpty()) { throw new IllegalArgumentException("Environment variable SYSTEM_PASSWORD is not set or is empty."); } - - URL url = URI.create(urlString).toURL(); + final URL url = URI.create(urlString + "/api/user").toURL(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); diff --git a/dbrepo-auth-service/listeners/src/main/java/at/tuwien/CreateEventListenerProvider.java b/dbrepo-auth-service/listeners/src/main/java/at/tuwien/CreateEventListenerProvider.java index 93f2b2919b81940e8803b8b451c5388163f7d5dd..ea4aa7794b6f26167da704e4c12057cf9d8c5c42 100644 --- a/dbrepo-auth-service/listeners/src/main/java/at/tuwien/CreateEventListenerProvider.java +++ b/dbrepo-auth-service/listeners/src/main/java/at/tuwien/CreateEventListenerProvider.java @@ -57,7 +57,6 @@ public class CreateEventListenerProvider implements EventListenerProvider { final String userData = "{" + quoteAttr("id", user.getId()) + ", " + quoteAttr("username", user.getUsername()) + ", " + - quoteAttr("email", user.getEmail()) + ", " + quoteAttr("ldap_id", user.getFirstAttribute("LDAP_ID")) + ", " + quoteAttr("given_name", user.getFirstName()) + ", " + quoteAttr("family_name", user.getLastName()) + diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index a23243d39509ec3821219e5799a25740c93e2ca1..a970096eeaa5015d9e95064f6b341fffdf8aae5f 100644 Binary files a/dbrepo-auth-service/listeners/target/create-event-listener.jar and b/dbrepo-auth-service/listeners/target/create-event-listener.jar differ diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index db7947432e3f6117bfe8d888a47e7b6d176b66ab..0e2001b9319f1d755eca5f3f6dbe6335b1cbede3 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.7.0</version> + <version>1.6.4</version> <description>Service that manages the data</description> diff --git a/dbrepo-data-service/querystore/pom.xml b/dbrepo-data-service/querystore/pom.xml index 1aa138f611c7fa5ec2fc4f6dc98beb8a177f24b5..0c01d6893c9d39bfea9890b2a848030d0373146f 100644 --- a/dbrepo-data-service/querystore/pom.xml +++ b/dbrepo-data-service/querystore/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-data-service-querystore</artifactId> <name>dbrepo-data-service-querystore</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies/> diff --git a/dbrepo-data-service/report/pom.xml b/dbrepo-data-service/report/pom.xml index 98536501d3beb70b5c05f632e673a401b03ae2cd..ed4826a38d5aa6f820914db64def695882261d9c 100644 --- a/dbrepo-data-service/report/pom.xml +++ b/dbrepo-data-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>report</artifactId> <name>dbrepo-data-service-report</name> - <version>1.7.0</version> + <version>1.6.4</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 434c423ef056566305e2d72db984781e7b1429fc..836782387040df14680ade1af7b49f2fffb10895 100644 --- a/dbrepo-data-service/rest-service/pom.xml +++ b/dbrepo-data-service/rest-service/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>rest-service</artifactId> <name>dbrepo-data-service-rest-service</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>services</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </dependency> </dependencies> diff --git a/dbrepo-data-service/services/pom.xml b/dbrepo-data-service/services/pom.xml index 5252e6a3d30439671d085b9ac2d6bca81bf462c0..3f645dda320c2774eba62b273c5f851f7a3b3e8d 100644 --- a/dbrepo-data-service/services/pom.xml +++ b/dbrepo-data-service/services/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>services</artifactId> <name>dbrepo-data-service-services</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service-querystore</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </dependency> </dependencies> diff --git a/dbrepo-metadata-service/api/pom.xml b/dbrepo-metadata-service/api/pom.xml index 6c3b1aa13fbe0ccac21e0e0ce1ede0a78e6f340d..3f68887ec008b41db2d0afe027ce3d65eaa8a7d1 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-api</artifactId> <name>dbrepo-metadata-service-api</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service-entities</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> <scope>compile</scope> </dependency> </dependencies> 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 16f45aec4d625639f1188e0e853b3a81bd71811f..9742986ae08df9f9d00f5c1bc9da15b245bad8fc 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 @@ -40,7 +40,4 @@ public class CreateUserDto { @Schema(example = "bar") private String familyName; - @Schema(example = "foo.bar@example.com") - private String email; - } diff --git a/dbrepo-metadata-service/entities/pom.xml b/dbrepo-metadata-service/entities/pom.xml index 313309e18831501558a149cab52920bb90e89e91..382fa2e7e81dcd2629b0c4cc3c25b8bce3364b4f 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-entities</artifactId> <name>dbrepo-metadata-service-entity</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies/> 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 ba86e3d29c6913d45d51ae0498fdac8d3092b657..156fc3b4c8efbd44e4d8389b50a7cb0f65814aac 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 @@ -65,7 +65,7 @@ public class User { @Column(name = "mariadb_password", nullable = false) private String mariadbPassword; - @Column(name = "is_internal", nullable = false, updatable = false) + @Column(name = "is_internal", nullable = false, updatable = false, columnDefinition = "bool default false") private Boolean isInternal; } diff --git a/dbrepo-metadata-service/oai/pom.xml b/dbrepo-metadata-service/oai/pom.xml index 54c464b11a31cea0e588f797fa38012c573a1d02..76beb8d88f596107f16e135c7aa17cedd5fb2d2b 100644 --- a/dbrepo-metadata-service/oai/pom.xml +++ b/dbrepo-metadata-service/oai/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-oai</artifactId> <name>dbrepo-metadata-service-oai</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies/> diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index d64da973f01777505b79c85232aac253494a52b6..ae5c004e0cbdb64c3adac5d091e39cafd5376ad7 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.7.0</version> + <version>1.6.4</version> <description>Service that manages the metadata</description> diff --git a/dbrepo-metadata-service/report/pom.xml b/dbrepo-metadata-service/report/pom.xml index 6bcb8d579b67439ad4bcd590cf5af3819f70218e..be6e86a4d08965220aaf87d6ec93b8162514f943 100644 --- a/dbrepo-metadata-service/report/pom.xml +++ b/dbrepo-metadata-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-report</artifactId> <name>dbrepo-metadata-service-report</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/pom.xml b/dbrepo-metadata-service/repositories/pom.xml index 4d3b5f933d2c39674b2f9e58461387c0a2cffdb8..cf327942a45f9efeb7e8e06374ffdec8c443fa4c 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-repositories</artifactId> <name>dbrepo-metadata-service-repositories</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/rest-service/pom.xml b/dbrepo-metadata-service/rest-service/pom.xml index 9e9f23d11fdbab4fc2308bead597a7626272ceb1..e1524f79715ffbd081c170257c1ab295d45a5052 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-rest-service</artifactId> <name>dbrepo-metadata-service-rest</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> 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 50016103d83ccfffab65ddc153e6b88074e34e2c..41cc59ca6ad3aa8b3a74bf3ae5eda482231863be 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 @@ -511,19 +511,26 @@ public class DatabaseEndpoint extends AbstractEndpoint { .stream() .filter(a -> a.getUser().getId().equals(getId(principal))) .findFirst(); + optional.ifPresentOrElse(access -> log.trace("user has access: {}", access), () -> log.trace("user has no access")); if (!database.getIsPublic() && !database.getIsSchemaPublic() && optional.isEmpty() && !isSystem(principal)) { log.error("Failed to find database: not public and no access found"); throw new NotAllowedException("Failed to find database: not public and no access found"); } /* reduce metadata */ + final int tables = database.getTables() + .size(); database.setTables(database.getTables() .stream() .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent()) .toList()); + log.trace("filtered database tables from {} to {}", tables, database.getTables().size()); + final int views = database.getViews() + .size(); database.setViews(database.getViews() .stream() .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent()) .toList()); + log.trace("filtered database views from {} to {}", views, database.getViews().size()); 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()); 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 51f323c30f1581314df88dab86ec2900775c215e..5ca14a5a34605e80ab48c5f2309f6dd15bea714f 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 @@ -106,47 +106,15 @@ public class UserEndpoint extends AbstractEndpoint { @ApiResponse(responseCode = "400", description = "Parameters are not well-formed (likely email)", content = {@Content(mediaType = "application/json")}), - @ApiResponse(responseCode = "403", - description = "Internal authentication to the auth service is invalid", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "404", - description = "Default role not found", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "409", - description = "User with username already exists", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "417", - description = "User with e-mail already exists", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "502", - description = "Failed to create in auth service", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "503", - description = "Failed to create in auth service", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<UserBriefDto> create(@NotNull @Valid @RequestBody CreateUserDto data) - throws UserExistsException, EmailExistsException, AuthServiceException, AuthServiceConnectionException, - UserNotFoundException, CredentialsInvalidException { + public ResponseEntity<UserBriefDto> create(@NotNull @Valid @RequestBody CreateUserDto data) { log.debug("endpoint create user, data.id={}, data.username={}", data.getId(), data.getUsername()); return ResponseEntity.status(HttpStatus.CREATED) .body(userMapper.userToUserBriefDto( userService.create(data))); } - @GetMapping("/{userId}") + @RequestMapping(value = "/{userId}", method = {RequestMethod.GET, RequestMethod.HEAD}) @Transactional(readOnly = true) @PreAuthorize("isAuthenticated()") @Observed(name = "dbrepo_user_find") @@ -181,12 +149,14 @@ public class UserEndpoint extends AbstractEndpoint { throw new NotAllowedException("Failed to find user: foreign user"); } if (user.getIsInternal()) { - throw new UserNotFoundException("Failed to find user with username: " + user.getUsername()); + log.error("Failed to find user: internal user"); + throw new NotAllowedException("Failed to find user: internal user"); } final HttpHeaders headers = new HttpHeaders(); if (isSystem(principal)) { headers.set("X-Username", user.getUsername()); headers.set("X-Password", user.getMariadbPassword()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) @@ -282,18 +252,18 @@ public class UserEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody UserPasswordDto data, @NotNull Principal principal) throws NotAllowedException, UserNotFoundException, DatabaseNotFoundException, DataServiceException, - DataServiceConnectionException { + DataServiceConnectionException, AuthServiceException { 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.findAllAtLestReadAccess(userId)) { databaseService.updatePassword(database, user); } userService.updatePassword(user, data); + authenticationService.setupFinished(user); return ResponseEntity.accepted() .build(); } 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 a54f616b01e61edad50d85d4b5f0d494c9e429d6..6fe29c118bd47683874cd4a92397c62317de3a83 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 @@ -131,7 +131,7 @@ public class EndpointValidator extends AbstractEndpoint { final Optional<CreateTableColumnDto> optional3 = data.getColumns() .stream() .filter(c -> c.getType().equals(ColumnTypeDto.SET)) - .filter(c -> c.getEnums() == null || c.getSets().isEmpty()) + .filter(c -> c.getSets() == null || c.getSets().isEmpty()) .findFirst(); if (optional3.isPresent()) { log.error("Validation failed: column {} needs at least 1 allowed set value", optional3.get().getName()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..33c7bc76c552c70989dbc4ffc39e317fdb5826ac --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/ApplicationIntegrationTest.java @@ -0,0 +1,23 @@ +package at.tuwien; + +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@Log4j2 +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@SpringBootTest +@ExtendWith(SpringExtension.class) +public class ApplicationIntegrationTest { + + @Test + public void main_succeeds() { + + /* test */ + DbrepoMetadataServiceApplication.main(new String[]{}); + } + +} 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 fd91fb5655ad563ee0b4f8503dbdb5b60db6fea9..1340d552d1b8ff3da3be847704d3d9ccd328eabc 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 @@ -269,7 +269,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void list_anonymous_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + public void list_anonymous_succeeds() { /* mock */ when(databaseService.findAllPublicOrSchemaPublic()) @@ -281,7 +281,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRole_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + public void list_hasRole_succeeds() { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -296,7 +296,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleForeign_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + public void list_hasRoleForeign_succeeds() { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -311,7 +311,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilter_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + public void list_hasRoleFilter_succeeds() { /* mock */ when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, DATABASE_3_INTERNALNAME)) @@ -323,7 +323,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilterNoResult_succeeds() throws DatabaseNotFoundException, UserNotFoundException { + public void list_hasRoleFilterNoResult_succeeds() { /* mock */ when(databaseService.findAllPublicOrSchemaPublicOrReadAccessByInternalName(USER_1_ID, "i_do_not_exist")) @@ -333,6 +333,18 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { list_generic("i_do_not_exist", USER_1_PRINCIPAL, 0); } + @Test + @WithAnonymousUser + public void list_filterNoResult_succeeds() { + + /* mock */ + when(databaseService.findAllPublicOrSchemaPublicByInternalName("i_do_not_exist")) + .thenReturn(List.of()); + + /* test */ + list_generic("i_do_not_exist", null, 0); + } + @Test @WithAnonymousUser public void visibility_anonymous_fails() { @@ -562,15 +574,15 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithAnonymousUser - public void findById_anonymousPrivateSchemaNoAccessSystem_succeeds() throws UserNotFoundException, + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) + public void findById_privateSchemaNoAccessInternalUser_succeeds() throws UserNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, ExchangeNotFoundException, DataServiceConnectionException { /* test */ - final DatabaseDto database = findById_generic(DATABASE_1_ID, DATABASE_1, USER_LOCAL_ADMIN_PRINCIPAL); - assertEquals(4, database.getTables().size()); - assertEquals(2, database.getViews().size()); + final DatabaseDto database = findById_generic(DATABASE_3_ID, DATABASE_3, USER_LOCAL_ADMIN_PRINCIPAL); + assertEquals(0, database.getTables().size()); + assertEquals(1, database.getViews().size()); assertNotEquals(0, database.getAccesses().size()); } @@ -610,6 +622,58 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { assertEquals(3, database.getAccesses().size()); } + @Test + @WithMockUser(username = USER_2_USERNAME) + public void findById_hiddenAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { + + /* mock */ + when(accessService.list(DATABASE_1)) + .thenReturn(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS, DATABASE_1_USER_2_READ_ACCESS)); + + /* test */ + final DatabaseDto database = findById_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL); + assertEquals(4, database.getTables().size()); + assertEquals(3, database.getViews().size()); + assertEquals(0, database.getAccesses().size()); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void findById_hiddenAccessRightsSeesOwn_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { + + /* mock */ + when(accessService.list(DATABASE_1)) + .thenReturn(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS, DATABASE_1_USER_2_READ_ACCESS)); + + /* test */ + final DatabaseDto database = findById_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL); + assertEquals(4, database.getTables().size()); + assertEquals(3, database.getViews().size()); + assertEquals(3, database.getAccesses().size()); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void findById_privateDataPrivateSchemaNoAccess_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + findById_generic(DATABASE_1_ID, DATABASE_1, USER_4_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void findById_anonymousPrivateDataPrivateSchema_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + findById_generic(DATABASE_1_ID, DATABASE_1, null); + }); + } + @Test @WithAnonymousUser public void findPreviewImage_anonymous_succeeds() throws DatabaseNotFoundException { @@ -660,8 +724,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void list_generic(String internalName, Principal principal, Integer expectedSize) - throws DatabaseNotFoundException, UserNotFoundException { + public void list_generic(String internalName, Principal principal, Integer expectedSize) { /* test */ final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName, principal); 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 a17d31649e6824442613261b91bca4ee923a4817..16551784c883cc69dfbb87504fafc504f1af7015 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 @@ -1,12 +1,12 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.CreateTableDto; +import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.TableUpdateDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.columns.CreateTableColumnDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; import at.tuwien.api.semantics.EntityDto; @@ -40,6 +40,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.security.Principal; import java.util.List; +import java.util.UUID; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -524,7 +525,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findById_publicDatabasePrivateDataPrivateSchemaAnonymous_succeeds() throws UserNotFoundException, - TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { + TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, + AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); @@ -596,6 +598,16 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }); } + @Test + @WithMockUser(username = USER_4_USERNAME, authorities = {"table-semantic-analyse"}) + public void analyseTable_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + analyseTable_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL); + }); + } + @Test @WithMockUser(username = USER_4_USERNAME) public void findAll_noRole_fails() { @@ -930,6 +942,29 @@ public class TableEndpointUnitTest extends AbstractUnitTest { generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, null, null, null); } + @Test + @WithMockUser(username = USER_4_USERNAME) + public void findById_privateSchemaNotOwnerNoAccess_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_4_PRINCIPAL, USER_4, null); + }); + } + + @Test + @WithMockUser(username = USER_4_USERNAME) + public void findById_publicSchemaNotOwnerNoAccess_succeeds() throws UserNotFoundException, TableNotFoundException, + NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, + QueueNotFoundException, DataServiceConnectionException { + + /* test */ + final ResponseEntity<TableDto> response = generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, USER_4_PRINCIPAL, USER_4, null); + assertEquals(HttpStatus.OK, response.getStatusCode()); + final TableDto body = response.getBody(); + assertNotNull(body); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") public void findById_privateHasRoleTableNotFound_fails() { @@ -970,7 +1005,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { /* test */ - generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL, USER_4, null); + generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL, USER_4, DATABASE_1_USER_4_READ_ACCESS); } @Test @@ -1081,6 +1116,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } + @Test + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system", "update-table-statistic"}) + public void updateStatistic_internalUser_succeeds() throws TableNotFoundException, SearchServiceException, + MalformedException, NotAllowedException, DataServiceException, DatabaseNotFoundException, + SearchServiceConnectionException, DataServiceConnectionException { + + /* test */ + final ResponseEntity<Void> response = generic_updateStatistic(USER_LOCAL_ADMIN_PRINCIPAL); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + } + /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -1148,7 +1194,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } protected ResponseEntity<TableBriefDto> generic_create(Long databaseId, Database database, CreateTableDto data, - Principal principal, User user, DatabaseAccess access) + Principal principal, User user, DatabaseAccess access) throws MalformedException, NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, @@ -1203,11 +1249,21 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .when(tableService) .findById(any(Database.class), eq(tableId)); } - if (principal != null) { + if (user != null) { when(userService.findById(user.getId())) .thenReturn(user); - when(accessService.find(any(Database.class), eq(user))) + } else { + doThrow(UserNotFoundException.class) + .when(userService) + .findById(any(UUID.class)); + } + if (access != null) { + when(accessService.find(any(Database.class), any(User.class))) .thenReturn(access); + } else { + doThrow(AccessNotFoundException.class) + .when(accessService) + .find(any(Database.class), any(User.class)); } /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java index 6ef4bd8779f08abaaa28d68e306e0a700eebd39b..de5c8993a118471b786710a72fbc8799499d4a82 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 @@ -1,5 +1,6 @@ package at.tuwien.endpoints; +import at.tuwien.api.auth.CreateUserDto; import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserDto; import at.tuwien.api.user.UserPasswordDto; @@ -19,6 +20,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.test.context.support.WithAnonymousUser; @@ -63,6 +65,15 @@ public class UserEndpointUnitTest extends AbstractUnitTest { assertEquals(2, response.size()); } + @Test + @WithAnonymousUser + public void findAll_filterInternalUserEmptyList_succeeds() throws UserNotFoundException { + + /* test */ + final List<UserBriefDto> response = findAll_generic(USER_LOCAL_ADMIN_USERNAME, null); + assertEquals(0, response.size()); + } + @Test @WithMockUser(username = USER_1_USERNAME) public void findAll_noRole_succeeds() throws UserNotFoundException { @@ -142,6 +153,18 @@ public class UserEndpointUnitTest extends AbstractUnitTest { assertEquals(USER_3_DATABASE_PASSWORD, response.getHeaders().get("X-Password").get(0)); } + @Test + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) + public void find_internalUser_fails() { + final Principal principal = new UsernamePasswordAuthenticationToken(USER_LOCAL_ADMIN_DETAILS, USER_LOCAL_ADMIN_PASSWORD, List.of( + new SimpleGrantedAuthority("system"))); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + find_generic(USER_LOCAL_ADMIN_ID, USER_LOCAL, principal); + }); + } + @Test @WithAnonymousUser public void modify_anonymous_fails() { @@ -233,7 +256,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) public void password_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, - UserNotFoundException, DatabaseNotFoundException { + UserNotFoundException, DatabaseNotFoundException, AuthServiceException { final UserPasswordDto request = UserPasswordDto.builder() .password(USER_1_PASSWORD) .build(); @@ -242,6 +265,38 @@ public class UserEndpointUnitTest extends AbstractUnitTest { password_generic(USER_1_PRINCIPAL, request); } + @Test + @WithAnonymousUser + public void create_anonymous_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + generic_create(USER_1_CREATE_USER_DTO); + }); + } + + @Test + @WithMockUser(username = USER_2_USERNAME) + public void create_notInternalUser_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + generic_create(USER_1_CREATE_USER_DTO); + }); + } + + @Test + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) + public void create_succeeds() { + + /* mock */ + when(userService.create(USER_1_CREATE_USER_DTO)) + .thenReturn(USER_1); + + /* test */ + generic_create(USER_1_CREATE_USER_DTO); + } + /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -260,7 +315,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } } else { when(userService.findAll()) - .thenReturn(List.of(USER_1, USER_2)); + .thenReturn(List.of(USER_1, USER_2, USER_LOCAL)); } /* test */ @@ -310,14 +365,15 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } protected void password_generic(Principal principal, UserPasswordDto data) throws NotAllowedException, - DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException { + DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + AuthServiceException { /* mock */ when(userService.findById(USER_1_ID)) .thenReturn(USER_1); doNothing() .when(authenticationService) - .updatePassword(USER_1, data); + .setupFinished(USER_1); doNothing() .when(userService) .updatePassword(USER_1, data); @@ -331,4 +387,13 @@ public class UserEndpointUnitTest extends AbstractUnitTest { final ResponseEntity<?> response = userEndpoint.password(USER_1_ID, data, principal); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } + + protected void generic_create(CreateUserDto data) { + + /* test */ + final ResponseEntity<UserBriefDto> response = userEndpoint.create(data); + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + final UserBriefDto body = response.getBody(); + assertNotNull(body); + } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java index e72cd7fa7591a7e641c74df6eab07845b0a193ea..58701adfc34f3d8c1be0b189a857307737bcfc47 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayIntegrationTest.java @@ -92,23 +92,4 @@ public class KeycloakGatewayIntegrationTest extends AbstractUnitTest { }); } - @Test - public void updateUserCredentials_succeeds() throws UserNotFoundException { - - /* mock */ - keycloakUtils.createUser(USER_1_ID, USER_1_KEYCLOAK_SIGNUP_REQUEST); - - /* test */ - keycloakGateway.updateUserCredentials(keycloakUtils.getUserId(USER_1_USERNAME), USER_1_PASSWORD_DTO); - } - - @Test - public void updateUserCredentials_notFound_fails() { - - /* test */ - assertThrows(UserNotFoundException.class, () -> { - keycloakGateway.updateUserCredentials(keycloakUtils.getUserId(USER_1_USERNAME), USER_1_PASSWORD_DTO); - }); - } - } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java index 9075ec2a02d0420b9fe0cec8c307a9dc8ac1c13e..a58a4b49da03358371c1346b16d893ac8b51bb8e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java @@ -1,12 +1,16 @@ package at.tuwien.handlers; +import at.tuwien.api.error.ApiErrorDto; +import at.tuwien.exception.*; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.bind.annotation.ResponseStatus; @@ -18,12 +22,17 @@ import java.util.Optional; import static at.tuwien.test.utils.EndpointUtils.getErrorCodes; import static at.tuwien.test.utils.EndpointUtils.getExceptions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest public class ApiExceptionHandlerTest extends AbstractUnitTest { + @Autowired + private ApiExceptionHandler apiExceptionHandler; + @Test public void handle_succeeds() throws ClassNotFoundException, IOException { final List<Method> handlers = Arrays.asList(ApiExceptionHandler.class.getMethods()); @@ -42,7 +51,903 @@ public class ApiExceptionHandlerTest extends AbstractUnitTest { Assertions.assertNotNull(exception.getDeclaredAnnotation(ResponseStatus.class).reason(), "Exception " + exception.getName() + " does not provide a reason code"); Assertions.assertTrue(errorCodes.contains(exception.getDeclaredAnnotation(ResponseStatus.class).reason()), "Exception code " + exception.getDeclaredAnnotation(ResponseStatus.class).reason() + " does have a reason code mapped in localized ui error messages"); /* handler method */ - Assertions.assertEquals(method.getDeclaredAnnotation(ResponseStatus.class).code(), exception.getDeclaredAnnotation(ResponseStatus.class).code()); + assertEquals(method.getDeclaredAnnotation(ResponseStatus.class).code(), exception.getDeclaredAnnotation(ResponseStatus.class).code()); } } + + @Test + public void handle_accessNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new AccessNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.access.missing", body.getCode()); + } + + + @Test + public void handle_accountNotSetupException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new AccountNotSetupException("msg")); + assertEquals(HttpStatus.PRECONDITION_REQUIRED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.PRECONDITION_REQUIRED, body.getStatus()); + assertEquals("error.user.setup", body.getCode()); + } + + + @Test + public void handle_analyseServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new AnalyseServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.analyse.invalid", body.getCode()); + } + + + @Test + public void handle_authServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new AuthServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.auth.connection", body.getCode()); + } + + + @Test + public void handle_authServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new AuthServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.auth.invalid", body.getCode()); + } + + + @Test + public void handle_brokerServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new BrokerServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.broker.connection", body.getCode()); + } + + + @Test + public void handle_brokerServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new BrokerServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.broker.invalid", body.getCode()); + } + + + @Test + public void handle_conceptNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ConceptNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.concept.missing", body.getCode()); + } + + + @Test + public void handle_containerAlreadyExistsException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ContainerAlreadyExistsException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.container.exists", body.getCode()); + } + + + @Test + public void handle_containerNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ContainerNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.container.missing", body.getCode()); + } + + + @Test + public void handle_containerQuotaException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ContainerQuotaException("msg")); + assertEquals(HttpStatus.LOCKED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.LOCKED, body.getStatus()); + assertEquals("error.container.quota", body.getCode()); + } + + + @Test + public void handle_credentialsInvalidException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new CredentialsInvalidException("msg")); + assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.FORBIDDEN, body.getStatus()); + assertEquals("error.user.credentials", body.getCode()); + } + + + @Test + public void handle_dataServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DataServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.data.connection", body.getCode()); + } + + + @Test + public void handle_dataServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DataServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.data.invalid", body.getCode()); + } + + + @Test + public void handle_databaseMalformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DatabaseMalformedException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.database.invalid", body.getCode()); + } + + + @Test + public void handle_databaseNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DatabaseNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.database.missing", body.getCode()); + } + + + @Test + public void handle_databaseUnavailableException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DatabaseUnavailableException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.database.connection", body.getCode()); + } + + + @Test + public void handle_doiNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new DoiNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.doi.missing", body.getCode()); + } + + + @Test + public void handle_emailExistsException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new EmailExistsException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.user.email-exists", body.getCode()); + } + + + @Test + public void handle_exchangeNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ExchangeNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.exchange.missing", body.getCode()); + } + + + @Test + public void handle_externalServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ExternalServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.external.invalid", body.getCode()); + } + + + @Test + public void handle_filterBadRequestException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new FilterBadRequestException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.semantic.filter", body.getCode()); + } + + + @Test + public void handle_formatNotAvailableException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new FormatNotAvailableException("msg")); + assertEquals(HttpStatus.NOT_ACCEPTABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_ACCEPTABLE, body.getStatus()); + assertEquals("error.identifier.format", body.getCode()); + } + + + @Test + public void handle_identifierNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new IdentifierNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.identifier.missing", body.getCode()); + } + + + @Test + public void handle_identifierNotSupportedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new IdentifierNotSupportedException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.identifier.unsupported", body.getCode()); + } + + + @Test + public void handle_imageAlreadyExistsException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ImageAlreadyExistsException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.image.exists", body.getCode()); + } + + + @Test + public void handle_imageInvalidException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ImageInvalidException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.image.invalid", body.getCode()); + } + + + @Test + public void handle_imageNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ImageNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.image.missing", body.getCode()); + } + + + @Test + public void handle_licenseNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new LicenseNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.license.missing", body.getCode()); + } + + + @Test + public void handle_malformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new MalformedException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.request.invalid", body.getCode()); + } + + + @Test + public void handle_messageNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new MessageNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.message.missing", body.getCode()); + } + + + @Test + public void handle_metadataServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new MetadataServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.metadata.connection", body.getCode()); + } + + + @Test + public void handle_metadataServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new MetadataServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.metadata.invalid", body.getCode()); + } + + + @Test + public void handle_notAllowedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new NotAllowedException("msg")); + assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.FORBIDDEN, body.getStatus()); + assertEquals("error.request.forbidden", body.getCode()); + } + + + @Test + public void handle_ontologyNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new OntologyNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.ontology.missing", body.getCode()); + } + + + @Test + public void handle_orcidNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new OrcidNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.orcid.missing", body.getCode()); + } + + + @Test + public void handle_paginationException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new PaginationException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.request.pagination", body.getCode()); + } + + + @Test + public void handle_queryMalformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryMalformedException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.query.invalid", body.getCode()); + } + + + @Test + public void handle_queryNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.query.missing", body.getCode()); + } + + + @Test + public void handle_queryNotSupportedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryNotSupportedException("msg")); + assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_IMPLEMENTED, body.getStatus()); + assertEquals("error.query.invalid", body.getCode()); + } + + + @Test + public void handle_queryStoreCreateException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryStoreCreateException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.store.invalid", body.getCode()); + } + + + @Test + public void handle_queryStoreGCException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryStoreGCException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.store.clean", body.getCode()); + } + + + @Test + public void handle_queryStoreInsertException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryStoreInsertException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.store.insert", body.getCode()); + } + + + @Test + public void handle_queryStorePersistException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueryStorePersistException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.store.persist", body.getCode()); + } + + + @Test + public void handle_queueNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new QueueNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.queue.missing", body.getCode()); + } + + + @Test + public void handle_remoteUnavailableException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new RemoteUnavailableException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.metadata.privileged", body.getCode()); + } + + + @Test + public void handle_rorNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new RorNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.ror.missing", body.getCode()); + } + + + @Test + public void handle_searchServiceConnectionException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new SearchServiceConnectionException("msg")); + assertEquals(HttpStatus.BAD_GATEWAY, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_GATEWAY, body.getStatus()); + assertEquals("error.search.connection", body.getCode()); + } + + + @Test + public void handle_searchServiceException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new SearchServiceException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.search.invalid", body.getCode()); + } + + + @Test + public void handle_semanticEntityNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new SemanticEntityNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.semantic.missing", body.getCode()); + } + + + @Test + public void handle_sortException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new SortException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.request.sort", body.getCode()); + } + + + @Test + public void handle_storageNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new StorageNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.storage.missing", body.getCode()); + } + + + @Test + public void handle_storageUnavailableException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new StorageUnavailableException("msg")); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.SERVICE_UNAVAILABLE, body.getStatus()); + assertEquals("error.storage.invalid", body.getCode()); + } + + + @Test + public void handle_tableExistsException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new TableExistsException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.table.exists", body.getCode()); + } + + + @Test + public void handle_tableMalformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new TableMalformedException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.table.invalid", body.getCode()); + } + + + @Test + public void handle_tableNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new TableNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.table.missing", body.getCode()); + } + + + @Test + public void handle_tableSchemaException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new TableSchemaException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.schema.table", body.getCode()); + } + + + @Test + public void handle_unitNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new UnitNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.unit.missing", body.getCode()); + } + + + @Test + public void handle_uriMalformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new UriMalformedException("msg")); + assertEquals(HttpStatus.EXPECTATION_FAILED, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.EXPECTATION_FAILED, body.getStatus()); + assertEquals("error.semantics.uri", body.getCode()); + } + + + @Test + public void handle_userExistsException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new UserExistsException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.user.exists", body.getCode()); + } + + + @Test + public void handle_userNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new UserNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.user.missing", body.getCode()); + } + + + @Test + public void handle_viewMalformedException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ViewMalformedException("msg")); + assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.BAD_REQUEST, body.getStatus()); + assertEquals("error.view.invalid", body.getCode()); + } + + + @Test + public void handle_viewNotFoundException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ViewNotFoundException("msg")); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.NOT_FOUND, body.getStatus()); + assertEquals("error.view.missing", body.getCode()); + } + + + @Test + public void handle_viewSchemaException_succeeds() { + + /* test */ + final ResponseEntity<ApiErrorDto> response = apiExceptionHandler.handle(new ViewSchemaException("msg")); + assertEquals(HttpStatus.CONFLICT, response.getStatusCode()); + final ApiErrorDto body = response.getBody(); + assertNotNull(body); + assertEquals("msg", body.getMessage()); + assertEquals(HttpStatus.CONFLICT, body.getStatus()); + assertEquals("error.schema.view", body.getCode()); + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..39aed0d28ea800574177821a252dbbfbde647db9 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java @@ -0,0 +1,85 @@ +package at.tuwien.service; + +import at.tuwien.entities.user.User; +import at.tuwien.exception.AuthServiceException; +import at.tuwien.exception.UserNotFoundException; +import at.tuwien.gateway.KeycloakGateway; +import at.tuwien.repository.UserRepository; +import at.tuwien.test.AbstractUnitTest; +import at.tuwien.utils.KeycloakUtils; +import dasniko.testcontainers.keycloak.KeycloakContainer; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@Log4j2 +@Testcontainers +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class UserServiceIntegrationTest extends AbstractUnitTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserService userService; + + @Autowired + private KeycloakUtils keycloakUtils; + + @BeforeEach + public void beforeEach() { + genesis(); + /* keycloak */ + userRepository.deleteAll(); + keycloakUtils.deleteUser(USER_1_USERNAME); + } + + @Container + private static KeycloakContainer keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE) + .withImagePullPolicy(PullPolicy.alwaysPull()) + .withAdminUsername("admin") + .withAdminPassword("admin") + .withRealmImportFile("./init/dbrepo-realm.json") + .withEnv("KC_HOSTNAME_STRICT_HTTPS", "false"); + + @DynamicPropertySource + static void keycloakProperties(DynamicPropertyRegistry registry) { + final String authServiceEndpoint = "http://localhost:" + keycloakContainer.getMappedPort(8080); + log.trace("set auth endpoint: {}", authServiceEndpoint); + registry.add("dbrepo.endpoints.authService", () -> authServiceEndpoint); + } + + @Test + public void create_succeeds() throws UserNotFoundException, AuthServiceException { + + /* test */ + final User response = userService.create(USER_1_CREATE_USER_DTO); + assertEquals(USER_1_ID, response.getId()); + assertEquals(USER_1_KEYCLOAK_ID, response.getKeycloakId()); + assertEquals(USER_1_USERNAME, response.getUsername()); + assertEquals(USER_1_THEME, response.getTheme()); + assertNotNull(response.getMariadbPassword()); + assertEquals(USER_1_LANGUAGE, response.getLanguage()); + assertEquals(USER_1_FIRSTNAME, response.getFirstname()); + assertEquals(USER_1_LASTNAME, response.getLastname()); + assertEquals(USER_1_IS_INTERNAL, response.getIsInternal()); + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java index 514d23b227dc3294741e2dcd212083f9ff23f619..eb228ab3c3c3f781a585fa199b63c7a512d222c3 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServicePersistenceTest.java @@ -42,7 +42,7 @@ public class UserServicePersistenceTest extends AbstractUnitTest { public void beforeEach() { genesis(); /* metadata database */ - userRepository.save(USER_1); + userRepository.saveAll(List.of(USER_1, USER_LOCAL)); } @Test @@ -54,6 +54,16 @@ public class UserServicePersistenceTest extends AbstractUnitTest { assertEquals(USER_1_USERNAME, response.getUsername()); } + @Test + public void findAllInternalUsers_succeeds() { + + /* test */ + final List<User> response = userService.findAllInternalUsers(); + assertEquals(1, response.size()); + final User user0 = response.get(0); + assertEquals(USER_LOCAL_ADMIN_ID, user0.getId()); + } + @Test public void findByUsername_fails() { @@ -68,7 +78,7 @@ public class UserServicePersistenceTest extends AbstractUnitTest { /* test */ final List<User> response = userService.findAll(); - assertEquals(1, response.size()); + assertEquals(2, response.size()); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java index 58d7cdc5e47f79cd45dd868d1b473a8051c79dce..df13d00b0858a28dd4ccc38c5542601790dc964a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java @@ -93,12 +93,12 @@ public class UserServiceUnitTest extends AbstractUnitTest { } @Test - public void updatePassword_succeeds() throws UserNotFoundException { + public void updatePassword_succeeds() throws UserNotFoundException, AuthServiceException { /* mock */ doNothing() .when(keycloakGateway) - .updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO); + .setupFinished(USER_1_ID); when(userRepository.findById(USER_1_ID)) .thenReturn(Optional.of(USER_1)); when(userRepository.save(any(User.class))) 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 486db28e5945737e776da4b8f0aaf6d6d977715e..8105a7fb8907b508a336876e9c5e6ce94916e59d 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 @@ -52,9 +52,27 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { public static Stream<Arguments> needSize_parameters() { return Stream.of( - Arguments.arguments(ColumnTypeDto.VARCHAR), - Arguments.arguments(ColumnTypeDto.BINARY), - Arguments.arguments(ColumnTypeDto.VARBINARY) + Arguments.arguments("varchar", ColumnTypeDto.VARCHAR), + Arguments.arguments("binary", ColumnTypeDto.BINARY), + Arguments.arguments("varbinary", ColumnTypeDto.VARBINARY) + ); + } + + public static Stream<Arguments> needSizeAndD_parameters() { + return Stream.of( + Arguments.arguments("double_size", ColumnTypeDto.DOUBLE, 40L, null), + Arguments.arguments("double_d", ColumnTypeDto.DOUBLE, null, 10L), + Arguments.arguments("decimal_size", ColumnTypeDto.DECIMAL, 40L, null), + Arguments.arguments("decimal_d", ColumnTypeDto.DECIMAL, null, 10L) + ); + } + + public static Stream<Arguments> enums_parameters() { + return Stream.of( + Arguments.arguments("enums_null", ColumnTypeDto.ENUM, null), + Arguments.arguments("enums_empty", ColumnTypeDto.ENUM, List.of()), + Arguments.arguments("sets_null", ColumnTypeDto.SET, null), + Arguments.arguments("sets_empty", ColumnTypeDto.SET, List.of()) ); } @@ -244,6 +262,20 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(TABLE_1, USER_1); } + @Test + public void validateOnlyWriteOwnOrWriteAllAccess_writeOwnAccess_succeeds() throws DatabaseNotFoundException, + TableNotFoundException, AccessNotFoundException, NotAllowedException { + + /* mock */ + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + when(accessService.find(eq(DATABASE_1), any(User.class))) + .thenReturn(DATABASE_1_USER_1_WRITE_OWN_ACCESS); + + /* test */ + endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(TABLE_1, USER_1); + } + @Test public void validateOnlyWriteOwnOrWriteAllAccess_privateHasReadAccess_fails() throws DatabaseNotFoundException, TableNotFoundException, AccessNotFoundException { @@ -285,7 +317,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { @ParameterizedTest @MethodSource("needSize_parameters") - public void validateColumnCreateConstraints_needSize_fails(ColumnTypeDto type) { + public void validateColumnCreateConstraints_needSize_fails(String name, ColumnTypeDto type) { final CreateTableDto request = CreateTableDto.builder() .columns(List.of(CreateTableColumnDto.builder() .type(type) @@ -299,12 +331,13 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { }); } - @Test - public void validateColumnCreateConstraints_needEnum_fails() { + @ParameterizedTest + @MethodSource("enums_parameters") + public void validateColumnCreateConstraints_needEnum_fails(String name, ColumnTypeDto type, List<String> enums) { final CreateTableDto request = CreateTableDto.builder() .columns(List.of(CreateTableColumnDto.builder() - .type(ColumnTypeDto.ENUM) - .enums(null) // <<<<<<< + .type(type) + .enums(enums) .build())) .build(); @@ -314,12 +347,14 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { }); } - @Test - public void validateColumnCreateConstraints_needSet_fails() { + @ParameterizedTest + @MethodSource("needSizeAndD_parameters") + public void validateColumnCreateConstraints_needSizeAndD_fails(String name, ColumnTypeDto type, Long size, Long d) { final CreateTableDto request = CreateTableDto.builder() .columns(List.of(CreateTableColumnDto.builder() - .type(ColumnTypeDto.SET) - .sets(null) // <<<<<<< + .type(type) + .size(size) + .d(d) .build())) .build(); @@ -345,6 +380,34 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { }); } + @Test + public void validateOnlyOwnerOrWriteAll_writeOwnAccess_succeeds() throws DatabaseNotFoundException, + TableNotFoundException, AccessNotFoundException, NotAllowedException { + + /* mock */ + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + when(accessService.find(DATABASE_1, USER_1)) + .thenReturn(DATABASE_1_USER_1_WRITE_OWN_ACCESS); + + /* test */ + endpointValidator.validateOnlyOwnerOrWriteAll(TABLE_1, USER_1); + } + + @Test + public void validateOnlyOwnerOrWriteAll_writeAllAccess_succeeds() throws DatabaseNotFoundException, + TableNotFoundException, AccessNotFoundException, NotAllowedException { + + /* mock */ + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + when(accessService.find(DATABASE_1, USER_2)) + .thenReturn(DATABASE_1_USER_2_WRITE_ALL_ACCESS); + + /* test */ + endpointValidator.validateOnlyOwnerOrWriteAll(TABLE_1, USER_2); + } + @Test public void validateOnlyPrivateDataHasRole_publicDatabase_succeeds() throws NotAllowedException { @@ -555,6 +618,13 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { assertTrue(endpointValidator.validateOnlyMineOrWriteAccessOrHasRole(USER_1, USER_1_PRINCIPAL, DATABASE_1_USER_1_WRITE_OWN_ACCESS, "nobody-role")); } + @Test + public void validateOnlyMineOrWriteAccessOrHasRole_ownerOnlyWriteAll_succeeds() { + + /* test */ + assertTrue(endpointValidator.validateOnlyMineOrWriteAccessOrHasRole(USER_1, USER_1_PRINCIPAL, DATABASE_1_USER_1_WRITE_ALL_ACCESS, "nobody-role")); + } + @Test public void validateOnlyMineOrWriteAccessOrHasRole_notOwnerOnlyWriteOwn_fails() { diff --git a/dbrepo-metadata-service/services/pom.xml b/dbrepo-metadata-service/services/pom.xml index 906fa5258b02807565c4acc0e361d5c65bd65b77..e918d3ae24adf706455b8ca7767b166198f5028f 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-services</artifactId> <name>dbrepo-metadata-service-services</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java index cd5fd08a7ef64e88134a1fc19aa0840ad1e98020..296457b3d8ba1cd6e14e8a46be85a217b9cb8e13 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -1,7 +1,6 @@ package at.tuwien.gateway; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserPasswordDto; import at.tuwien.api.user.UserUpdateDto; import at.tuwien.exception.AuthServiceException; import at.tuwien.exception.UserNotFoundException; @@ -22,13 +21,7 @@ public interface KeycloakGateway { */ void deleteUser(UUID id) throws UserNotFoundException; - /** - * Update the credentials for a given user. - * - * @param id The user id. - * @param password The user credential. - */ - void updateUserCredentials(UUID id, UserPasswordDto password) throws UserNotFoundException; + void setupFinished(UUID id) throws AuthServiceException, UserNotFoundException; void updateUser(UUID id, UserUpdateDto data) throws AuthServiceException, UserNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index af54651d6c36197e136134003291ea88f5df2a49..270653ee8ffade88a9b96c24e2650843b21c5dd5 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -1,14 +1,12 @@ package at.tuwien.gateway.impl; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserPasswordDto; import at.tuwien.api.user.UserUpdateDto; import at.tuwien.config.KeycloakConfig; import at.tuwien.exception.AuthServiceException; import at.tuwien.exception.UserNotFoundException; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.mapper.MetadataMapper; -import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.ForbiddenException; import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.core.Response; @@ -17,7 +15,6 @@ import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.KeycloakBuilder; import org.keycloak.admin.client.resource.UserResource; -import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.springframework.stereotype.Service; @@ -80,21 +77,25 @@ public class KeycloakGatewayImpl implements KeycloakGateway { } @Override - public void updateUserCredentials(UUID id, UserPasswordDto data) throws UserNotFoundException { - final CredentialRepresentation credential = new CredentialRepresentation(); - credential.setTemporary(false); - credential.setValue(data.getPassword()); - credential.setType(CredentialRepresentation.PASSWORD); + public void setupFinished(UUID id) throws AuthServiceException, UserNotFoundException { + final UserResource resource = keycloak.realm(keycloakConfig.getRealm()) + .users() + .get(String.valueOf(id)); + final UserRepresentation user; try { - keycloak.realm(keycloakConfig.getRealm()) - .users() - .get(String.valueOf(id)) - .resetPassword(credential); + user = resource.toRepresentation(); } catch (NotFoundException e) { - log.error("Failed to update user password: not found"); - throw new UserNotFoundException("Failed to update user password: not found", e); + log.error("Failed to update user setup: not found: {}", e.getMessage()); + throw new UserNotFoundException("Failed to update user setup: not found", e); + } + user.singleAttribute("SETUP_FINISHED", "true"); + try { + resource.update(user); + } catch (ForbiddenException e) { + log.error("Failed to update user setup: forbidden: {}", e.getMessage()); + throw new AuthServiceException("Failed to update user setup: forbidden", e); } - log.info("Updated user {} password at auth service", id); + log.info("Updated user {} setup at auth service", id); } @Override @@ -102,7 +103,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { final UserResource resource = keycloak.realm(keycloakConfig.getRealm()) .users() .get(String.valueOf(id)); - UserRepresentation user; + final UserRepresentation user; try { user = resource.toRepresentation(); } catch (NotFoundException e) { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java index 75b647bf954fd638dfde8ffa8b7f650d03ce7c49..3abe07a10a16b7b72ec144d6ddeb7ee32cd599b6 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AuthenticationService.java @@ -1,6 +1,5 @@ package at.tuwien.service; -import at.tuwien.api.user.UserPasswordDto; import at.tuwien.entities.user.User; import at.tuwien.exception.AuthServiceConnectionException; import at.tuwien.exception.AuthServiceException; @@ -23,8 +22,7 @@ public interface AuthenticationService { * Updates the password of a user with given id. * * @param user The user. - * @param data The new password. * @throws UserNotFoundException The user was not found after creation in the auth database. */ - void updatePassword(User user, UserPasswordDto data) throws UserNotFoundException; + void setupFinished(User user) throws UserNotFoundException, AuthServiceException; } 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 581641a93ab95927d63c5b4a5f6b069eb6f270b7..c6ca0ff21eb02986f30d42ec0b8727b368d5bfe4 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 @@ -4,7 +4,6 @@ import at.tuwien.api.auth.CreateUserDto; import at.tuwien.api.user.UserPasswordDto; import at.tuwien.api.user.UserUpdateDto; import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceConnectionException; import at.tuwien.exception.AuthServiceException; import at.tuwien.exception.UserExistsException; import at.tuwien.exception.UserNotFoundException; @@ -47,7 +46,7 @@ public interface UserService { * @param data The user data. * @return The user, if successful. */ - User create(CreateUserDto data) throws UserNotFoundException, AuthServiceException; + User create(CreateUserDto data); /** * Updates the user information for a user with given id in the metadata database. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java index 1159913039ef59227758006f28d678db99329386..dec3577886de7e4e0b60b015f72f73099a441065 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AuthenticationServiceImpl.java @@ -1,10 +1,7 @@ package at.tuwien.service.impl; -import at.tuwien.api.user.UserPasswordDto; import at.tuwien.entities.user.User; -import at.tuwien.exception.AuthServiceConnectionException; import at.tuwien.exception.AuthServiceException; -import at.tuwien.exception.CredentialsInvalidException; import at.tuwien.exception.UserNotFoundException; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.service.AuthenticationService; @@ -29,8 +26,8 @@ public class AuthenticationServiceImpl implements AuthenticationService { } @Override - public void updatePassword(User user, UserPasswordDto data) throws UserNotFoundException { - keycloakGateway.updateUserCredentials(user.getKeycloakId(), data); + public void setupFinished(User user) throws AuthServiceException, UserNotFoundException { + keycloakGateway.setupFinished(user.getKeycloakId()); } } 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 1d582bb9752a0cecd6885c72ba5de19d5cb78887..e79dd9bd842ac4cbb145f3b86f533962c23e2625 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 @@ -65,14 +65,14 @@ public class UserServiceImpl implements UserService { } @Override - public User create(CreateUserDto data) throws UserNotFoundException, AuthServiceException { + public User create(CreateUserDto data) { /* create at authentication service */ final User entity = User.builder() .id(data.getLdapId()) .keycloakId(data.getId()) .username(data.getUsername()) .theme("light") - .mariadbPassword(getMariaDbPassword(RandomStringUtils.randomAlphabetic(10))) /* user needs to set it later to access */ + .mariadbPassword(getMariaDbPassword(RandomStringUtils.randomAlphabetic(10))) .language("en") .firstname(data.getGivenName()) .lastname(data.getFamilyName()) diff --git a/dbrepo-metadata-service/test/pom.xml b/dbrepo-metadata-service/test/pom.xml index 792523227eaa968b3dd8c340779bece2323cb461..4aa6188f9fa7b26d9181a1cdc42a0ee00bce3b39 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.7.0</version> + <version>1.6.4</version> </parent> <artifactId>dbrepo-metadata-service-test</artifactId> <name>dbrepo-metadata-service-test</name> - <version>1.7.0</version> + <version>1.6.4</version> <dependencies> <dependency> 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 bccf903b8befe7ceec1915f10a49ff0fdb0e35c0..860eeb8253c18a58d19ac6c61d8017382399875a 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 @@ -5,6 +5,7 @@ import at.tuwien.api.amqp.CreateVirtualHostDto; import at.tuwien.api.amqp.ExchangeDto; import at.tuwien.api.amqp.GrantVirtualHostPermissionsDto; import at.tuwien.api.amqp.QueueDto; +import at.tuwien.api.auth.CreateUserDto; import at.tuwien.api.auth.LoginRequestDto; import at.tuwien.api.auth.RefreshTokenRequestDto; import at.tuwien.api.container.ContainerBriefDto; @@ -478,8 +479,6 @@ public abstract class BaseTest { @SuppressWarnings("java:S2068") public final static String USER_1_PASSWORD = "junit1"; @SuppressWarnings("java:S2068") - public final static String USER_1_PASSWORD_ENCODED = "$2a$10$0dtdedA/RLTrFbUsvpbUw.I73AXOKeQP3t5UXj96OvnDEaDb3d3M6"; - @SuppressWarnings("java:S2068") 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"; @@ -487,18 +486,11 @@ public abstract class BaseTest { public final static String USER_1_NAME = "John Doe"; public final static String USER_1_AFFILIATION = "TU Graz"; public final static String USER_1_ORCID_URL = "https://orcid.org/0000-0003-4216-302X"; - public final static 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) */; - public final static Instant USER_1_LAST_MODIFIED = USER_1_CREATED; - public final static UUID USER_1_REALM_ID = REALM_DBREPO_ID; public final static UpdateUserPasswordDto USER_1_UPDATE_PASSWORD_DTO = UpdateUserPasswordDto.builder() .username(USER_1_USERNAME) @@ -568,6 +560,14 @@ public abstract class BaseTest { .qualifiedName(USER_1_QUALIFIED_NAME) .build(); + public final static CreateUserDto USER_1_CREATE_USER_DTO = CreateUserDto.builder() + .id(USER_1_KEYCLOAK_ID) + .ldapId(USER_1_ID) + .givenName(USER_1_FIRSTNAME) + .familyName(USER_1_LASTNAME) + .username(USER_1_USERNAME) + .build(); + public final static UserUpdateDto USER_1_UPDATE_DTO = UserUpdateDto.builder() .firstname(USER_1_FIRSTNAME) .lastname(USER_1_LASTNAME) @@ -608,7 +608,6 @@ public abstract class BaseTest { public final static UUID USER_2_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); public final static UUID USER_2_KEYCLOAK_ID = UUID.fromString("eeb9a51b-4cd8-4039-90bf-e24f17372f7c"); - public final static String USER_2_EMAIL = "jane.doe@example.com"; public final static String USER_2_USERNAME = "junit2"; public final static String USER_2_FIRSTNAME = "Jane"; public final static String USER_2_LASTNAME = "Doe"; @@ -620,16 +619,9 @@ public abstract class BaseTest { @SuppressWarnings("java:S2068") public final static String USER_2_DATABASE_PASSWORD = "*9AA70A8B0EEFAFCB5BED5BDEF6EE264D5DA915AE" /* junit2 */; public final static String USER_2_QUALIFIED_NAME = USER_2_FIRSTNAME + " " + USER_2_LASTNAME + " — @" + USER_2_USERNAME; - public final static Boolean USER_2_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) */; - public final static Instant USER_2_LAST_MODIFIED = USER_1_CREATED; - public final static UUID USER_2_REALM_ID = REALM_DBREPO_ID; public final static UserAttributesDto USER_2_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_2_THEME) @@ -697,20 +689,13 @@ public abstract class BaseTest { public final static String USER_3_AFFILIATION = "TU Wien"; public final static String USER_3_ORCID_URL = null; public final static String USER_3_ORCID_UNCOMPRESSED = null; - public final static String USER_3_EMAIL = "system@example.com"; @SuppressWarnings("java:S2068") 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_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; public final static UserAttributesDto USER_3_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_3_THEME) @@ -779,12 +764,8 @@ public abstract class BaseTest { @SuppressWarnings("java:S2068") public final static String USER_4_DATABASE_PASSWORD = "*C20EF5C6875857DEFA9BE6E9B62DD76AAAE51882" /* junit4 */; public final static String USER_4_QUALIFIED_NAME = USER_4_FIRSTNAME + " " + USER_4_LASTNAME + " — @" + USER_4_USERNAME; - public final static Boolean USER_4_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; public final static UserAttributesDto USER_4_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_4_THEME) @@ -842,18 +823,13 @@ public abstract class BaseTest { 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_FIRSTNAME + " " + USER_5_LASTNAME + " — @" + USER_5_USERNAME; - 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; public final static UserAttributesDto USER_5_ATTRIBUTES_DTO = UserAttributesDto.builder() .theme(USER_5_THEME) @@ -7680,6 +7656,21 @@ public abstract class BaseTest { .user(USER_3_BRIEF_DTO) .build(); + public final static DatabaseAccess DATABASE_1_USER_4_READ_ACCESS = DatabaseAccess.builder() + .type(AccessType.READ) + .hdbid(DATABASE_1_ID) + .database(DATABASE_1) + .huserid(USER_4_ID) + .user(USER_4) + .build(); + + public final static DatabaseAccessDto DATABASE_1_USER_4_READ_ACCESS_DTO = DatabaseAccessDto.builder() + .type(AccessTypeDto.READ) + .hdbid(DATABASE_1_ID) + .huserid(USER_4_ID) + .user(USER_4_BRIEF_DTO) + .build(); + public final static Database DATABASE_2 = Database.builder() .id(DATABASE_2_ID) .created(DATABASE_2_CREATED) diff --git a/dbrepo-search-service/Pipfile b/dbrepo-search-service/Pipfile index 6284708cc1d7f99f10843ad47c05b35a25916bf4..4e3f9968022e35187cec3fbe92fdc33e70898ab8 100644 --- a/dbrepo-search-service/Pipfile +++ b/dbrepo-search-service/Pipfile @@ -18,7 +18,7 @@ jwt = "~=1.3" testcontainers-opensearch = "*" pytest = "*" rdflib = "*" -dbrepo = {path = "./lib/dbrepo-1.7.0.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.6.4.tar.gz"} gunicorn = "*" [dev-packages] diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index 4fc5ec3cab2dcfb47e52f6804e9888da37a42055..87013913cdcee8520ff2760de0e16e81d0082d3c 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "30aa6fefdbdbb9f57d58ebc8660eee64445a831cea44c6ca1fa605f2a2e1adc3" + "sha256": "c22580f5873b7bd3fc1edb71c84b7269ae79da6a2554225fe8d95cab6af9f14d" }, "pipfile-spec": 6, "requires": { @@ -369,9 +369,9 @@ }, "dbrepo": { "hashes": [ - "sha256:f25d5adbd618bf2906578e671af2bf3bcc24d738ef8bc791c220e7e5b714e2f7" + "sha256:a518aee79540d9e302b161e7e10072f50730489da19368f00a1e68204009ce44" ], - "path": "./lib/dbrepo-1.7.0.tar.gz" + "path": "./lib/dbrepo-1.6.4.tar.gz" }, "docker": { "hashes": [ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.4-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.6.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d083b0bafc937528fdcc09634c41132578cbf345 Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.6.4-py3-none-any.whl differ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.4.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.6.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..87e9a503ebc621238ebe7efca15f2bdf0a6e1a85 Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.6.4.tar.gz differ diff --git a/dbrepo-search-service/lib/dbrepo-1.6.4-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.6.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d083b0bafc937528fdcc09634c41132578cbf345 Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.6.4-py3-none-any.whl differ diff --git a/dbrepo-search-service/lib/dbrepo-1.6.4.tar.gz b/dbrepo-search-service/lib/dbrepo-1.6.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..87e9a503ebc621238ebe7efca15f2bdf0a6e1a85 Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.6.4.tar.gz differ diff --git a/dbrepo-ui/composables/authentication-service.ts b/dbrepo-ui/composables/authentication-service.ts deleted file mode 100644 index 39f6cc5a3fc843bd8db07c22b0f94a2ea2d7a93a..0000000000000000000000000000000000000000 --- a/dbrepo-ui/composables/authentication-service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {jwtDecode} from 'jwt-decode' - -export const useAuthenticationService = (): any => { - - function isExpiredToken(token: string): boolean { - if (!token) { - return false - } - return tokenToExpiryDate(token) < Date.now() - } - - function tokenToExpiryDate(token: string): number { - if (!token) { - return -1 - } - const exp: number = jwtDecode<Token>(token).exp - if (exp) { - return exp * 1000 - } - return -1 - } - - return {isExpiredToken, tokenToExpiryDate} -} diff --git a/dbrepo-ui/composables/axios-instance.ts b/dbrepo-ui/composables/axios-instance.ts index ca7a7b111cf70cf92524f5459808277e4b14144e..cd3737f2bfad4bbd40d15f6cb5cf334a73d0c334 100644 --- a/dbrepo-ui/composables/axios-instance.ts +++ b/dbrepo-ui/composables/axios-instance.ts @@ -16,7 +16,7 @@ export const useAxiosInstance = () => { baseURL: config.public.api.client }); instance.interceptors.request.use((config) => { - const { loggedIn, user, login, logout } = useOidcAuth() + const { loggedIn, user } = useOidcAuth() if (!loggedIn) { return config } diff --git a/dbrepo-ui/composables/user-service.ts b/dbrepo-ui/composables/user-service.ts index 3425dbaa5c7d77d927798914b8a4fdac6123c166..b90ee34033fb773418a16b1f9ffc9afdbfcc1f4c 100644 --- a/dbrepo-ui/composables/user-service.ts +++ b/dbrepo-ui/composables/user-service.ts @@ -1,5 +1,3 @@ -import {jwtDecode} from 'jwt-decode' -import axios from 'axios' import {axiosErrorToApiError} from '@/utils' export const useUserService = (): any => { @@ -80,36 +78,6 @@ export const useUserService = (): any => { }) } - async function refreshToken(refreshToken: string): Promise<KeycloakOpenIdTokenDto> { - console.debug('refresh user token') - return new Promise<KeycloakOpenIdTokenDto>((resolve, reject) => { - const config = useRuntimeConfig() - const instance = axios.create({ - timeout: 90_000, - params: {}, - baseURL: config.public.api.client - }) - instance.put<KeycloakOpenIdTokenDto>('/api/user/token', {refresh_token: refreshToken}) - .then((response) => { - console.info('Refreshed user token') - const userStore = useUserStore() - // eslint-disable-next-line camelcase - const {access_token, refresh_token} = response.data - userStore.setToken(access_token) - userStore.setRefreshToken(refresh_token) - resolve(response.data) - }).catch((error) => { - console.error('Failed to refresh user token', error) - reject(axiosErrorToApiError(error)) - }) - }) - } - - function tokenToRoles(token: string): string[] { - const data: Token = jwtDecode<Token>(token) - return data.realm_access.roles || [] - } - function nameIdentifierToNameIdentifierScheme(nameIdentifier: string) { if (nameIdentifier.includes('orcid.org')) { return 'ORCID' diff --git a/dbrepo-ui/layouts/default.vue b/dbrepo-ui/layouts/default.vue index a26c6d2539c86a240a3f4f45818e2780915aff9f..85d530e74daf40dcf3deb47bae5adca762ef99c2 100644 --- a/dbrepo-ui/layouts/default.vue +++ b/dbrepo-ui/layouts/default.vue @@ -141,12 +141,30 @@ </v-form> <v-main> <v-container> - <slot /> + <div + v-cloak> + <v-alert + v-if="isNotFinishedAccountSetup" + border="start" + color="info" + class="mb-4"> + {{ $t('pages.settings.subpages.authentication.setup.text') }} + <v-btn + variant="flat" + size="small" + to="/user/authentication"> + {{ $t('pages.settings.subpages.authentication.setup.action') }} + </v-btn> + . + </v-alert> + </div> <JumboBox v-if="error" :title="$t(errorCodeKey(error).title, { resource })" :subtitle="$t(errorCodeKey(error).subtitle)" :text="$t(errorCodeKey(error).text, { resource })" /> + <slot + v-else /> </v-container> </v-main> </v-app> @@ -251,6 +269,15 @@ export default { commitShort () { return this.$config.public.commit.substr(0, 8) }, + isNotFinishedAccountSetup () { + if (!this.cacheUser) { + return false + } + if (!('setup_finished' in this.cacheUser)) { + return true + } + return this.cacheUser.setup_finished === false + }, error () { if (this.identifier) { return null diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 07ac0163ef086dd1915d90daf5cf7aabc59695d4..d17da2341db70b270a9cf780773ea7900afa4c03 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -794,11 +794,11 @@ }, "firstname": { "label": "Given Name", - "hint": "" + "hint": "Managed by your identity provider: {provider}" }, "lastname": { "label": "Family Name", - "hint": "" + "hint": "Managed by your identity provider: {provider}" }, "affiliation": { "label": "Affiliation Identifier", @@ -834,8 +834,12 @@ "settings": { "subpages": { "authentication": { - "title": "User Password", - "subtitle": "Update the user password used for basic authentication with all interfaces", + "title": "API Password", + "subtitle": "Update the user password used for authentication with all interfaces (e.g. HTTP API, AMQP API, MQTT API)", + "setup": { + "text": "Finish your account setup by setting the", + "action": "API Password" + }, "password": { "label": "Password", "hint": "Required" diff --git a/dbrepo-ui/pages/user/authentication.vue b/dbrepo-ui/pages/user/authentication.vue index 50008d3c5dab56111fb15ae7a6164e1a591af1f9..912c1878c4940556e1dae3e890e4087ca7af5984 100644 --- a/dbrepo-ui/pages/user/authentication.vue +++ b/dbrepo-ui/pages/user/authentication.vue @@ -61,7 +61,7 @@ </template> <script setup> -const { loggedIn } = useOidcAuth() +const { loggedIn, user } = useOidcAuth() </script> <script> import UserToolbar from '@/components/user/UserToolbar.vue' @@ -113,11 +113,20 @@ export default { const userService = useUserService() userService.updatePassword(this.cacheUser.uid, {'password': this.password}) .then(() => { + const user = Object.assign({}, this.cacheUser) + user.setup_finished = true + this.cacheStore.setUser(user) + // fixme [mweise]: currently nuxt-oidc-auth cannot refresh the session correctly const toast = useToastInstance() toast.success(this.$t('success.user.password')) this.loadingUpdate = false }) - .catch(() => { + .catch(({code, message}) => { + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(message) this.loadingUpdate = false }) .finally(() => { diff --git a/dbrepo-ui/pages/user/info.vue b/dbrepo-ui/pages/user/info.vue index 8674c57e2d15abb0be7a50182f2681d5e0f6526e..9c8dbf873d5b7ec4c13a4cde7a42a61790fdc4a3 100644 --- a/dbrepo-ui/pages/user/info.vue +++ b/dbrepo-ui/pages/user/info.vue @@ -74,24 +74,24 @@ <v-col md="6"> <v-text-field v-model="model.firstname" - :disabled="!canModifyInformation" + :disabled="!canModifyInformation || identityProvider" clearable persistent-hint :variant="inputVariant" :label="$t('pages.user.subpages.info.firstname.label')" - :hint="$t('pages.user.subpages.info.firstname.hint')" /> + :hint="identityProvider ? $t('pages.user.subpages.info.firstname.hint', { provider: identityProvider }) : ''" /> </v-col> </v-row> <v-row dense> <v-col md="6"> <v-text-field v-model="model.lastname" - :disabled="!canModifyInformation" + :disabled="!canModifyInformation || identityProvider" clearable persistent-hint :variant="inputVariant" :label="$t('pages.user.subpages.info.lastname.label')" - :hint="$t('pages.user.subpages.info.lastname.hint')" /> + :hint="identityProvider ? $t('pages.user.subpages.info.lastname.hint', { provider: identityProvider }) : ''" /> </v-col> </v-row> <v-row dense> @@ -191,6 +191,12 @@ export default { cacheUser () { return this.cacheStore.getUser }, + identityProvider () { + if (!this.cacheUser || !('identity_provider' in this.cacheUser)) { + return false + } + return this.cacheUser.identity_provider + }, canModifyInformation () { if (!this.roles) { return false diff --git a/dbrepo-upload-service/pom.xml b/dbrepo-upload-service/pom.xml index 9a5531c0be3e149d22d69f8271fa323a0c7826c5..7e4f27586e27b6a76a5ccd9fccd7f4e1d34b8542 100644 --- a/dbrepo-upload-service/pom.xml +++ b/dbrepo-upload-service/pom.xml @@ -11,7 +11,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-upload-service</artifactId> <name>dbrepo-upload-service</name> - <version>1.7.0</version> + <version>1.6.4</version> <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/</url> <developers> diff --git a/docker-compose.yml b/docker-compose.yml index 9176f6404a06df5e30269f4a0dde4d8e4483ebd8..94b5fc30a61c1081e194fd4eb98c45d7af9b261c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -96,7 +96,7 @@ services: KEYCLOAK_DATABASE_NAME: "${AUTH_DB_NAME:-keycloak}" KEYCLOAK_DATABASE_USER: "${AUTH_DB_USERNAME:-keycloak}" KEYCLOAK_DATABASE_PASSWORD: "${AUTH_DB_PASSWORD:-dbrepo}" - METADATA_SERVICE_ENDPOINT: "${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080}/api/user" + METADATA_SERVICE_ENDPOINT: "${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080}" SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: diff --git a/helm/dbrepo/Chart.yaml b/helm/dbrepo/Chart.yaml index b6fa24359ad19fba6595c53a2f64b7f0472d7ff3..9418fa7c6628c3b26154d460bdf02404114dabf8 100644 --- a/helm/dbrepo/Chart.yaml +++ b/helm/dbrepo/Chart.yaml @@ -7,14 +7,14 @@ description: Helm Chart for installing DBRepo sources: - https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services type: application -version: "1.7.0" -appVersion: "1.7.0" +version: "1.6.4" +appVersion: "1.6.4" keywords: - dbrepo maintainers: - name: Martin Weise email: martin.weise@tuwien.ac.at -home: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ +home: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/ icon: https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/dbrepo-ui/public/favicon.png dependencies: - name: opensearch diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index 086b635a63f8e25fc78a25b54315f838ae4097f9..88051e6035586bdc5f27ff4c6c78a4d33e041671 100644 --- a/helm/dbrepo/README.md +++ b/helm/dbrepo/README.md @@ -1,17 +1,17 @@ # DBRepo Helm chart -[DBRepo](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/) is a database repository system that +[DBRepo](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/) is a database repository system that allows researchers to ingest data into a central, versioned repository through common interfaces. ## TL;DR Download the sample [ -`values.yaml`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-1.7/helm-charts/dbrepo/values.yaml?inline=true) +`values.yaml`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-1.6/helm-charts/dbrepo/values.yaml?inline=true) for your deployment and update the variables, especially `hostname`. ```bash -helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" --values ./values.yaml --version "1.7.0" +helm install my-release "oci://registry.datalab.tuwien.ac.at/dbrepo/helm/dbrepo" --values ./values.yaml --version "1.6.4" ``` ## 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.7.0" +helm install my-release "oci://oci://registry.datalab.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.6.4" ``` The command deploys DBRepo on the Kubernetes cluster in the default configuration. The Parameters section lists the @@ -68,7 +68,7 @@ The command removes all the Kubernetes components associated with the chart and | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | `metadatadb.enabled` | Enable the Metadata datadb. | `true` | | `metadatadb.host` | The hostname for the microservices. | `metadata-db` | -| `metadatadb.extraFlags` | Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/data-db/#data | `--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci` | +| `metadatadb.extraFlags` | Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/data-db/#data | `--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci` | | `metadatadb.rootUser.user` | The root username. | `root` | | `metadatadb.rootUser.password` | The root user password. | `dbrepo` | | `metadatadb.db.name` | The database name. | `dbrepo` | @@ -101,7 +101,7 @@ The command removes all the Kubernetes components associated with the chart and | Name | Description | Value | | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | `datadb.host` | The hostname for the microservices. | `data-db` | -| `datadb.extraFlags` | Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/data-db/#data | `--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci` | +| `datadb.extraFlags` | Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/data-db/#data | `--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci` | | `datadb.rootUser.user` | The root username. | `root` | | `datadb.rootUser.password` | The root user password. | `dbrepo` | | `datadb.db.name` | The database name. | `dbrepo` | diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index a23243d39509ec3821219e5799a25740c93e2ca1..a970096eeaa5015d9e95064f6b341fffdf8aae5f 100644 Binary files a/helm/dbrepo/files/create-event-listener.jar and b/helm/dbrepo/files/create-event-listener.jar differ diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index 18a0ec69c78cc56f559c56d8c95a63e1c42ab619..d5260781df5e8e68484bf939e5b254e55b7365af 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -33,7 +33,7 @@ metadatadb: fullnameOverride: metadata-db ## @param metadatadb.host The hostname for the microservices. host: metadata-db - ## @param metadatadb.extraFlags Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/data-db/#data + ## @param metadatadb.extraFlags Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/data-db/#data extraFlags: "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci" rootUser: ## @param metadatadb.rootUser.user The root username. @@ -118,7 +118,7 @@ authservice: setupJob: image: ## @skip authservice.setupJob.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/auth-service-init:1.6.4 ## @param authservice.setupJob.resourcesPreset The container resource preset resourcesPreset: "nano" ## @param authservice.setupJob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) @@ -162,7 +162,7 @@ datadb: fullnameOverride: data-db ## @param datadb.host The hostname for the microservices. host: data-db - ## @param datadb.extraFlags Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/data-db/#data + ## @param datadb.extraFlags Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/data-db/#data extraFlags: "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci" rootUser: ## @param datadb.rootUser.user The root username. @@ -401,7 +401,7 @@ analyseservice: enabled: true image: ## @skip analyseservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.4 ## 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 @@ -462,7 +462,7 @@ metadataservice: enabled: true image: ## @skip metadataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.4 ## 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 @@ -559,7 +559,7 @@ dataservice: endpoint: http://data-service image: ## @skip dataservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.4 ## 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 @@ -645,7 +645,7 @@ searchservice: endpoint: http://search-service image: ## @skip searchservice.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.4 ## 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 @@ -692,7 +692,7 @@ searchservice: init: image: ## @skip searchservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.4 ## @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) @@ -753,7 +753,7 @@ storageservice: init: image: ## @skip storageservice.init.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.4 s3: ## @param storageservice.init.s3.endpoint The S3-capable endpoint the microservice connects to. endpoint: http://storage-service-s3:8333 @@ -862,7 +862,7 @@ ui: enabled: true image: ## @skip ui.image.name - name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.7.0 + name: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.4 ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod podSecurityContext: ## @param ui.podSecurityContext.enabled Enable pods' Security Context diff --git a/install.sh b/install.sh index 6de016007f4e4eab84cd331a0a1a7aafca046b38..c5f130f5b7a4b59ea9a8d98e172984e09ae7ff48 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash # preset -VERSION="1.7.0" +VERSION="1.6.4" MIN_CPU=8 MIN_RAM=4 MIN_MAP_COUNT=262144 diff --git a/lib/python/README.md b/lib/python/README.md index d4599caee863105b3cebd337d290e0fcb1a5a6c0..443787cbb4cdcb13d0e3ec522d0d9762262000e8 100644 --- a/lib/python/README.md +++ b/lib/python/README.md @@ -48,17 +48,17 @@ client.import_table_data(database_id=7, table_id=13, file_name_or_data_frame=df) ## Supported Features & Best-Practices - Manage user - account ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/#create-user-account)) + account ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/#create-user-account)) - Manage - databases ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/usage-overview/#create-database)) + databases ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/usage-overview/#create-database)) - Manage database access & - visibility ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/#create-database)) + visibility ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/#create-database)) - Import - dataset ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/#import-dataset)) + dataset ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/#import-dataset)) - Create persistent - identifiers ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/#assign-database-pid)) + identifiers ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/#assign-database-pid)) - Execute - queries ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/#export-subset)) + queries ([docs](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/#export-subset)) - Get data from tables/views/subsets ## Configure diff --git a/lib/python/docs/index.rst b/lib/python/docs/index.rst index 137dde40c6abbc4ec83fbb3b999c660b94d85efd..6c0c17e37503b68240274f7a6081efc598dea544 100644 --- a/lib/python/docs/index.rst +++ b/lib/python/docs/index.rst @@ -6,13 +6,13 @@ Pandas `DataFrame <https://pandas.pydata.org/docs/reference/api/pandas.DataFrame provides an object-oriented API as well as low-level access to DBRepo services. .. note:: - The SDK has been implemented and documented for DBRepo version 1.7.0, earlier versions may be supported but are not tested for compatibility. + The SDK has been implemented and documented for DBRepo version 1.6.4, earlier versions may be supported but are not tested for compatibility. Quickstart ---------- Find numerous quickstart examples on -the `DBRepo website <https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/api/>`_. +the `DBRepo website <https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/>`_. AMQP API Client ----------- diff --git a/lib/python/pyproject.toml b/lib/python/pyproject.toml index 65d9c7e3d9c2611bb1bfed55d59f1da01e41e874..b956d6afd0ff66f7ae83f38112b7443001e98da1 100644 --- a/lib/python/pyproject.toml +++ b/lib/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dbrepo" -version = "1.7.0" +version = "1.6.4" description = "DBRepo Python Library" keywords = [ "DBRepo", @@ -34,7 +34,7 @@ requires = [ build-backend = "setuptools.build_meta" [project.urls] -Homepage = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/" -Documentation = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/python/" +Homepage = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/" +Documentation = "https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/python/" Issues = "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues" Source = "https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/" \ No newline at end of file diff --git a/lib/python/setup.py b/lib/python/setup.py index 4fff48185b04734932caad08d4aa06583730a52f..53f4832404814c0e1468082add0b090ea106de84 100644 --- a/lib/python/setup.py +++ b/lib/python/setup.py @@ -2,9 +2,9 @@ from distutils.core import setup setup(name="dbrepo", - version="1.7.0", + version="1.6.4", description="A library for communicating with DBRepo", - url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/", + url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/", author="Martin Weise", license="Apache-2.0", author_email="martin.weise@tuwien.ac.at", diff --git a/mkdocs.yml b/mkdocs.yml index 536eed294ed4f5683d601f2e0a460a8ade5267d1..5ec3a92799fba08d9299e466e780422f20bf1a65 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,5 @@ site_name: Database Repository -site_url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ +site_url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/ repo_url: https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services repo_name: fda-services site_author: Research Unit Data Science, Technische Universität Wien @@ -120,9 +120,9 @@ markdown_extensions: custom_icons: - .docs/overrides/.icons extra: - homepage: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7/ + homepage: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/ version: - default: 1.7 + default: 1.6 provider: mike social: - icon: simple/artifacthub diff --git a/sonar-project.properties b/sonar-project.properties index 0d25b112d7133494be618d3f61e3e17a2c415e94..e118258889d85c43894ea7493ba9c16bcc83c5fa 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,7 +2,7 @@ sonar.projectKey=fair-data-austria-db-repository_fda-services_a57fa043-ab99-4cdd-a721-162d9a916d77 sonar.host.url=https://s39.datalab.tuwien.ac.at # project -sonar.projectVersion=1.7.0 +sonar.projectVersion=1.6.4 # general sonar.qualitygate.wait=true sonar.projectCreation.mainBranchName=master diff --git a/versions.json b/versions.json index 95ca2a62a6fec4b73534bc3d6981b1bcdfd8fff2..b42a3dfd7d8ac8f78858923d4ac6d89906452771 100644 --- a/versions.json +++ b/versions.json @@ -1,9 +1,4 @@ [ - { - "version": "1.7", - "title": "1.7", - "aliases": [] - }, { "version": "1.6", "title": "1.6",