diff --git a/.docs/api/identity-service.md b/.docs/api/identity-service.md index 1fe3454956aca84b3c38e174e1f16705afa5360b..e01ad63fc2bb3ac06d84dccf1d61765d84ddad87 100644 --- a/.docs/api/identity-service.md +++ b/.docs/api/identity-service.md @@ -12,10 +12,13 @@ author: Martin Weise ## Overview -This service holds the user identities which we simply call identities in the following. It is integrated into the -[Auth Service](../auth-service) through an LDAP federation, allowing any identity to authenticate through the Auth -Service. The LDAP protocol is not used for authentication. You can use your own identity provider, e.g. Active -Directory. +This optional service holds the user identities which we simply call identities in the following. It is integrated into +the [Auth Service](../auth-service) through an LDAP federation, allowing any identity to authenticate through the Auth +Service. The LDAP protocol is not used for authentication. + +The Identity Service can be optionally replaced with your existing LDAP solution. Your LDAP solution should store +users using the RFC 2798 [`InetOrgPerson`](https://datatracker.ietf.org/doc/html/rfc2798) schema which is standard +to most LDAP solutions. ## Identities @@ -23,6 +26,9 @@ Any identity is identified by its `entryUUID` by default in the Auth Service. No the Auth Service) may assign a different UUID to a user. DBRepo **always** uses the UUID provided through the Identity Service. +The field `uid` is the username and is used for bind/unbind operations. The fields `cn` and `sn` are ignored by the +Auth Service and can be empty `""`. + ## Limitations * Limited support for scaling in Kubernetes, see the diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c934e6a459b9a43c4b63ac471c65f0794a32bff3..605b27a39cfd4da5bf682351ebe00dd2ba2e7669 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -100,6 +100,7 @@ build-data-service: dependencies: - build-metadata-service script: + - "mvn -f ./dbrepo-metadata-service/pom.xml clean install $MAVEN_OPTS -DskipTests" - "mvn -f ./dbrepo-data-service/pom.xml clean package $MAVEN_OPTS -DskipTests" # Compiled classes are needed for SonarQube in later stages artifacts: @@ -169,8 +170,8 @@ verify-install-script: - bash install.sh - exit 0 -lint-helm: - image: docker.io/docker:24-dind +lint-helm-chart: + image: docker.io/alpine:3.20 stage: lint except: refs: @@ -179,8 +180,9 @@ lint-helm: - build-metadata-service dependencies: - build-metadata-service + before_script: + - apk add helm script: - - apk add sed helm curl - helm lint ./helm/dbrepo test-metadata-service: @@ -271,7 +273,7 @@ test-search-service: script: - "pip install pipenv" - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-search-service/ && coverage run -m pytest test/test_opensearch_client.py --junitxml=report.xml && coverage html --omit="test/*" && coverage report --omit="test/*" > ./coverage.txt + - cd ./dbrepo-search-service/ && coverage run -m pytest test/test_opensearch_client.py --junitxml=report.xml && coverage html --omit="test/*,omlib/*" && coverage report --omit="test/*,omlib/*" > ./coverage.txt - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" artifacts: when: always diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6a6e8d951f9c9a486408f47827d7e49ed92820f..4e9c81e56350032ae19e8ced1b1d004c71fab418 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,4 +35,11 @@ a couple of days at maximum, one could go directly for a PR. It's fine. - [ ] Change the maven version in the metadata & data services: - `mvn -f ./dbrepo-metadata-service/pom.xml versions:set -DnewVersion=VERSION` - `mvn -f ./dbrepo-data-service/pom.xml versions:set -DnewVersion=VERSION` -- [ ] Change the versions in `versions.json` for the generated website \ No newline at end of file +- [ ] Change the versions in `versions.json` for the generated website + +Then generate the REST API-, Python Library- and Helm Chart documentation: + +```bash +# optional: pip install -r ./requirements.txt +make gen-swagger-doc gen-lib-doc gen-helm-doc +``` \ No newline at end of file diff --git a/dbrepo-analyse-service/app.py b/dbrepo-analyse-service/app.py index bfc8212864933c7ec8253825d5fbe4d5dc7e7b44..c006e5777b5a14cc64dde335ddbdad185f162bbb 100644 --- a/dbrepo-analyse-service/app.py +++ b/dbrepo-analyse-service/app.py @@ -185,8 +185,6 @@ app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKE app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost/api/auth") app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") -app.config["ADMIN_USERNAME"] = os.getenv('ADMIN_USERNAME', 'admin') -app.config["ADMIN_PASSWORD"] = os.getenv('ADMIN_PASSWORD', 'admin') app.config["S3_ACCESS_KEY_ID"] = os.getenv('S3_ACCESS_KEY_ID', 'seaweedfsadmin') app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000') app.config["S3_EXPORT_BUCKET"] = os.getenv('S3_EXPORT_BUCKET', 'dbrepo-download') @@ -211,8 +209,6 @@ def verify_token(token: str): def verify_password(username: str, password: str) -> Any: if username is None or username == "" or password is None or password == "": return False - if username == app.config["ADMIN_USERNAME"] and password == app.config["ADMIN_PASSWORD"]: - return User(username=username, roles=["admin"]) client = KeycloakClient() try: return client.verify_jwt(access_token=client.obtain_user_token(username=username, password=password)) diff --git a/dbrepo-auth-service/dbrepo-realm.json b/dbrepo-auth-service/dbrepo-realm.json index 270ca00a1f59dedc2b3f9b25b7c30c73064f7c82..87eb81e777ad6fef5b893cfabea4366d035ddb7a 100644 --- a/dbrepo-auth-service/dbrepo-realm.json +++ b/dbrepo-auth-service/dbrepo-realm.json @@ -66,6 +66,17 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "7ee1c424-11b0-46a9-b0ed-725e9b7fc40c", + "name" : "default-system-roles", + "description" : "${default-system-roles}", + "composite" : true, + "composites" : { + "realm" : [ "delete-database-view", "update-semantic-unit", "export-query-data", "check-foreign-database-access", "default-data-steward-roles", "execute-query", "default-user-handling", "delete-table-data", "find-query", "list-database-views", "persist-query", "update-search-index", "delete-database-access", "view-table-history", "create-ontology", "update-ontology", "modify-user-theme", "default-system-roles", "create-semantic-concept", "default-container-handling", "create-container", "create-table", "default-broker-handling", "default-maintenance-handling", "execute-semantic-query", "uma_authorization", "table-semantic-analyse", "list-containers", "check-database-access", "escalated-query-handling", "delete-identifier", "modify-database-owner", "list-tables", "export-table-data", "create-database-access", "delete-container", "re-execute-query", "create-semantic-unit", "escalated-identifier-handling", "system", "update-table-statistic", "escalated-semantics-handling", "default-database-handling", "delete-ontology", "find-database", "find-database-view", "update-semantic-concept", "find-user", "import-database-data", "publish-identifier", "default-roles-dbrepo", "find-foreign-user", "create-database", "create-maintenance-message", "find-maintenance-message", "escalated-container-handling", "default-researcher-roles", "default-identifier-handling", "escalated-user-handling", "modify-user-information", "create-database-view", "update-maintenance-message", "delete-foreign-table", "offline_access", "modify-foreign-table-column-semantics", "delete-maintenance-message", "find-container", "insert-table-data", "modify-identifier-metadata", "modify-database-image", "escalated-broker-handling", "modify-table-column-semantics", "escalated-database-handling", "default-semantics-handling", "update-database-access", "default-query-handling", "find-table", "list-queries", "default-developer-roles", "create-identifier", "escalated-table-handling", "find-identifier", "view-database-view-data", "view-table-data", "list-licenses", "default-table-handling", "list-identifiers", "create-foreign-identifier", "list-databases", "list-ontologies", "modify-database-visibility", "list-maintenance-messages", "delete-table" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "143ba359-5fa2-451e-8296-43ecf20bb251", "name" : "update-semantic-concept", @@ -104,6 +115,14 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "74648f9a-777e-4ef9-b97b-4c5d749d862f", + "name" : "update-search-index", + "description" : "${update-search-index}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "22492b64-c633-48a0-9678-b28669f2885b", "name" : "execute-semantic-query", @@ -131,14 +150,6 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } - }, { - "id" : "79534da1-4c85-409e-810e-a7ce6d632b09", - "name" : "system", - "description" : "${system}", - "composite" : false, - "clientRole" : false, - "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", - "attributes" : { } }, { "id" : "b0d66d3d-59b4-4aae-aa66-e3d5a49f28e3", "name" : "view-database-view-data", @@ -389,6 +400,14 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "b05e9b2b-748d-490b-949b-e78655bf7805", + "name" : "check-foreign-database-access", + "description" : "${check-foreign-database-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "c047d521-cec3-4444-86c4-aef098489b7b", "name" : "delete-maintenance-message", @@ -397,6 +416,14 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "88f82262-be80-4d18-9fb4-5529da031f33", + "name" : "system", + "description" : "${system}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "e14ab76b-1c24-484d-ae2d-478b8457edea", "name" : "list-licenses", @@ -646,6 +673,14 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "0c487c93-448f-4a82-8b9f-ebd8a0904bf8", + "name" : "find-foreign-user", + "description" : "${find-foreign-user}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "cf9735a9-fb70-4cc5-b5f4-75afc4e5654b", "name" : "modify-identifier-metadata", @@ -1089,6 +1124,14 @@ "realmRoles" : [ "default-researcher-roles" ], "clientRoles" : { }, "subGroups" : [ ] + }, { + "id" : "2b9f94b4-d434-4a98-8eab-25678cfee983", + "name" : "system", + "path" : "/system", + "attributes" : { }, + "realmRoles" : [ "default-system-roles" ], + "clientRoles" : { }, + "subGroups" : [ ] } ], "defaultRole" : { "id" : "abd2d9ee-ebc4-4d0a-839e-6b588a6d442a", @@ -1107,7 +1150,7 @@ "otpPolicyLookAheadWindow" : 1, "otpPolicyPeriod" : 30, "otpPolicyCodeReusable" : false, - "otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppFreeOTPName", "totpAppGoogleName" ], + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], "webAuthnPolicyRpEntityName" : "keycloak", "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], "webAuthnPolicyRpId" : "", @@ -2095,7 +2138,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "saml-user-property-mapper" ] } }, { "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", @@ -2121,7 +2164,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-role-list-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper" ] } } ], "org.keycloak.storage.UserStorageProvider" : [ { @@ -2149,8 +2192,8 @@ "config" : { "ldap.attribute" : [ "sn" ], "is.mandatory.in.ldap" : [ "true" ], - "always.read.value.from.ldap" : [ "true" ], "read.only" : [ "false" ], + "always.read.value.from.ldap" : [ "true" ], "user.model.attribute" : [ "lastName" ] } }, { @@ -2185,17 +2228,17 @@ "config" : { "membership.attribute.type" : [ "DN" ], "group.name.ldap.attribute" : [ "cn" ], - "preserve.group.inheritance" : [ "false" ], "membership.user.ldap.attribute" : [ "uid" ], - "groups.dn" : [ "cn=system,ou=users,dc=dbrepo,dc=at" ], + "preserve.group.inheritance" : [ "false" ], + "groups.dn" : [ "ou=users,dc=dbrepo,dc=at" ], "mode" : [ "LDAP_ONLY" ], "user.roles.retrieve.strategy" : [ "LOAD_GROUPS_BY_MEMBER_ATTRIBUTE" ], - "ignore.missing.groups" : [ "false" ], "membership.ldap.attribute" : [ "member" ], - "memberof.ldap.attribute" : [ "memberOf" ], + "ignore.missing.groups" : [ "false" ], "group.object.classes" : [ "groupOfNames" ], - "groups.path" : [ "/" ], - "drop.non.existing.groups.during.sync" : [ "false" ] + "memberof.ldap.attribute" : [ "memberOf" ], + "drop.non.existing.groups.during.sync" : [ "false" ], + "groups.path" : [ "/" ] } }, { "id" : "b6ff3285-35af-4e86-8bb4-d94b8e0d70bb", @@ -2205,8 +2248,8 @@ "config" : { "ldap.attribute" : [ "modifyTimestamp" ], "is.mandatory.in.ldap" : [ "false" ], - "always.read.value.from.ldap" : [ "true" ], "read.only" : [ "true" ], + "always.read.value.from.ldap" : [ "true" ], "user.model.attribute" : [ "modifyTimestamp" ] } }, { @@ -2219,8 +2262,8 @@ "attribute.force.default" : [ "false" ], "is.mandatory.in.ldap" : [ "true" ], "is.binary.attribute" : [ "false" ], - "always.read.value.from.ldap" : [ "false" ], "read.only" : [ "false" ], + "always.read.value.from.ldap" : [ "false" ], "user.model.attribute" : [ "username" ] } } ] @@ -2229,16 +2272,16 @@ "fullSyncPeriod" : [ "-1" ], "pagination" : [ "false" ], "startTls" : [ "false" ], - "usersDn" : [ "ou=users,dc=dbrepo,dc=at" ], "connectionPooling" : [ "true" ], + "usersDn" : [ "ou=users,dc=dbrepo,dc=at" ], "cachePolicy" : [ "DEFAULT" ], "useKerberosForPasswordAuthentication" : [ "false" ], "importEnabled" : [ "true" ], "enabled" : [ "true" ], - "usernameLDAPAttribute" : [ "uid" ], - "bindDn" : [ "cn=admin,dc=dbrepo,dc=at" ], - "bindCredential" : [ "adminpassword" ], "changedSyncPeriod" : [ "-1" ], + "bindDn" : [ "cn=admin,dc=dbrepo,dc=at" ], + "usernameLDAPAttribute" : [ "uid" ], + "bindCredential" : [ "admin" ], "lastSync" : [ "1719252666" ], "vendor" : [ "other" ], "uuidLDAPAttribute" : [ "entryUUID" ], @@ -2304,7 +2347,7 @@ "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "df1ebc5f-2037-43f5-9915-71eb4cd0ed7e", + "id" : "259dd7b6-01b7-433a-bda4-028857151ecd", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -2326,7 +2369,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "76ef2d26-2756-4ce1-904b-4be58e99b576", + "id" : "f94a4b6d-deaa-4505-be0f-544828436fa1", "alias" : "Authentication Options", "description" : "Authentication options.", "providerId" : "basic-flow", @@ -2355,7 +2398,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "b0d74a54-cea7-48f2-a4c9-f35204488da6", + "id" : "542ca1d7-9627-4102-b843-98837ce433fb", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2377,7 +2420,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "07b964c7-4527-4071-9f7a-e50d6321d951", + "id" : "4f153b98-6851-440b-a022-0a14e67a9b2f", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2399,7 +2442,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "be69fd2d-1bf5-429e-9833-a76232a23904", + "id" : "3d791b35-d35c-40b2-bb3e-e806d72b27ee", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2421,7 +2464,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "e9d23d2a-d857-4547-a419-2fd850ed58e5", + "id" : "9b746104-9371-4c3f-b69f-9322cead1b08", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -2443,7 +2486,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "75e1f120-8a28-4cc0-af60-26fa9d865975", + "id" : "7a164efe-c97b-4fbb-950d-7745359ba9a4", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -2465,7 +2508,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "eeb37a0b-2f2f-47f5-9ee6-3da2c8b48ec0", + "id" : "4fdc5e1b-1b55-4662-8360-67d75fa22677", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -2488,7 +2531,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "8637f64c-8b45-48b0-b3ba-c6e93225cce4", + "id" : "75893341-c338-44d8-ae27-a3fc7bfe8f2d", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -2510,7 +2553,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "7ad56360-b344-4f26-9dea-1a718ed99d4e", + "id" : "89626b76-f4cf-4c46-934c-4408c225a44b", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -2546,7 +2589,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "c6817917-1d21-4693-9171-b2e3dfde9582", + "id" : "4112115a-e7a7-44c2-9af5-65d538e4ba0d", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -2582,7 +2625,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "7cd02437-6d05-486d-a7fe-4d1762895ded", + "id" : "f82a9b0a-2c0a-4cb1-96b2-6c78b0b1f14f", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -2611,7 +2654,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "eb1d9721-b4a0-40a5-9236-b4fd95ca9024", + "id" : "3614e155-e8ce-4958-98fb-a27e4706cc70", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -2626,7 +2669,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "219415d8-3bab-47a6-9d0c-8c1061ffb68a", + "id" : "506f9b96-5002-47c0-96e3-3830a0fcfa26", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -2649,7 +2692,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "ccbf8944-bd32-4aa1-a6f8-93513a3fa5a4", + "id" : "4b7a7e91-36db-4b27-8e2d-01a04a822980", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -2671,7 +2714,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "805f972b-75ca-48c0-a390-752b32c0688a", + "id" : "f8ba3c2e-3952-4434-98e8-b892eea90e9e", "alias" : "http challenge", "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", "providerId" : "basic-flow", @@ -2693,7 +2736,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "2b15383f-ded1-4fb6-afdc-0c19f65dacc7", + "id" : "04c2fe01-5076-4aa4-9596-4efb4004195f", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -2709,7 +2752,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "1c18c3c7-a191-426b-84a4-1ffec96562cc", + "id" : "d12f77e1-7733-44a2-98ff-fd75c784d721", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -2745,7 +2788,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "cab07ead-2a48-4b0c-8916-2f89abe55720", + "id" : "91f6048c-a376-4809-8f37-c8d7a517830c", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -2781,7 +2824,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "6e158077-d221-4695-b0d3-9528c5ba6bfd", + "id" : "7b8fb487-53b8-4533-a696-76bc05256cb1", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -2797,13 +2840,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "fcb6cb09-fec5-4390-800c-00a3d49525ec", + "id" : "48372696-0579-45e5-b074-5e8dbdbbe7d6", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "68f9e765-81d4-47cd-b111-94d6723883c5", + "id" : "08df3b83-e522-42a7-9e24-9028b960bf39", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/dbrepo-data-db/README.md b/dbrepo-data-db/README.md index 94eb341d841ea5150c920ada2461cf9f1302555f..c2dfb1b0c65e7e97903457dfafc7ed7d913d2b94 100644 --- a/dbrepo-data-db/README.md +++ b/dbrepo-data-db/README.md @@ -1 +1,5 @@ -# Data Database \ No newline at end of file +# Data Database + +S3 Import + +https://mariadb.com/kb/en/s3-storage-engine-system-variables/ \ No newline at end of file diff --git a/dbrepo-data-db/enable_history_insert.cnf b/dbrepo-data-db/enable_history_insert.cnf new file mode 100644 index 0000000000000000000000000000000000000000..7bced156c829b3dbd4d6221dfd9654045c6f501e --- /dev/null +++ b/dbrepo-data-db/enable_history_insert.cnf @@ -0,0 +1 @@ +secure_timestamp="SUPER" \ No newline at end of file diff --git a/dbrepo-data-db/sidecar/app.py b/dbrepo-data-db/sidecar/app.py index c88966bb00e789e8b102985a5abbdf4ec7034c90..40cb9fa4aab88e2478e9b7671043169c383e165c 100644 --- a/dbrepo-data-db/sidecar/app.py +++ b/dbrepo-data-db/sidecar/app.py @@ -119,8 +119,6 @@ app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKE app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost/api/auth") app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") -app.config["ADMIN_USERNAME"] = os.getenv('ADMIN_USERNAME', 'admin') -app.config["ADMIN_PASSWORD"] = os.getenv('ADMIN_PASSWORD', 'admin') app.config["S3_ACCESS_KEY_ID"] = os.getenv('S3_ACCESS_KEY_ID', 'seaweedfsadmin') app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000') app.config["S3_EXPORT_BUCKET"] = os.getenv('S3_EXPORT_BUCKET', 'dbrepo-download') @@ -146,8 +144,6 @@ def verify_token(token: str): def verify_password(username: str, password: str) -> Any: if username is None or username == "" or password is None or password == "": return False - if username == app.config["ADMIN_USERNAME"] and password == app.config["ADMIN_PASSWORD"]: - return User(username=username, roles=["admin"]) client = KeycloakClient() try: return client.verify_jwt(access_token=client.obtain_user_token(username=username, password=password)) @@ -178,7 +174,7 @@ def health(): @app.route("/sidecar/import/<string:filename>", methods=["POST"], endpoint="sidecar_import") @metrics.gauge(name='dbrepo_sidecar_import_dataset', description='Time needed to import dataset from S3') -@auth.login_required(role=['admin', 'import-database-data']) +@auth.login_required(role=['import-database-data']) @swag_from("ds-yml/import.yml") def import_csv(filename): auth.current_user() @@ -192,7 +188,7 @@ def import_csv(filename): @app.route("/sidecar/export/<string:filename>", methods=["POST"], endpoint="sidecar_export") @metrics.gauge(name='dbrepo_sidecar_export_dataset', description='Time needed to export dataset to S3') -@auth.login_required(role=['admin', 'export-query-data', 'export-table-data']) +@auth.login_required(role=['export-query-data', 'export-table-data']) @swag_from("ds-yml/export.yml") def import_csv(filename): logging.debug('endpoint export csv, filename=%s, body=%s', filename, request) diff --git a/dbrepo-data-service/Dockerfile b/dbrepo-data-service/Dockerfile index d4016836d91bf88f09ad60279689d9b16b5d9bb8..806908a8affe8d64b0aa3d6927418eaed8cd1e1e 100644 --- a/dbrepo-data-service/Dockerfile +++ b/dbrepo-data-service/Dockerfile @@ -28,9 +28,9 @@ RUN apk add --no-cache curl bash jq WORKDIR /app -USER 65534 +USER 1001 -COPY --from=build --chown=65534 ./rest-service/target/rest-service-*.jar ./data-service.jar +COPY --from=build --chown=1001 ./rest-service/target/rest-service-*.jar ./data-service.jar # non-root port EXPOSE 8080 diff --git a/dbrepo-data-service/metrics.md b/dbrepo-data-service/metrics.md index 425b58ad17e24683a606cf0a4cb9d3123412e4cf..8219898284d6a830e52f3f2f3ee4ee80dd635e52 100644 --- a/dbrepo-data-service/metrics.md +++ b/dbrepo-data-service/metrics.md @@ -2,18 +2,18 @@ |-----------------------------|-------------------------------------------| | `dbrepo_message_receive` | Received AMQP message from Broker Service | | `dbrepo_subset_create` | Create subset | -| `dbrepo_subset_data` | Retrieved subset data | +| `dbrepo_subset_data` | Get subset data | | `dbrepo_subset_find` | Find subset | | `dbrepo_subset_list` | Find subsets | | `dbrepo_subset_persist` | Persist subset | -| `dbrepo_table_data_create` | Insert a raw data tuple | -| `dbrepo_table_data_delete` | Delete table data | -| `dbrepo_table_data_export` | Export table data | -| `dbrepo_table_data_history` | Find table history | -| `dbrepo_table_data_import` | Import data from a dataset | -| `dbrepo_table_data_list` | Retrieve table data | -| `dbrepo_table_data_update` | Update a raw data tuple | -| `dbrepo_table_schema_list` | Find table schemas | -| `dbrepo_table_statistic` | Generate table statistic | -| `dbrepo_view_data` | Retrieve view data | -| `dbrepo_view_schema_list` | Find view schemas | +| `dbrepo_table_data_create` | Insert tuple | +| `dbrepo_table_data_delete` | Delete tuple | +| `dbrepo_table_data_export` | Get table data | +| `dbrepo_table_data_history` | Get history | +| `dbrepo_table_data_import` | Import dataset | +| `dbrepo_table_data_list` | Get table data | +| `dbrepo_table_data_update` | Update tuple | +| `dbrepo_table_schema_list` | Find tables | +| `dbrepo_table_statistic` | Get table statistic | +| `dbrepo_view_data` | Get view data | +| `dbrepo_view_schema_list` | Find views | diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 76ead57517edb931164c3758dd1ea49c9d5c111a..fa6f32a02f94b182dbbe3b50ed6385521bcd03cb 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -173,6 +173,12 @@ <artifactId>dbrepo-metadata-service-api</artifactId> <version>${project.version}</version> </dependency> + <!-- Exceptions --> + <dependency> + <groupId>at.tuwien</groupId> + <artifactId>dbrepo-metadata-service-repositories</artifactId> + <version>${project.version}</version> + </dependency> <!-- AMPQ --> <dependency> <groupId>org.springframework.amqp</groupId> diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 4966e008424aa6e1f290c70b29e97d4b55e72273..133bee769c792602ae89114a218381dd913f5c93 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -41,7 +41,7 @@ public class AccessEndpoint { } @PostMapping("/{userId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Give access", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -78,7 +78,7 @@ public class AccessEndpoint { @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto data) throws NotAllowedException, DatabaseUnavailableException, DatabaseNotFoundException, - RemoteUnavailableException, UserNotFoundException, DatabaseMalformedException, ServiceException { + RemoteUnavailableException, UserNotFoundException, DatabaseMalformedException, MetadataServiceException { log.debug("endpoint give access to database, databaseId={}, userId={}", databaseId, userId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); final PrivilegedUserDto user = metadataServiceGateway.getPrivilegedUserById(userId); @@ -97,7 +97,7 @@ public class AccessEndpoint { } @PutMapping("/{userId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Update access", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -134,7 +134,7 @@ public class AccessEndpoint { @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto access) throws NotAllowedException, DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException, MetadataServiceException { log.debug("endpoint modify access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, access.getType()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); @@ -154,7 +154,7 @@ public class AccessEndpoint { } @DeleteMapping("/{userId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Revoke access", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -190,7 +190,7 @@ public class AccessEndpoint { public ResponseEntity<Void> revoke(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("userId") UUID userId) throws NotAllowedException, DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException, MetadataServiceException { log.debug("endpoint revoke access to database, databaseId={}, userId={}", databaseId, userId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); final UserDto user = metadataServiceGateway.getUserById(userId); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 5397ba158477d9f30b05cf7707b489213dcc3920..9cefc57fa2b70db65daee6d4bc1d1ddd6434aa24 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -53,7 +53,7 @@ public class DatabaseEndpoint { } @PostMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Create database", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -86,7 +86,7 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> create(@Valid @RequestBody CreateDatabaseDto data) throws DatabaseUnavailableException, RemoteUnavailableException, ContainerNotFoundException, - DatabaseMalformedException, QueryStoreCreateException, ServiceException { + DatabaseMalformedException, QueryStoreCreateException, MetadataServiceException { log.debug("endpoint create database, data.containerId={}, data.internalName={}, data.username={}", data.getContainerId(), data.getInternalName(), data.getUsername()); final PrivilegedContainerDto container = metadataServiceGateway.getContainerById(data.getContainerId()); @@ -108,7 +108,7 @@ public class DatabaseEndpoint { } @PutMapping("/{databaseId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Update user password", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -134,7 +134,7 @@ public class DatabaseEndpoint { public ResponseEntity<Void> update(@NotBlank @PathVariable("databaseId") Long databaseId, @Valid @RequestBody UpdateUserPasswordDto data) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException, MetadataServiceException { log.debug("endpoint update user password in database, databaseId={}, data.username={}", databaseId, data.getUsername()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index e75cd571eb49ee8bab55fb4b21cd925e9bd9948a..f4626deb93f9f1581be1ee5eab2fe748734ee4e6 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -89,7 +89,7 @@ public class SubsetEndpoint { @RequestParam(name = "persisted", required = false) Boolean filterPersisted, Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - QueryNotFoundException, NotAllowedException, ServiceException { + QueryNotFoundException, NotAllowedException, MetadataServiceException { log.debug("endpoint find subsets in database, databaseId={}, filterPersisted={}", databaseId, filterPersisted); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); if (!database.getIsPublic()) { @@ -156,7 +156,7 @@ public class SubsetEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, QueryMalformedException, SidecarExportException, StorageNotFoundException, NotAllowedException, UserNotFoundException, - ServiceException { + MetadataServiceException { String accept = httpServletRequest.getHeader("Accept"); log.debug("endpoint find subset in database, databaseId={}, subsetId={}, accept={}, timestamp={}", databaseId, subsetId, accept, timestamp); @@ -260,7 +260,7 @@ public class SubsetEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, StorageUnavailableException, QueryMalformedException, SidecarExportException, StorageNotFoundException, QueryStoreInsertException, TableMalformedException, PaginationException, - QueryNotSupportedException, NotAllowedException, UserNotFoundException, ServiceException { + QueryNotSupportedException, NotAllowedException, UserNotFoundException, MetadataServiceException { log.debug("endpoint create subset in database, databaseId={}, data.statement={}, principal.name={}, page={}, " + "size={}, timestamp={}", databaseId, data.getStatement(), principal.getName(), page, size, timestamp); /* check */ @@ -337,7 +337,7 @@ public class SubsetEndpoint { @RequestParam(required = false) Long size) throws PaginationException, DatabaseNotFoundException, RemoteUnavailableException, NotAllowedException, QueryNotFoundException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, UserNotFoundException, - ServiceException { + MetadataServiceException { log.debug("endpoint re-execute query, databaseId={}, subsetId={}, principal.name={} page={}, size={}", databaseId, subsetId, principal != null ? principal.getName() : null, page, size); endpointValidator.validateDataParams(page, size); @@ -424,7 +424,7 @@ public class SubsetEndpoint { @NotNull @Valid @RequestBody QueryPersistDto data, @NotNull Principal principal) throws NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, QueryStorePersistException, - DatabaseUnavailableException, QueryNotFoundException, UserNotFoundException, ServiceException { + DatabaseUnavailableException, QueryNotFoundException, UserNotFoundException, MetadataServiceException { log.debug("endpoint persist query, databaseId={}, queryId={}, data.persist={}, principal.name={}", databaseId, queryId, data.getPersist(), principal.getName()); metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index a0200609a6001638615c7726279483f563585f97..7e95c7cfa94ae356a1e3d908c903bf7294f3621a 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -61,7 +61,7 @@ public class TableEndpoint { } @PostMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Create table", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -95,7 +95,7 @@ public class TableEndpoint { public ResponseEntity<TableDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody TableCreateDto data) throws DatabaseNotFoundException, RemoteUnavailableException, TableMalformedException, DatabaseUnavailableException, TableExistsException, - TableNotFoundException, QueryMalformedException, ServiceException { + TableNotFoundException, QueryMalformedException, MetadataServiceException { log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -108,7 +108,7 @@ public class TableEndpoint { } @DeleteMapping("/{tableId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Delete table", security = {@SecurityRequirement(name = "basicAuth")}, hidden = true) @@ -137,7 +137,7 @@ public class TableEndpoint { public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - QueryMalformedException, ServiceException { + QueryMalformedException, MetadataServiceException { log.debug("endpoint delete table, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); try { @@ -191,7 +191,7 @@ public class TableEndpoint { @RequestParam(required = false) Long size, Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, PaginationException, QueryMalformedException, ServiceException, + TableMalformedException, PaginationException, QueryMalformedException, MetadataServiceException, NotAllowedException { log.debug("endpoint find table data, databaseId={}, tableId={}, timestamp={}, page={}, size={}", databaseId, tableId, timestamp, page, size); @@ -268,7 +268,7 @@ public class TableEndpoint { @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException, StorageUnavailableException, - StorageNotFoundException, ServiceException { + StorageNotFoundException, MetadataServiceException { log.debug("endpoint insert raw table data, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); final DatabaseAccessDto access = metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); @@ -319,7 +319,7 @@ public class TableEndpoint { @Valid @RequestBody TupleUpdateDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, ServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { log.debug("endpoint update raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); @@ -371,7 +371,7 @@ public class TableEndpoint { @Valid @RequestBody TupleDeleteDto data, @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, ServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { log.debug("endpoint delete raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); @@ -424,7 +424,7 @@ public class TableEndpoint { @NotNull @PathVariable("tableId") Long tableId, @RequestParam(value = "size", required = false) Long size, Principal principal) throws DatabaseUnavailableException, - RemoteUnavailableException, TableNotFoundException, NotAllowedException, ServiceException, + RemoteUnavailableException, TableNotFoundException, NotAllowedException, MetadataServiceException, PaginationException { log.debug("endpoint find table history, databaseId={}, tableId={}", databaseId, tableId); if (size != null && size <= 0) { @@ -453,7 +453,7 @@ public class TableEndpoint { } @GetMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Observed(name = "dbrepo_table_schema_list") @Operation(summary = "Find tables", hidden = true) @@ -491,7 +491,7 @@ public class TableEndpoint { }) public ResponseEntity<List<TableDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - DatabaseMalformedException, TableNotFoundException, QueryMalformedException, ServiceException { + DatabaseMalformedException, TableNotFoundException, MetadataServiceException { log.debug("endpoint inspect table schemas, databaseId={}", databaseId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -540,7 +540,7 @@ public class TableEndpoint { Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, NotAllowedException, StorageUnavailableException, QueryMalformedException, SidecarExportException, - StorageNotFoundException, ServiceException { + StorageNotFoundException, MetadataServiceException { log.debug("endpoint find table history, databaseId={}, tableId={}, timestamp={}", databaseId, tableId, timestamp); /* parameters */ if (timestamp == null) { @@ -606,7 +606,7 @@ public class TableEndpoint { @NotNull Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, QueryMalformedException, StorageNotFoundException, SidecarImportException, NotAllowedException, - ServiceException { + MetadataServiceException { log.debug("endpoint insert table data, databaseId={}, tableId={}, data.location={}", databaseId, tableId, data.getLocation()); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); final DatabaseAccessDto access = metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); @@ -659,7 +659,7 @@ public class TableEndpoint { public ResponseEntity<TableStatisticDto> statistic(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - ServiceException, TableMalformedException, QueryMalformedException { + MetadataServiceException, TableMalformedException, QueryMalformedException { log.debug("endpoint generate table statistic, databaseId={}, tableId={}", databaseId, tableId); final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); try { diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 3212b699a2789ca6e127c9132286f696142c57f2..e9dbfd5c3a7f3d59088f048398cd2c4f9d9d8f45 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -54,7 +54,7 @@ public class ViewEndpoint { } @GetMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Observed(name = "dbrepo_view_schema_list") @Operation(summary = "Find views", hidden = true) @@ -93,7 +93,7 @@ public class ViewEndpoint { public ResponseEntity<List<ViewDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, ViewNotFoundException, DatabaseMalformedException, ViewSchemaException, - ServiceException { + MetadataServiceException { log.debug("endpoint inspect view schemas, databaseId={}", databaseId); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -105,7 +105,7 @@ public class ViewEndpoint { } @PostMapping - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Create view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}, hidden = true) @@ -138,7 +138,7 @@ public class ViewEndpoint { }) public ResponseEntity<ViewDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody ViewCreateDto data) throws DatabaseUnavailableException, - DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, MetadataServiceException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { @@ -151,7 +151,7 @@ public class ViewEndpoint { } @DeleteMapping("/{viewId}") - @PreAuthorize("hasAuthority('admin')") + @PreAuthorize("hasAuthority('system')") @Operation(summary = "Delete view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}, hidden = true) @@ -182,7 +182,7 @@ public class ViewEndpoint { public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("viewId") Long viewId) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, - ViewMalformedException, ServiceException { + ViewMalformedException, MetadataServiceException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId); try { @@ -243,7 +243,7 @@ public class ViewEndpoint { Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, QueryMalformedException, ViewMalformedException, PaginationException, NotAllowedException, - ServiceException { + MetadataServiceException { log.debug("endpoint get view data, databaseId={}, viewId={}, page={}, size={}, timestamp={}", databaseId, viewId, page, size, timestamp); endpointValidator.validateDataParams(page, size); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java deleted file mode 100644 index 18373423c5dd58d5236670a63989134132e4685d..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ /dev/null @@ -1,235 +0,0 @@ -package at.tuwien.handlers; - -import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.exception.*; -import io.swagger.v3.oas.annotations.Hidden; -import lombok.extern.log4j.Log4j2; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@Log4j2 -@ControllerAdvice -public class ApiExceptionHandler extends ResponseEntityExceptionHandler { - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(ContainerNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(ContainerNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) - @ExceptionHandler(DatabaseMalformedException.class) - public ResponseEntity<ApiErrorDto> handle(DatabaseMalformedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(DatabaseNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(DatabaseNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(DatabaseUnavailableException.class) - public ResponseEntity<ApiErrorDto> handle(DatabaseUnavailableException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE) - @ExceptionHandler(FormatNotAvailableException.class) - public ResponseEntity<ApiErrorDto> handle(FormatNotAvailableException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.FORBIDDEN) - @ExceptionHandler(NotAllowedException.class) - public ResponseEntity<ApiErrorDto> handle(NotAllowedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler(PaginationException.class) - public ResponseEntity<ApiErrorDto> handle(PaginationException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler(QueryMalformedException.class) - public ResponseEntity<ApiErrorDto> handle(QueryMalformedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(QueryNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(QueryNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_IMPLEMENTED) - @ExceptionHandler(QueryNotSupportedException.class) - public ResponseEntity<ApiErrorDto> handle(QueryNotSupportedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) - @ExceptionHandler(QueryStoreCreateException.class) - public ResponseEntity<ApiErrorDto> handle(QueryStoreCreateException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler(QueryStoreGCException.class) - public ResponseEntity<ApiErrorDto> handle(QueryStoreGCException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) - @ExceptionHandler(QueryStoreInsertException.class) - public ResponseEntity<ApiErrorDto> handle(QueryStoreInsertException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) - @ExceptionHandler(QueryStorePersistException.class) - public ResponseEntity<ApiErrorDto> handle(QueryStorePersistException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(RemoteUnavailableException.class) - public ResponseEntity<ApiErrorDto> handle(RemoteUnavailableException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_GATEWAY) - @ExceptionHandler(ServiceConnectionException.class) - public ResponseEntity<ApiErrorDto> handle(ServiceConnectionException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(ServiceException.class) - public ResponseEntity<ApiErrorDto> handle(ServiceException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(SidecarExportException.class) - public ResponseEntity<ApiErrorDto> handle(SidecarExportException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(SidecarImportException.class) - public ResponseEntity<ApiErrorDto> handle(SidecarImportException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(StorageNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(StorageNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler(StorageUnavailableException.class) - public ResponseEntity<ApiErrorDto> handle(StorageUnavailableException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.CONFLICT) - @ExceptionHandler(TableExistsException.class) - public ResponseEntity<ApiErrorDto> handle(TableExistsException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler(TableMalformedException.class) - public ResponseEntity<ApiErrorDto> handle(TableMalformedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(TableNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(TableNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.CONFLICT) - @ExceptionHandler(TableSchemaException.class) - public ResponseEntity<ApiErrorDto> handle(TableSchemaException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(UserNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(UserNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler(ViewMalformedException.class) - public ResponseEntity<ApiErrorDto> handle(ViewMalformedException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler(ViewNotFoundException.class) - public ResponseEntity<ApiErrorDto> handle(ViewNotFoundException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - @Hidden - @ResponseStatus(code = HttpStatus.CONFLICT) - @ExceptionHandler(ViewSchemaException.class) - public ResponseEntity<ApiErrorDto> handle(ViewSchemaException e) { - return generic_handle(e.getClass(), e.getLocalizedMessage()); - } - - private ResponseEntity<ApiErrorDto> generic_handle(Class<?> exceptionClass, String message) { - final HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Type", "application/problem+json"); - final ResponseStatus annotation = exceptionClass.getAnnotation(ResponseStatus.class); - final ApiErrorDto response = ApiErrorDto.builder() - .status(annotation.code()) - .message(message) - .code(annotation.reason()) - .build(); - return new ResponseEntity<>(response, headers, response.getStatus()); - } - -} diff --git a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml index 5a6dc187e80cde15b38961c77875d4e2fde0ff98..fc5445ce78e9a1f29ae6fd0f3d2d918dcb30a277 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml @@ -57,15 +57,14 @@ dbrepo: secretAccessKey: seaweedfsadmin importBucket: dbrepo-upload exportBucket: dbrepo-download - filePath: /tmp - admin: + system: username: admin password: admin jwt: public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB keycloak: - username: fda - password: fda + username: admin + password: admin client: dbrepo-client clientSecret: MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG defaultDateFormatId: 1 diff --git a/dbrepo-data-service/rest-service/src/main/resources/application.yml b/dbrepo-data-service/rest-service/src/main/resources/application.yml index 93f31ab5ae3020352e56bea4c890fe81c26e7f31..2043395f307070c0e95b9d442d5baa9b7bb58951 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml @@ -59,9 +59,9 @@ dbrepo: importBucket: "${S3_IMPORT_BUCKET:dbrepo-upload}" exportBucket: "${S3_EXPORT_BUCKET:dbrepo-download}" filePath: "${S3_FILE_PATH:/tmp}" - admin: - username: "${ADMIN_USERNAME:admin}" - password: "${ADMIN_PASSWORD:admin}" + system: + username: "${SYSTEM_USERNAME:admin}" + password: "${SYSTEM_PASSWORD:admin}" jwt: public_key: "${JWT_PUBKEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" keycloak: diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java index 54af799db3fd021475222be7fac444ad83ed4535..8f73fa1b53b41be7d8cbfbe71f25a27c94ccbb01 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java @@ -177,7 +177,8 @@ public class MariaDbConfig { if (set.next()) { final Matcher matcher = Pattern.compile("GRANT (.*) ON.*").matcher(set.getString(1)); if (matcher.find()) { - final List<String> privileges = Arrays.asList(matcher.group(1).split(","));; + final List<String> privileges = Arrays.asList(matcher.group(1).split(",")); + ; log.trace("found privileges: {}", privileges); return privileges; } @@ -224,7 +225,7 @@ public class MariaDbConfig { public static Long mockUserQueryInsert(PrivilegedDatabaseDto database, String query, String username, String password) throws SQLException { final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); - log.trace("connect to database {}", jdbc); + log.trace("connect to database: {}", jdbc); try (Connection connection = DriverManager.getConnection(jdbc, username, password)) { final String call = "{call store_query(?,?,?)}"; log.trace("prepare procedure '{}'", call); @@ -255,7 +256,7 @@ public class MariaDbConfig { public static void insertQueryStore(PrivilegedDatabaseDto database, QueryDto query, UUID userId) throws SQLException { final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); - log.trace("connect to database {}", jdbc); + log.trace("connect to database: {}", jdbc); try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { final PreparedStatement prepareStatement = connection.prepareStatement( "INSERT INTO qs_queries (created_by, query, query_normalized, is_persisted, query_hash, result_hash, result_number, created, executed) VALUES (?,?,?,?,?,?,?,?,?)"); @@ -332,13 +333,27 @@ public class MariaDbConfig { public static void execute(PrivilegedContainerDto container, String query) throws SQLException { final String jdbc = "jdbc:mariadb://" + container.getHost() + ":" + container.getPort(); - log.trace("connect to database {}", jdbc); + log.trace("connect to database: {}", jdbc); try (Connection connection = DriverManager.getConnection(jdbc, container.getUsername(), container.getPassword())) { final Statement statement = connection.createStatement(); statement.executeUpdate(query); } } + public static void dropQueryStore(PrivilegedDatabaseDto database) + throws SQLException { + final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort() + "/" + database.getInternalName(); + log.trace("connect to database: {}", jdbc); + try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { + final Statement statement = connection.createStatement(); + statement.executeUpdate("DROP SEQUENCE IF EXISTS `qs_queries_seq`;"); + statement.executeUpdate("DROP TABLE IF EXISTS `qs_queries`;"); + statement.executeUpdate("DROP PROCEDURE IF EXISTS `hash_table`;"); + statement.executeUpdate("DROP PROCEDURE IF EXISTS `store_query`;"); + statement.executeUpdate("DROP PROCEDURE IF EXISTS `_store_query`;"); + } + } + public static Map<String, List<Object>> describeTableSchema(PrivilegedTableDto table, String username, String password) throws SQLException { final String jdbc = "jdbc:mariadb://" + table.getDatabase().getContainer().getHost() + ":" + table.getDatabase().getContainer().getPort() + "/" + table.getDatabase().getInternalName(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java index 0a69255f1056de6e8f02e671d6835f2daef2640b..1dc008dbebffdd0a02ef0ffb12a12b9f6e8e6f08 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java @@ -42,9 +42,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseUnavailableException, - DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -57,9 +57,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_alreadyAccess_fails() throws UserNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -74,9 +74,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -90,9 +90,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_userNotFound_fails() throws UserNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -118,9 +118,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - NotAllowedException, DatabaseUnavailableException, DatabaseMalformedException, ServiceException { + NotAllowedException, DatabaseUnavailableException, DatabaseMalformedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -143,9 +143,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -159,9 +159,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_userNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, ServiceException { + UserNotFoundException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -177,9 +177,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void revoke_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseUnavailableException, - DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, ServiceException, + DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, MetadataServiceException, SQLException { /* mock */ @@ -206,9 +206,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void revoke_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -222,9 +222,9 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void revoke_userNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, ServiceException { + UserNotFoundException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java index aa424e3aa60a3e64d0b835254506706f1f8bc7b6..c2b04d5aa914b86ef3edde0ebdf5d82f130c1e40 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java @@ -52,9 +52,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseUnavailableException, RemoteUnavailableException, - QueryStoreCreateException, ContainerNotFoundException, DatabaseMalformedException, ServiceException { + QueryStoreCreateException, ContainerNotFoundException, DatabaseMalformedException, MetadataServiceException { /* test */ databaseEndpoint.create(DATABASE_1_CREATE_INTERNAL); @@ -63,7 +63,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void create_noRole_fails() throws RemoteUnavailableException, ContainerNotFoundException, - SQLException, QueryStoreCreateException, DatabaseMalformedException, ServiceException { + SQLException, QueryStoreCreateException, DatabaseMalformedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) @@ -84,9 +84,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_containerNotFound_fails() throws RemoteUnavailableException, ContainerNotFoundException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(ContainerNotFoundException.class) @@ -100,9 +100,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_queryStore_fails() throws RemoteUnavailableException, ContainerNotFoundException, SQLException, - DatabaseMalformedException, QueryStoreCreateException, ServiceException { + DatabaseMalformedException, QueryStoreCreateException, MetadataServiceException { /* mock */ doThrow(ContainerNotFoundException.class) @@ -121,9 +121,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_succeeds() throws DatabaseUnavailableException, RemoteUnavailableException, - DatabaseMalformedException, DatabaseNotFoundException, ServiceException { + DatabaseMalformedException, DatabaseNotFoundException, MetadataServiceException { /* test */ databaseEndpoint.update(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); @@ -131,7 +131,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) - public void update_noRole_fails() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { + public void update_noRole_fails() throws RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -144,9 +144,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_databaseNotFound_fails() throws RemoteUnavailableException, DatabaseNotFoundException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -160,9 +160,9 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void update_password_fails() throws RemoteUnavailableException, DatabaseNotFoundException, SQLException, - DatabaseMalformedException, ServiceException { + DatabaseMalformedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index 6cdb0c6753488d84be16798636d46d42c139392f..c45454b8f3c3ac8238726755e0eda19c063ed1f8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -66,7 +66,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findAllById_succeeds() throws DatabaseUnavailableException, NotAllowedException, QueryNotFoundException, - DatabaseNotFoundException, RemoteUnavailableException, SQLException, ServiceException { + DatabaseNotFoundException, RemoteUnavailableException, SQLException, MetadataServiceException { /* test */ final List<QueryDto> response = generic_findAllById(DATABASE_3_ID, DATABASE_3_PRIVILEGED_DTO, null); @@ -98,7 +98,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, StorageNotFoundException, - SQLException, ServiceException { + SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -113,7 +113,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_acceptCsv_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException, MetadataServiceException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -134,7 +134,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { public void findById_timestamp_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, SidecarExportException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException, MetadataServiceException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -152,7 +152,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ServiceException { + public void findById_fails() throws DatabaseNotFoundException, RemoteUnavailableException, MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -171,7 +171,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { NotAllowedException, SidecarExportException, QueryNotSupportedException, PaginationException, StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -207,7 +207,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { TableMalformedException, NotAllowedException, SidecarExportException, QueryNotSupportedException, PaginationException, StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -227,7 +227,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-query"}) public void create_databaseNotFound_fails() throws NotAllowedException, RemoteUnavailableException, - DatabaseNotFoundException, ServiceException { + DatabaseNotFoundException, MetadataServiceException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -260,7 +260,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME, authorities = {"execute-query"}) - public void create_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, ServiceException { + public void create_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, MetadataServiceException { final ExecuteStatementDto request = ExecuteStatementDto.builder() .statement(QUERY_5_STATEMENT) .build(); @@ -279,7 +279,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test public void getData_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException, - DatabaseUnavailableException, PaginationException, ServiceException { + DatabaseUnavailableException, PaginationException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -308,7 +308,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test public void getData_onlyHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException, - DatabaseUnavailableException, PaginationException, ServiceException { + DatabaseUnavailableException, PaginationException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID)) @@ -332,7 +332,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME) public void getData_private_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, ServiceException { + QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -358,7 +358,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getData_privateAnonymous_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -373,7 +373,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) public void getData_privateNoAccess_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -392,7 +392,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME) public void getData_privateOnlyHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, ServiceException { + QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -416,7 +416,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) public void persist_succeeds() throws NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, QueryStorePersistException, SQLException, UserNotFoundException, QueryNotFoundException, - DatabaseUnavailableException, ServiceException { + DatabaseUnavailableException, MetadataServiceException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -451,7 +451,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) - public void persist_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, ServiceException { + public void persist_noAccess_fails() throws NotAllowedException, RemoteUnavailableException, MetadataServiceException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -470,7 +470,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"persist-query"}) public void persist_databaseNotFound_fails() throws NotAllowedException, RemoteUnavailableException, - DatabaseNotFoundException, ServiceException { + DatabaseNotFoundException, MetadataServiceException { final QueryPersistDto request = QueryPersistDto.builder() .persist(true) .build(); @@ -490,7 +490,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { protected List<QueryDto> generic_findAllById(Long databaseId, PrivilegedDatabaseDto database, Principal principal) throws DatabaseUnavailableException, NotAllowedException, QueryNotFoundException, DatabaseNotFoundException, - RemoteUnavailableException, SQLException, ServiceException { + RemoteUnavailableException, SQLException, MetadataServiceException { /* mock */ if (database != null) { @@ -514,7 +514,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { Principal principal) throws UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, NotAllowedException, QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, SidecarExportException, RemoteUnavailableException, FormatNotAvailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException, MetadataServiceException { /* mock */ when(queryService.findById(DATABASE_3_PRIVILEGED_DTO, subsetId)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 022b043caadc66ec495402fb2f05afb1ccf711ce..29a33d1d9cbb3dd95a5640610d7620a36d1800db 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -52,10 +52,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseUnavailableException, TableMalformedException, DatabaseNotFoundException, TableExistsException, RemoteUnavailableException, SQLException, - TableNotFoundException, QueryMalformedException, ServiceException { + TableNotFoundException, QueryMalformedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -79,9 +79,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -95,9 +95,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_succeeds() throws RemoteUnavailableException, DatabaseUnavailableException, - TableNotFoundException, QueryMalformedException, SQLException, ServiceException { + TableNotFoundException, QueryMalformedException, SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -122,9 +122,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_tableNotFound_fails() throws RemoteUnavailableException, TableNotFoundException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(TableNotFoundException.class) @@ -140,7 +140,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, - SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException, ServiceException, + SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException, MetadataServiceException, NotAllowedException { /* mock */ @@ -166,7 +166,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(TableNotFoundException.class) @@ -183,7 +183,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void createTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, StorageUnavailableException, StorageNotFoundException, ServiceException { + SQLException, StorageUnavailableException, StorageNotFoundException, MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -227,7 +227,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -249,7 +249,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -273,7 +273,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + StorageUnavailableException, StorageNotFoundException, MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -294,7 +294,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -318,7 +318,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void createTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + StorageUnavailableException, StorageNotFoundException, MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -340,7 +340,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -390,7 +390,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -415,7 +415,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -442,7 +442,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccess_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -473,7 +473,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -500,7 +500,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -532,7 +532,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -574,7 +574,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -595,7 +595,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -618,7 +618,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, TableMalformedException, SQLException, QueryMalformedException, - DatabaseUnavailableException, ServiceException { + DatabaseUnavailableException, MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -645,7 +645,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -668,7 +668,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, ServiceException { + SQLException, MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -695,7 +695,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - RemoteUnavailableException, SQLException, NotAllowedException, ServiceException, PaginationException { + RemoteUnavailableException, SQLException, NotAllowedException, MetadataServiceException, PaginationException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID)) @@ -711,7 +711,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_privateNoRole_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -726,7 +726,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void getHistory_privateNoAccess_fails() throws NotAllowedException, RemoteUnavailableException, - TableNotFoundException, ServiceException { + TableNotFoundException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -744,7 +744,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(TableNotFoundException.class) @@ -761,7 +761,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithAnonymousUser public void exportData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, NotAllowedException, StorageUnavailableException, QueryMalformedException, SidecarExportException, RemoteUnavailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException, MetadataServiceException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("deadbeef") .resource(new InputStreamResource(InputStream.nullInputStream())) @@ -782,7 +782,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void exportData_privateNoAccess_fails() throws TableNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) @@ -802,7 +802,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, SidecarImportException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - StorageNotFoundException, SQLException, ServiceException { + StorageNotFoundException, SQLException, MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -844,7 +844,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -865,7 +865,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -888,7 +888,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importData_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, SidecarImportException, QueryMalformedException, - StorageNotFoundException, ServiceException { + StorageNotFoundException, MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -908,7 +908,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") @@ -931,7 +931,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importData_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, SidecarImportException, QueryMalformedException, - StorageNotFoundException, ServiceException { + StorageNotFoundException, MetadataServiceException { final ImportCsvDto request = ImportCsvDto.builder() .skipLines(1L) .lineTermination("\\n") diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index 9f7ad136a8dbed048cd85d3f097d1fa59bd5dac5..b9b814378e9bd537d42c421c3e3fab81d381443f 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -49,9 +49,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, DatabaseUnavailableException, ServiceException { + SQLException, DatabaseUnavailableException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -67,7 +67,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void create_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, ServiceException { + SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -82,9 +82,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_databaseNotFound_fails() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(DatabaseNotFoundException.class) @@ -98,9 +98,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, DatabaseUnavailableException, ViewNotFoundException, ServiceException { + SQLException, DatabaseUnavailableException, ViewNotFoundException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -117,7 +117,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME) public void delete_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, ServiceException { + SQLException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) @@ -133,9 +133,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_databaseNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(ViewNotFoundException.class) @@ -152,7 +152,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException, PaginationException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) @@ -182,7 +182,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_onlyHead_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException, - PaginationException, NotAllowedException, ServiceException { + PaginationException, NotAllowedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) @@ -209,7 +209,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_viewNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException, - ServiceException { + MetadataServiceException { /* mock */ doThrow(ViewNotFoundException.class) @@ -225,7 +225,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"view-database-view-data"}) public void getData_privateNoAccess_fails() throws RemoteUnavailableException, ViewNotFoundException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_3_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java index 30a4d31cfbb288b58817bc52d803d913fa353421..b00f871d5ca92797197e40b898ce95c94463b807 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/DataDatabaseGatewayUnitTest.java @@ -41,7 +41,8 @@ public class DataDatabaseGatewayUnitTest extends AbstractUnitTest { } @Test - public void importFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, ServiceException { + public void importFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, + SidecarImportException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) @@ -75,7 +76,7 @@ public class DataDatabaseGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(SidecarImportException.class, () -> { dataDatabaseSidecarGateway.importFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); }); } @@ -95,7 +96,8 @@ public class DataDatabaseGatewayUnitTest extends AbstractUnitTest { } @Test - public void exportFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, ServiceException { + public void exportFile_succeeds() throws RemoteUnavailableException, StorageNotFoundException, + SidecarExportException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), eq(HttpEntity.EMPTY), eq(Void.class))) @@ -129,7 +131,7 @@ public class DataDatabaseGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(SidecarExportException.class, () -> { dataDatabaseSidecarGateway.exportFile(CONTAINER_1_HOST, CONTAINER_1_PORT, "filename"); }); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java index 0fd20a8025bc209df9c645f4d2b01329660dbf03..b87793a8bcd00c499b74de68748c001750430584 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/InterceptorUnitTest.java @@ -1,9 +1,6 @@ package at.tuwien.gateway; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; -import at.tuwien.exception.StorageNotFoundException; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -15,16 +12,11 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @Log4j2 @@ -36,9 +28,6 @@ public class InterceptorUnitTest extends AbstractUnitTest { @Qualifier("keycloakRestTemplate") private RestTemplate restTemplate; - @Autowired - private DataDatabaseSidecarGateway dataDatabaseSidecarGateway; - @BeforeEach public void beforeEach() { genesis(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java deleted file mode 100644 index 2a02e03466d57116c3c529d5750229e80b015b26..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakSidecarGatewayUnitTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package at.tuwien.gateway; - -import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceConnectionException; -import at.tuwien.exception.ServiceException; -import at.tuwien.test.AbstractUnitTest; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class KeycloakSidecarGatewayUnitTest extends AbstractUnitTest { - - @MockBean - @Qualifier("restTemplate") - private RestTemplate restTemplate; - - @Autowired - private KeycloakGateway keycloakGateway; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void obtainUserToken_succeeds() throws ServiceException, RemoteUnavailableException { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.ok() - .build()); - - /* test */ - final TokenDto response = keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - } - - @Test - public void obtainUserToken_unavailable_fails() { - - /* mock */ - doThrow(HttpServerErrorException.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); - - /* test */ - assertThrows(RemoteUnavailableException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - - @Test - public void obtainUserToken_badRequest_fails() { - - /* mock */ - doThrow(HttpClientErrorException.BadRequest.class) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); - - /* test */ - assertThrows(ServiceException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - - @Test - public void obtainUserToken_statusCode_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .build()); - - /* test */ - assertThrows(ServiceException.class, () -> { - keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); - }); - } - -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java index 1ba4978788d7ee5d05d881d397a453086eaed41c..c224af4cb28604c2554da1942a782932db8d7390 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java @@ -53,7 +53,8 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void getTableById_succeeds() throws TableNotFoundException, RemoteUnavailableException, ServiceException { + public void getTableById_succeeds() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException { final HttpHeaders headers = new HttpHeaders(); headers.set("X-Type", IMAGE_1_JDBC); headers.set("X-Host", CONTAINER_1_HOST); @@ -119,7 +120,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .body(TABLE_1_DTO)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); }); } @@ -139,7 +140,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .headers(headers) .body(TABLE_1_DTO)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); }); } @@ -164,14 +165,14 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); }); } @Test public void getDatabaseByInternalName_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class))) @@ -206,7 +207,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .body(new PrivilegedDatabaseDto[]{DATABASE_1_PRIVILEGED_DTO})); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); }); } @@ -220,7 +221,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME); }); } @@ -240,7 +241,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void getDatabaseById_succeeds() throws RemoteUnavailableException, ServiceException, + public void getDatabaseById_succeeds() throws RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException { final HttpHeaders headers = new HttpHeaders(); headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); @@ -294,7 +295,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getDatabaseById(DATABASE_1_ID); }); } @@ -312,7 +313,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getDatabaseById(DATABASE_1_ID); }); } @@ -332,14 +333,14 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .headers(headers) .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getDatabaseById(DATABASE_1_ID); }); } } @Test - public void getContainerById_succeeds() throws RemoteUnavailableException, ContainerNotFoundException, ServiceException { + public void getContainerById_succeeds() throws RemoteUnavailableException, ContainerNotFoundException, MetadataServiceException { final HttpHeaders headers = new HttpHeaders(); headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); @@ -392,7 +393,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getContainerById(CONTAINER_1_ID); }); } @@ -412,7 +413,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getContainerById(CONTAINER_1_ID); }); } @@ -431,13 +432,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getContainerById(CONTAINER_1_ID); }); } @Test - public void getViewById_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ServiceException { + public void getViewById_succeeds() throws RemoteUnavailableException, ViewNotFoundException, MetadataServiceException { final HttpHeaders headers = new HttpHeaders(); headers.set("X-Type", IMAGE_1_JDBC); headers.set("X-Host", CONTAINER_1_HOST); @@ -494,7 +495,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); }); } @@ -514,7 +515,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); }); } @@ -537,13 +538,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); }); } @Test - public void getUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, ServiceException { + public void getUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(UserDto.class))) @@ -592,7 +593,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getUserById(USER_1_ID); }); } @@ -606,14 +607,14 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getUserById(USER_1_ID); }); } @Test public void getPrivilegedUserById_succeeds() throws RemoteUnavailableException, UserNotFoundException, - ServiceException { + MetadataServiceException { final HttpHeaders headers = new HttpHeaders(); headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); @@ -668,7 +669,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getPrivilegedUserById(USER_1_ID); }); } @@ -688,7 +689,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getPrivilegedUserById(USER_1_ID); }); } @@ -707,13 +708,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getPrivilegedUserById(USER_1_ID); }); } @Test - public void getAccess_succeeds() throws RemoteUnavailableException, NotAllowedException, ServiceException { + public void getAccess_succeeds() throws RemoteUnavailableException, NotAllowedException, MetadataServiceException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(DatabaseAccessDto.class))) @@ -775,7 +776,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); }); } @@ -789,13 +790,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID); }); } @Test - public void getIdentifiers_witSubset_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { + public void getIdentifiers_witSubset_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) @@ -808,7 +809,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void getIdentifiers_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, ServiceException { + public void getIdentifiers_succeeds() throws RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(IdentifierDto[].class))) @@ -857,7 +858,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); }); } @@ -871,13 +872,13 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID); }); } @Test - public void updateTableStatistics_succeeds() throws RemoteUnavailableException, ServiceException, TableNotFoundException { + public void updateTableStatistics_succeeds() throws RemoteUnavailableException, MetadataServiceException, TableNotFoundException { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), eq(HttpEntity.EMPTY), eq(Void.class))) @@ -925,7 +926,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { .build()); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.updateTableStatistics(DATABASE_1_ID, TABLE_1_ID); }); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java deleted file mode 100644 index 9075ec2a02d0420b9fe0cec8c307a9dc8ac1c13e..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/handlers/ApiExceptionHandlerTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package at.tuwien.handlers; - -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.boot.test.context.SpringBootTest; -import org.springframework.http.HttpStatus; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.bind.annotation.ResponseStatus; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import static at.tuwien.test.utils.EndpointUtils.getErrorCodes; -import static at.tuwien.test.utils.EndpointUtils.getExceptions; - -@Log4j2 -@ExtendWith(SpringExtension.class) -@SpringBootTest -public class ApiExceptionHandlerTest extends AbstractUnitTest { - - @Test - public void handle_succeeds() throws ClassNotFoundException, IOException { - final List<Method> handlers = Arrays.asList(ApiExceptionHandler.class.getMethods()); - final List<String> errorCodes = getErrorCodes(); - - /* test */ - for (Class<?> exception : getExceptions()) { - final Optional<Method> optional = handlers.stream().filter(h -> Arrays.asList(h.getParameterTypes()).contains(exception)).findFirst(); - if (optional.isEmpty()) { - Assertions.fail("Exception " + exception.getName() + " does not have a corresponding handle method in the endpoint"); - } - final Method method = optional.get(); - /* exception */ - Assertions.assertNotNull(exception.getDeclaredAnnotation(ResponseStatus.class).code()); - Assertions.assertNotEquals(exception.getDeclaredAnnotation(ResponseStatus.class).code(), HttpStatus.INTERNAL_SERVER_ERROR); - Assertions.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()); - } - } -} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java index dec1fcc0282993ba0a7b527dc4dda7088fc0e4a5..88bad7b06124df10f5a3cec690e993ac5b8ffcd5 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java @@ -2,8 +2,8 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; @@ -63,7 +63,7 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { @Test public void onMessage_succeeds(CapturedOutput output) throws TableNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final Message request = buildMessage("dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID, "{\"id\":4,\"date\":\"2023-10-03\",\"mintemp\":15.0,\"rainfall\":0.2}", new HashMap<>()); /* mock */ @@ -78,7 +78,7 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { @Test @Disabled public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { final Message request = buildMessage("dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID, "{\"id\":4,\"date\":\"2023-10-03\",\"mintemp\":15.0,\"rainfall\":0.2}", new HashMap<>()); /* mock */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java index ab4a171c8915440055934c904247832ce0cf7549..648e36caa938f11e564ce772b00c25ba24d18281 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java @@ -2,8 +2,8 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; @@ -76,7 +76,7 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Test public void onMessage_messageMalformed_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { final Message request = buildMessage("dbrepo.1.1", "{,}", new HashMap<>()); /* mock */ @@ -90,7 +90,7 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Test public void onMessage_tableNotFound_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { final Message request = buildMessage("dbrepo.1.1", "{\"id\":1}", new HashMap<>()); /* mock */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java index e53f6ad88f92095ae405d586d39a399e0a6b0304..c89d53282ce3086cb28a88125b07549780b83d6b 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java @@ -9,6 +9,7 @@ import at.tuwien.mapper.MariaDbMapper; import at.tuwien.mapper.MariaDbMapperImpl; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -38,6 +39,11 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { @Autowired private MariaDbMapper mariaDbMapper; + @BeforeAll + public static void beforeAll() throws InterruptedException { + Thread.sleep(1000) /* wait for test container some more */; + } + @BeforeEach public void beforeEach() throws SQLException { genesis(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index 4bfa5b443a19ed6bf7af2c55183fd94fa0366baf..bd57eafacc47a1107e309be0fba94de75371bc95 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -3,13 +3,14 @@ package at.tuwien.service; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.ContainerNotFoundException; +import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.QueueServiceRabbitMqImpl; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,6 +43,11 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { @Container private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); + @BeforeAll + public static void beforeAll() throws InterruptedException { + Thread.sleep(1000) /* wait for test container some more */; + } + @BeforeEach public void beforeEach() throws SQLException { genesis(); @@ -51,8 +57,8 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { } @Test - public void insert_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, ServiceException { + public void insert_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, + TableNotFoundException, MetadataServiceException { final Map<String, Object> request = new HashMap<>() {{ put("id", 4L); put("date", "2023-10-03"); @@ -61,9 +67,6 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { put("rainfall", 0.2); }}; - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -75,16 +78,13 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { } @Test - public void insert_onlyMandatoryFields_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, TableNotFoundException, ServiceException { + public void insert_onlyMandatoryFields_succeeds() throws SQLException, RemoteUnavailableException, + TableNotFoundException, MetadataServiceException { final Map<String, Object> request = new HashMap<>() {{ put("id", 5L); put("date", "2023-10-04"); }}; - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) .thenReturn(TABLE_1_PRIVILEGED_DTO); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index d13a37531b06e3572547b1f472e970ada78a7faa..aeaae0ecf2626ff88027a210bd8e24a5c66d4ede 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -1,14 +1,21 @@ package at.tuwien.service; +import at.tuwien.ExportResourceDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.config.S3Config; import at.tuwien.exception.*; +import at.tuwien.gateway.DataDatabaseSidecarGateway; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; +import com.google.common.hash.Hashing; import lombok.extern.log4j.Log4j2; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.RandomUtils; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,15 +27,19 @@ import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.math.BigInteger; +import java.nio.charset.Charset; import java.sql.SQLException; import java.time.Instant; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @Log4j2 @@ -43,9 +54,18 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @MockBean private MetadataServiceGateway metadataServiceGateway; + @MockBean + private DataDatabaseSidecarGateway dataDatabaseSidecarGateway; + + @MockBean + private StorageService storageService; + @Container private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); + @Autowired + private S3Config s3Config; + @BeforeEach public void beforeEach() throws SQLException { genesis(); @@ -56,8 +76,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, - QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, + MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -96,9 +116,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void execute_joinWithAlias_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, - QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + public void execute_joinWithAlias_succeeds() throws QueryStoreInsertException, TableMalformedException, + SQLException, QueryNotFoundException, UserNotFoundException, NotAllowedException, + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -126,8 +146,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_oneResult_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException, - QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, + MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -157,8 +177,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Test public void execute_oneResultPagination_succeeds() throws QueryStoreInsertException, TableMalformedException, - SQLException, QueryNotFoundException, InterruptedException, UserNotFoundException, NotAllowedException, - RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + SQLException, QueryNotFoundException, UserNotFoundException, NotAllowedException, + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -187,8 +207,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void findAll_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + public void findAll_succeeds() throws SQLException, QueryNotFoundException, NotAllowedException, + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* test */ final List<QueryDto> response = findAll_generic(null); @@ -198,8 +218,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void findAll_onlyPersisted_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + public void findAll_onlyPersisted_succeeds() throws SQLException, QueryNotFoundException, NotAllowedException, + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* test */ final List<QueryDto> response = findAll_generic(true); @@ -208,8 +228,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void findAll_onlyNonPersisted_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + public void findAll_onlyNonPersisted_succeeds() throws SQLException, QueryNotFoundException, NotAllowedException, + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { /* test */ final List<QueryDto> response = findAll_generic(false); @@ -218,9 +238,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void findById_succeeds() throws SQLException, QueryNotFoundException, InterruptedException, - UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + public void findById_succeeds() throws SQLException, QueryNotFoundException, UserNotFoundException, + NotAllowedException, RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, + InterruptedException { /* test */ findById_generic(QUERY_1_ID); @@ -236,9 +256,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void persist_succeeds() throws SQLException, InterruptedException, QueryStorePersistException, - QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, - ServiceException, DatabaseNotFoundException { + public void persist_succeeds() throws SQLException, QueryStorePersistException, QueryNotFoundException, + UserNotFoundException, NotAllowedException, RemoteUnavailableException, MetadataServiceException, + DatabaseNotFoundException, InterruptedException { /* mock */ when(metadataServiceGateway.getUserById(QUERY_2_CREATED_BY)) @@ -252,9 +272,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } @Test - public void persist_unPersist_succeeds() throws SQLException, InterruptedException, QueryStorePersistException, - QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, - ServiceException, DatabaseNotFoundException { + public void persist_unPersist_succeeds() throws SQLException, QueryStorePersistException, QueryNotFoundException, + UserNotFoundException, NotAllowedException, RemoteUnavailableException, MetadataServiceException, + DatabaseNotFoundException, InterruptedException { /* mock */ when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY)) @@ -267,9 +287,40 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { assertFalse(response.getIsPersisted()); } - protected void findById_generic(Long queryId) throws InterruptedException, NotAllowedException, - RemoteUnavailableException, SQLException, UserNotFoundException, QueryNotFoundException, ServiceException, - DatabaseNotFoundException { + @Test + public void createQueryStore_succeeds() throws SQLException, QueryStoreCreateException, InterruptedException { + + /* mock */ + MariaDbConfig.dropQueryStore(DATABASE_1_PRIVILEGED_DTO); + + /* test */ + createQueryStore_generic(DATABASE_1_INTERNALNAME); + } + + @Test + public void createQueryStore_fails() { + + /* test */ + assertThrows(QueryStoreCreateException.class, () -> { + createQueryStore_generic(DATABASE_1_INTERNALNAME); + }); + } + + @Test + public void export_succeeds() throws SQLException, StorageUnavailableException, QueryMalformedException, + SidecarExportException, MetadataServiceException, RemoteUnavailableException, IOException, + StorageNotFoundException, InterruptedException { + + /* mock */ + MariaDbConfig.dropQueryStore(DATABASE_1_PRIVILEGED_DTO); + + /* test */ + export_generic(); + } + + protected void findById_generic(Long queryId) throws NotAllowedException, RemoteUnavailableException, SQLException, + UserNotFoundException, QueryNotFoundException, MetadataServiceException, DatabaseNotFoundException, + InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -287,9 +338,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { assertEquals(DATABASE_1_ID, response.getDatabaseId()); } - protected List<QueryDto> findAll_generic(Boolean filterPersisted) throws InterruptedException, SQLException, - QueryNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + protected List<QueryDto> findAll_generic(Boolean filterPersisted) throws SQLException, QueryNotFoundException, + NotAllowedException, RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, + InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -305,8 +356,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { } protected void persist_generic(Long queryId, List<IdentifierDto> identifiers, Boolean persist) - throws InterruptedException, RemoteUnavailableException, SQLException, QueryStorePersistException, - ServiceException, DatabaseNotFoundException { + throws RemoteUnavailableException, SQLException, QueryStorePersistException, MetadataServiceException, + DatabaseNotFoundException, InterruptedException { /* pre-condition */ Thread.sleep(1000) /* wait for test container some more */; @@ -321,4 +372,38 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { queryService.persist(DATABASE_1_PRIVILEGED_DTO, queryId, persist); } + protected void createQueryStore_generic(String databaseName) throws SQLException, QueryStoreCreateException, + InterruptedException { + + /* pre-condition */ + Thread.sleep(1000) /* wait for test container some more */; + + /* test */ + queryService.createQueryStore(CONTAINER_1_PRIVILEGED_DTO, databaseName); + final List<Map<String, Object>> response = MariaDbConfig.listQueryStore(DATABASE_1_PRIVILEGED_DTO); + assertEquals(0, response.size()); + } + + protected void export_generic() throws StorageUnavailableException, SQLException, + QueryMalformedException, SidecarExportException, MetadataServiceException, RemoteUnavailableException, + StorageNotFoundException, IOException, InterruptedException { + final String filename = "68b329da9893e34099c7d8ad5cb9c940"; + + /* pre-condition */ + Thread.sleep(1000) /* wait for test container some more */; + + /* mock */ + FileUtils.deleteQuietly(new File(s3Config.getS3FilePath() + "/" + filename)); + doNothing() + .when(dataDatabaseSidecarGateway) + .exportFile(anyString(), anyInt(), eq(filename)); + when(storageService.getResource(anyString())) + .thenReturn(EXPORT_RESOURCE_DTO); + + /* test */ + final ExportResourceDto response = queryService.export(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, Instant.now(), filename); + assertEquals(filename, response.getFilename()); + assertNotNull(response.getResource().getInputStream()); + } + } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index 86a0442ef60a4dc80365c48b8567a15ad04f9e85..65ec32c0d501524028e7caef05cb58e997d19446 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -25,6 +25,7 @@ import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -74,6 +75,11 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Container private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); + @BeforeAll + public static void beforeAll() throws InterruptedException { + Thread.sleep(1000) /* wait for test container some more */; + } + @BeforeEach public void beforeEach() throws SQLException { genesis(); @@ -84,9 +90,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + public void updateTuple_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, + TableNotFoundException, TableMalformedException, QueryMalformedException, MetadataServiceException { /* modify row based on primary key */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -100,9 +105,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -120,9 +122,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_modifyPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void updateTuple_modifyPrimaryKey_succeeds() throws SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, + MetadataServiceException { /* modify row primary key based on primary key */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -137,9 +139,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -157,9 +156,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_missingPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void updateTuple_missingPrimaryKey_succeeds() throws SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, + MetadataServiceException { /* modify row based on non-primary key column */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -173,9 +172,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -193,9 +189,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updateTuple_notInOrder_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, + public void updateTuple_notInOrder_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + MetadataServiceException { /* modify row based on non-primary key column */ final TupleUpdateDto request = TupleUpdateDto.builder() .data(new HashMap<>() {{ @@ -209,9 +205,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -229,9 +222,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void createTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + public void createTuple_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, + TableNotFoundException, TableMalformedException, QueryMalformedException, StorageUnavailableException, + StorageNotFoundException, MetadataServiceException { /* add row with primary key */ final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ @@ -243,9 +236,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -263,9 +253,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void createTuple_notInOrder_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, + public void createTuple_notInOrder_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, ServiceException { + StorageUnavailableException, StorageNotFoundException, MetadataServiceException { /* add row with primary key */ final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ @@ -277,9 +267,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -297,9 +284,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void deleteTuple_succeeds() throws InterruptedException, SQLException, RemoteUnavailableException, - ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, - ServiceException { + public void deleteTuple_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, + TableNotFoundException, TableMalformedException, QueryMalformedException, MetadataServiceException { /* delete row based on primary key */ final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ @@ -307,9 +293,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -323,9 +306,9 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void deleteTuple_withoutPrimaryKey_succeeds() throws InterruptedException, SQLException, - RemoteUnavailableException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, - QueryMalformedException, ServiceException { + public void deleteTuple_withoutPrimaryKey_succeeds() throws SQLException, RemoteUnavailableException, + ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, + MetadataServiceException { /* remove row based on non-primary key */ final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ @@ -334,9 +317,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { }}) .build(); - /* pre-condition */ - Thread.sleep(1000) /* wait for test container some more */; - /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) .thenReturn(CONTAINER_1_PRIVILEGED_DTO); @@ -350,8 +330,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void getSchemas_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException, - DatabaseMalformedException { + public void getSchemas_succeeds() throws TableNotFoundException, SQLException, DatabaseMalformedException { /* test */ final List<TableDto> response = tableService.getSchemas(DATABASE_1_PRIVILEGED_DTO); @@ -462,7 +441,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void create_succeeds() throws TableNotFoundException, TableMalformedException, SQLException, - QueryMalformedException, TableExistsException { + TableExistsException { /* test */ final TableDto response = tableService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO); @@ -538,7 +517,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { @Test public void create_needSequence_succeeds() throws TableNotFoundException, TableMalformedException, SQLException, - QueryMalformedException, TableExistsException { + TableExistsException { /* mock */ MariaDbConfig.dropTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNALNAME); @@ -665,8 +644,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void importDataset_withSeparatorAndQuoteAndNullElement_succeeds() throws SidecarImportException, ServiceException, SQLException, - QueryMalformedException, RemoteUnavailableException, StorageNotFoundException, IOException { + public void importDataset_withSeparatorAndQuoteAndNullElement_succeeds() throws SidecarImportException, + SQLException, QueryMalformedException, RemoteUnavailableException, StorageNotFoundException, IOException { final ImportCsvDto request = ImportCsvDto.builder() .location("weather_aus.csv") .separator(';') @@ -688,8 +667,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void importDataset_malformedData_fails() throws ServiceException, RemoteUnavailableException, StorageNotFoundException, - IOException { + public void importDataset_malformedData_fails() throws RemoteUnavailableException, StorageNotFoundException, + IOException, SidecarImportException { final ImportCsvDto request = ImportCsvDto.builder() .location("weather_aus.csv") .separator(';') @@ -712,9 +691,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { } @Test - public void exportDataset_succeeds() throws ServiceException, SQLException, - QueryMalformedException, RemoteUnavailableException, StorageNotFoundException, StorageUnavailableException, - SidecarExportException { + public void exportDataset_succeeds() throws SQLException, QueryMalformedException, RemoteUnavailableException, + StorageNotFoundException, StorageUnavailableException, SidecarExportException { final ExportResourceDto mock = ExportResourceDto.builder() .filename("weather_aus.csv") .resource(new InputStreamResource(InputStream.nullInputStream())) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..13806e93ddd1cbeb7a8e1c0ab4e0fe38db0830ad --- /dev/null +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/utils/UserUtilTest.java @@ -0,0 +1,40 @@ +package at.tuwien.utils; + +import at.tuwien.test.BaseTest; +import org.junit.jupiter.api.Test; + + +import static org.junit.jupiter.api.Assertions.*; + +public class UserUtilTest extends BaseTest { + + @Test + public void hasRole_succeeds() { + assertTrue(UserUtil.hasRole(USER_1_PRINCIPAL, "find-container")); + } + + @Test + public void hasRole_principalMissing_fails() { + assertFalse(UserUtil.hasRole(null, "find-container")); + } + + @Test + public void hasRole_roleMissing_fails() { + assertFalse(UserUtil.hasRole(USER_1_PRINCIPAL, null)); + } + + @Test + public void getId_succeeds() { + assertEquals(USER_1_ID, UserUtil.getId(USER_1_PRINCIPAL)); + } + + @Test + public void getId_principalMissing_fails() { + assertNull(UserUtil.getId(null)); + } + + @Test + public void getId_roleMissing_fails() { + assertNull(UserUtil.getId(USER_LOCAL_ADMIN_PRINCIPAL)); + } +} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b12313dfe957d0f02f05c58bfce1066979973d07 --- /dev/null +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java @@ -0,0 +1,101 @@ +package at.tuwien.validation; + +import at.tuwien.annotations.MockAmqp; +import at.tuwien.exception.PaginationException; +import at.tuwien.exception.QueryNotSupportedException; +import at.tuwien.test.AbstractUnitTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@Log4j2 +@ExtendWith(SpringExtension.class) +@AutoConfigureMockMvc +@SpringBootTest +@AutoConfigureObservability +@MockAmqp +public class EndpointValidatorUnitTest extends AbstractUnitTest { + + @Autowired + private EndpointValidator endpointValidator; + + @Test + public void validateDataParams_succeeds() throws Exception { + + /* test */ + endpointValidator.validateDataParams(null, null); + } + + @Test + public void validateDataParams_onlyPage_fails() { + + /* test */ + assertThrows(PaginationException.class, () -> { + endpointValidator.validateDataParams(0L, null); + }); + } + + @Test + public void validateDataParams_negativePage_fails() { + + /* test */ + assertThrows(PaginationException.class, () -> { + endpointValidator.validateDataParams(-1L, 10L); + }); + } + + @Test + public void validateDataParams_onlySize_fails() { + + /* test */ + assertThrows(PaginationException.class, () -> { + endpointValidator.validateDataParams(null, 10L); + }); + } + + @Test + public void validateDataParams_zeroSize_fails() { + + /* test */ + assertThrows(PaginationException.class, () -> { + endpointValidator.validateDataParams(0L, 0L); + }); + } + + @Test + public void validateForbiddenStatements_succeeds() throws QueryNotSupportedException { + + /* test */ + endpointValidator.validateForbiddenStatements("SELECT country FROM some_table"); + } + + @Test + public void validateForbiddenStatements_fails() { + + /* test */ + assertThrows(QueryNotSupportedException.class, () -> { + endpointValidator.validateForbiddenStatements("SELECT COUNT(id) FROM some_table"); + }); + } + + @Test + public void validateForbiddenStatements_lowercase_fails() { + + /* test */ + assertThrows(QueryNotSupportedException.class, () -> { + endpointValidator.validateForbiddenStatements("SELECT COUNT(id) FROM some_table"); + }); + } + +} diff --git a/dbrepo-data-service/rest-service/src/test/resources/application.properties b/dbrepo-data-service/rest-service/src/test/resources/application.properties index 07eb7f642bd62128618f3d0b86d04c0ba4743644..764d9609c99fb1609b24d6d7f61d6d8d6b06ec00 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-data-service/rest-service/src/test/resources/application.properties @@ -29,4 +29,4 @@ spring.rabbitmq.password=guest # s3 dbrepo.s3.accessKeyId=minioadmin -dbrepo.s3.secretAccessKey=minioadmin \ No newline at end of file +dbrepo.s3.secretAccessKey=minioadmin diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index 8aa52308bf3f237a0f84cca7d0f3a34edd1d32c3..80fdd15f1daff7625508eb8d46d9b54332a5150f 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -1,8 +1,6 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserDetailsDto; -import at.tuwien.config.GatewayConfig; import at.tuwien.exception.*; import at.tuwien.gateway.KeycloakGateway; import jakarta.servlet.ServletException; @@ -13,45 +11,30 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; -import java.util.List; - @Log4j2 @Component public class BasicAuthenticationProvider implements AuthenticationManager { - private final GatewayConfig gatewayConfig; private final AuthTokenFilter authTokenFilter; private final KeycloakGateway keycloakGateway; @Autowired - public BasicAuthenticationProvider(GatewayConfig gatewayConfig, AuthTokenFilter authTokenFilter, - KeycloakGateway keycloakGateway) { - this.gatewayConfig = gatewayConfig; + public BasicAuthenticationProvider(AuthTokenFilter authTokenFilter, KeycloakGateway keycloakGateway) { this.authTokenFilter = authTokenFilter; this.keycloakGateway = keycloakGateway; } @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { - if (auth.getName().equals(gatewayConfig.getAdminUsername()) - && auth.getCredentials().toString().equals(gatewayConfig.getAdminPassword())) { - log.trace("current user is {}: skip authentication", gatewayConfig.getAdminUsername()); - final UserDetails userDetails = UserDetailsDto.builder() - .username(auth.getName()) - .authorities(List.of(new SimpleGrantedAuthority("admin"))) - .build(); - return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } - log.trace("current user is {}: begin authentication", auth.getName()); try { final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } catch (ServletException | RemoteUnavailableException | ServiceException e) { + } catch (ServletException | CredentialsInvalidException | AccountNotSetupException | + AuthServiceConnectionException e) { throw new BadCredentialsException("Failed to authenticate with authentication service", e); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..20955bcdb36912e3f8dd4ed695a4e688f1177ccf --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java @@ -0,0 +1,45 @@ +package at.tuwien.auth; + +import at.tuwien.api.keycloak.TokenDto; +import at.tuwien.config.GatewayConfig; +import at.tuwien.exception.*; +import at.tuwien.gateway.KeycloakGateway; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +import java.io.IOException; +import java.util.List; + +@Log4j2 +public class InternalRequestInterceptor implements ClientHttpRequestInterceptor { + + private final GatewayConfig gatewayConfig; + private final KeycloakGateway keycloakGateway; + + public InternalRequestInterceptor(GatewayConfig gatewayConfig, KeycloakGateway keycloakGateway) { + this.gatewayConfig = gatewayConfig; + this.keycloakGateway = keycloakGateway; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + final HttpHeaders headers = request.getHeaders(); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + try { + final TokenDto token = keycloakGateway.obtainUserToken(gatewayConfig.getSystemUsername(), + gatewayConfig.getSystemPassword()); + headers.setBearerAuth(token.getAccessToken()); + log.trace("set bearer token for internal user: {}", gatewayConfig.getSystemUsername()); + } catch (AuthServiceConnectionException | CredentialsInvalidException | AccountNotSetupException e) { + log.error("Failed to obtain token for internal user: {}", gatewayConfig.getSystemUsername()); + throw new IOException("Failed to obtain token for internal user", e); + } + return execution.execute(request, body); + } +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index b04aff18ce5a49d68c01519a97b3550b14bddc6e..6ebd6744576fd034db2faf569ffb764e43d9c7f8 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -1,19 +1,16 @@ package at.tuwien.config; +import at.tuwien.auth.InternalRequestInterceptor; +import at.tuwien.gateway.KeycloakGateway; import lombok.Getter; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; -import java.util.List; - @Log4j2 @Getter @Configuration @@ -22,30 +19,26 @@ public class GatewayConfig { @Value("${dbrepo.endpoints.metadataService}") private String metadataEndpoint; - @Value("${dbrepo.admin.username}") - private String adminUsername; + @Value("${dbrepo.system.username}") + private String systemUsername; + + @Value("${dbrepo.system.password}") + private String systemPassword; - @Value("${dbrepo.admin.password}") - private String adminPassword; + private final KeycloakGateway keycloakGateway; + + @Autowired + public GatewayConfig(KeycloakGateway keycloakGateway) { + this.keycloakGateway = keycloakGateway; + } @Bean public RestTemplate restTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(metadataEndpoint)); - log.debug("add basic authentication for metadata service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), - clientHttpRequestInterceptor())); + .add(new InternalRequestInterceptor(this, keycloakGateway)); return restTemplate; } - @Bean - public ClientHttpRequestInterceptor clientHttpRequestInterceptor() { - return (request, body, execution) -> { - final HttpHeaders headers = request.getHeaders(); - headers.setAccept(List.of(MediaType.APPLICATION_JSON)); - return execution.execute(request, body); - }; - } - } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java index 4d258d496aa6ebe825ac2d84a1f00a1b4f9c0298..e0d7d0321513387f1e1c9c235c1c4b51e309be1d 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java @@ -2,16 +2,12 @@ package at.tuwien.config; import at.tuwien.interceptor.KeycloakInterceptor; import lombok.Getter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; -import java.util.List; - @Getter @Configuration public class KeycloakConfig { @@ -31,20 +27,12 @@ public class KeycloakConfig { @Value("${dbrepo.keycloak.clientSecret}") private String keycloakClientSecret; - private final ClientHttpRequestInterceptor clientHttpRequestInterceptor; - - @Autowired - public KeycloakConfig(ClientHttpRequestInterceptor clientHttpRequestInterceptor) { - this.clientHttpRequestInterceptor = clientHttpRequestInterceptor; - } - @Bean("keycloakRestTemplate") public RestTemplate brokerRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(keycloakEndpoint)); restTemplate.getInterceptors() - .addAll(List.of(new KeycloakInterceptor(keycloakUsername, keycloakPassword, keycloakEndpoint), - clientHttpRequestInterceptor)); + .add(new KeycloakInterceptor(keycloakUsername, keycloakPassword, keycloakEndpoint)); return restTemplate; } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java index 2aa39d5d4354912cd2101861328341f00725c3d3..1560c14b7aaa6272c76515a734a1ad99f7075222 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java @@ -43,8 +43,7 @@ public class WebSecurityConfig { } @Bean - public SecurityFilterChain filterChain(HttpSecurity http, KeycloakGateway keycloakGateway, - GatewayConfig gatewayConfig) + public SecurityFilterChain filterChain(HttpSecurity http, KeycloakGateway keycloakGateway) throws Exception { final OrRequestMatcher internalEndpoints = new OrRequestMatcher( new AntPathRequestMatcher("/actuator/**", "GET"), @@ -86,8 +85,8 @@ public class WebSecurityConfig { http.addFilterBefore(authTokenFilter(), UsernamePasswordAuthenticationFilter.class ); - http.addFilterBefore(new BasicAuthenticationFilter(new BasicAuthenticationProvider(gatewayConfig, - authTokenFilter(), keycloakGateway)), + http.addFilterBefore(new BasicAuthenticationFilter(new BasicAuthenticationProvider(authTokenFilter(), + keycloakGateway)), UsernamePasswordAuthenticationFilter.class ); return http.build(); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ContainerNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ContainerNotFoundException.java deleted file mode 100644 index 8d3b2b2243f220da74d0635ce24ec43a3583e03f..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ContainerNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.container.missing") -public class ContainerNotFoundException extends Exception { - - public ContainerNotFoundException(String message) { - super(message); - } - - public ContainerNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public ContainerNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java deleted file mode 100644 index ff4ce77cf2b00c229f0b5ccec991efbcb81b3d1c..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.database.missing") -public class DatabaseNotFoundException extends Exception { - - public DatabaseNotFoundException(String message) { - super(message); - } - - public DatabaseNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public DatabaseNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/FormatNotAvailableException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/FormatNotAvailableException.java deleted file mode 100644 index d46b7b2baaee08ddbec3bb3682e9f9b640498e85..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/FormatNotAvailableException.java +++ /dev/null @@ -1,23 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -import java.io.IOException; - -@ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE, reason = "error.subset.format") -public class FormatNotAvailableException extends IOException { - - public FormatNotAvailableException(String msg) { - super(msg); - } - - public FormatNotAvailableException(String msg, Throwable thr) { - super(msg + ": " + thr.getLocalizedMessage(), thr); - } - - public FormatNotAvailableException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/NotAllowedException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/NotAllowedException.java deleted file mode 100644 index 33b2f7f9e3daa933c35bb947332fd30c30c94c82..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/NotAllowedException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.FORBIDDEN, reason = "error.request.forbidden") -public class NotAllowedException extends Exception { - - public NotAllowedException(String message) { - super(message); - } - - public NotAllowedException(String message, Throwable thr) { - super(message, thr); - } - - public NotAllowedException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/PaginationException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/PaginationException.java deleted file mode 100644 index 53446bdb646dabd621510fe543380a936b3d290d..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/PaginationException.java +++ /dev/null @@ -1,22 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.pagination.malformed") -public class PaginationException extends Exception { - - public PaginationException(String msg) { - super(msg); - } - - public PaginationException(String msg, Throwable thr) { - super(msg + ": " + thr.getLocalizedMessage(), thr); - } - - public PaginationException(Throwable thr) { - super(thr); - } - -} - diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryNotFoundException.java deleted file mode 100644 index d55be584cf25a3acdc403617971fe08baee82721..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.query.missing") -public class QueryNotFoundException extends Exception { - - public QueryNotFoundException(String message) { - super(message); - } - - public QueryNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public QueryNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageNotFoundException.java deleted file mode 100644 index bbb780ea919d33c64c34f719f99c5ed30eae326a..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.storage.missing") -public class StorageNotFoundException extends Exception { - - public StorageNotFoundException(String message) { - super(message); - } - - public StorageNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public StorageNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableExistsException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableExistsException.java deleted file mode 100644 index fdc23ad7d3a254ed02cbefd49ba733aac3e277bd..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableExistsException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.CONFLICT, reason = "error.table.exists") -public class TableExistsException extends Exception { - - public TableExistsException(String message) { - super(message); - } - - public TableExistsException(String message, Throwable thr) { - super(message, thr); - } - - public TableExistsException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableNotFoundException.java deleted file mode 100644 index 199ce9c74cc0ba8f37b2ad55eb86cd2c6877a2ab..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.table.missing") -public class TableNotFoundException extends Exception { - - public TableNotFoundException(String message) { - super(message); - } - - public TableNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public TableNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/UserNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/UserNotFoundException.java deleted file mode 100644 index 5aeabab27de7abf68f88df1346019e398dc921e6..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/UserNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.user.missing") -public class UserNotFoundException extends Exception { - - public UserNotFoundException(String message) { - super(message); - } - - public UserNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public UserNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewNotFoundException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewNotFoundException.java deleted file mode 100644 index 7ba64c5e8fc0ddb90c5845d483105c849ac4bd78..0000000000000000000000000000000000000000 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewNotFoundException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "error.view.missing") -public class ViewNotFoundException extends Exception { - - public ViewNotFoundException(String message) { - super(message); - } - - public ViewNotFoundException(String message, Throwable thr) { - super(message, thr); - } - - public ViewNotFoundException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java index ecac6865f6e4704b915e10016afe8a5b25afaa63..23dc08a55d366f6560bcbaafbf6c79a94dfc2af3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/DataDatabaseSidecarGateway.java @@ -3,9 +3,28 @@ package at.tuwien.gateway; import at.tuwien.exception.*; public interface DataDatabaseSidecarGateway { + + /** + * Imports a given dataset name into the given database. + * @param hostname The database hostname. + * @param port The database port. + * @param filename The dataset name. + * @throws StorageNotFoundException The dataset name was not found in the storage service. + * @throws RemoteUnavailableException Connection to the sidecar could not be established. + * @throws SidecarImportException The sidecar failed to import the dataset. + */ void importFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException; + RemoteUnavailableException, SidecarImportException; + /** + * Exports a given dataset name from the given database. + * @param hostname The database hostname. + * @param port The database port. + * @param filename The dataset name. + * @throws StorageNotFoundException The dataset name was not found in the storage service. + * @throws RemoteUnavailableException Connection to the sidecar could not be established. + * @throws SidecarExportException The sidecar failed to export the dataset. + */ void exportFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - ServiceException, RemoteUnavailableException; + SidecarExportException, RemoteUnavailableException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java index 1058119a25c8b5de2affbc05b72cd9417c7887a7..9e6a5f56bda37fc1b3d9af9fca8158a5fcce27f7 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -1,14 +1,13 @@ package at.tuwien.gateway; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceConnectionException; -import at.tuwien.exception.ServiceException; - -import javax.naming.ServiceUnavailableException; +import at.tuwien.exception.AccountNotSetupException; +import at.tuwien.exception.AuthServiceConnectionException; +import at.tuwien.exception.CredentialsInvalidException; public interface KeycloakGateway { - TokenDto obtainUserToken(String username, String password) throws RemoteUnavailableException, ServiceException; + TokenDto obtainUserToken(String username, String password) throws AuthServiceConnectionException, + CredentialsInvalidException, AccountNotSetupException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java index 4c01a40a447954ae666bf7ef9d330b5879b85e59..d16c8c8eba81efd22a64757a6dd1eb51dc56318f 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java @@ -24,10 +24,10 @@ public interface MetadataServiceGateway { * @return The container with privileged connection information, if successful. * @throws ContainerNotFoundException The table was not found in the metadata service. * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, - ContainerNotFoundException, ServiceException; + ContainerNotFoundException, MetadataServiceException; /** * Get a database with given id from the metadata service. @@ -36,10 +36,10 @@ public interface MetadataServiceGateway { * @return The database, if successful. * @throws DatabaseNotFoundException The database was not found in the metadata service. * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException; + MetadataServiceException; /** * Get a database with given internal name from the metadata service. @@ -48,10 +48,10 @@ public interface MetadataServiceGateway { * @return The database, if successful. * @throws DatabaseNotFoundException The database was not found in the metadata service. * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException, - RemoteUnavailableException, ServiceException; + RemoteUnavailableException, MetadataServiceException; /** * Get a table with given database id and table id from the metadata service. @@ -61,10 +61,10 @@ public interface MetadataServiceGateway { * @return The table, if successful. * @throws TableNotFoundException The table was not found in the metadata service. * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, RemoteUnavailableException, - ServiceException; + MetadataServiceException; /** * Get a view with given database id and view id from the metadata service. @@ -73,10 +73,10 @@ public interface MetadataServiceGateway { * @return The view, if successful. * @throws ViewNotFoundException The view was not found in the metadata service. * @throws RemoteUnavailableException The remote service is not available. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, ViewNotFoundException, - ServiceException; + MetadataServiceException; /** * Get a user with given user id from the metadata service. @@ -85,9 +85,9 @@ public interface MetadataServiceGateway { * @return The user, if successful. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws UserNotFoundException The user was not found in the metadata service. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ - UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, ServiceException; + UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException; /** * Get a user with given user id from the metadata service. @@ -96,10 +96,10 @@ public interface MetadataServiceGateway { * @return The user, if successful. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws UserNotFoundException The user was not found in the metadata service. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException; + MetadataServiceException; /** * Get database access for a given user and database id from the metadata service. @@ -108,10 +108,10 @@ public interface MetadataServiceGateway { * @return The database access, if successful. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws NotAllowedException The access to this database is denied for the given user. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, NotAllowedException, - ServiceException; + MetadataServiceException; /** * Get a list of identifiers for a given database id and optional subset id. @@ -120,9 +120,9 @@ public interface MetadataServiceGateway { * @return The list of identifiers. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws DatabaseNotFoundException The database was not found. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ - List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws ServiceException, + List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws MetadataServiceException, RemoteUnavailableException, DatabaseNotFoundException; /** @@ -131,7 +131,7 @@ public interface MetadataServiceGateway { * @param tableId The table id. * @throws RemoteUnavailableException The remote service is not available and invalid data was returned. * @throws TableNotFoundException The table was not found. - * @throws ServiceException The remote service returned invalid data. + * @throws MetadataServiceException The remote service returned invalid data. */ - void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, ServiceException, RemoteUnavailableException; + void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, MetadataServiceException, RemoteUnavailableException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java index b3e7c3bd41545e07b344406d00b29e9daecd0aab..841aace47460c99a09a5d1cff0a26cf03bed1ce9 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/DataDatabaseSidecarGatewayImpl.java @@ -24,13 +24,13 @@ public class DataDatabaseSidecarGatewayImpl implements DataDatabaseSidecarGatewa @Override public void importFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, SidecarImportException { final ResponseEntity<Void> response; final String url = "http://" + hostname + ":" + port + "/sidecar/import/" + filename; log.debug("import file into data database sidecar"); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(null), Void.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + } catch (HttpServerErrorException e) { log.error("Failed to import dataset with filename: {}: {}", filename, e.getMessage()); throw new RemoteUnavailableException("Failed to import dataset: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest e) { @@ -39,19 +39,19 @@ public class DataDatabaseSidecarGatewayImpl implements DataDatabaseSidecarGatewa } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to import dataset with filename: {}: service responded unsuccessful: {}", filename, response.getStatusCode()); - throw new ServiceException("Failed to import dataset: service responded unsuccessful: " + response.getStatusCode()); + throw new SidecarImportException("Failed to import dataset: service responded unsuccessful: " + response.getStatusCode()); } } @Override public void exportFile(String hostname, Integer port, String filename) throws StorageNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, SidecarExportException { final ResponseEntity<Void> response; final String url = "http://" + hostname + ":" + port + "/sidecar/export/" + filename; log.debug("export file from data database sidecar: {}", url); try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(null), Void.class); - } catch (ResourceAccessException | HttpServerErrorException e) { + } catch (HttpServerErrorException e) { log.error("Failed to export dataset with filename: {}: {}", filename, e.getMessage()); throw new RemoteUnavailableException("Failed to export dataset: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest e) { @@ -60,7 +60,7 @@ public class DataDatabaseSidecarGatewayImpl implements DataDatabaseSidecarGatewa } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to export dataset with filename: {}: service responded unsuccessful: {}", filename, response.getStatusCode()); - throw new ServiceException("Failed to export dataset: service responded unsuccessful: " + response.getStatusCode()); + throw new SidecarExportException("Failed to export dataset: service responded unsuccessful: " + response.getStatusCode()); } } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 545e259097951b3ed79d34c73bef72ccd2270b6b..f95bb3fe76a1e95786fae0b109ee7c1619954209 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -1,61 +1,69 @@ package at.tuwien.gateway.impl; +import at.tuwien.api.auth.KeycloakErrorDto; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.config.KeycloakConfig; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.ServiceConnectionException; -import at.tuwien.exception.ServiceException; +import at.tuwien.exception.*; import at.tuwien.gateway.KeycloakGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @Log4j2 @Service public class KeycloakGatewayImpl implements KeycloakGateway { - private final RestTemplate restTemplate; private final KeycloakConfig keycloakConfig; @Autowired - public KeycloakGatewayImpl(RestTemplate restTemplate, KeycloakConfig keycloakConfig) { - this.restTemplate = restTemplate; + public KeycloakGatewayImpl(KeycloakConfig keycloakConfig) { this.keycloakConfig = keycloakConfig; } @Override - public TokenDto obtainUserToken(String username, String password) throws RemoteUnavailableException, ServiceException { + public TokenDto obtainUserToken(String username, String password) throws AuthServiceConnectionException, + CredentialsInvalidException, AccountNotSetupException { final HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); payload.add("username", username); payload.add("password", password); payload.add("grant_type", "password"); - payload.add("scope", "openid roles attributes"); + payload.add("scope", "openid roles"); payload.add("client_id", keycloakConfig.getKeycloakClient()); payload.add("client_secret", keycloakConfig.getKeycloakClientSecret()); final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/dbrepo/protocol/openid-connect/token"; - log.debug("request user token from url {}", url); + log.trace("request user token from url: {}", url); + log.trace("request username: {}", username); + log.trace("request password: {}", password != null ? "(set)" : "(not set)"); + log.trace("request client_id: {}", keycloakConfig.getKeycloakClient()); + log.trace("request client_secret: {}", keycloakConfig.getKeycloakClientSecret()); final ResponseEntity<TokenDto> response; try { - response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + response = new RestTemplate() + .exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); } catch (HttpServerErrorException e) { log.error("Failed to obtain user token: {}", e.getMessage()); - throw new RemoteUnavailableException("Failed to obtain user token: " + e.getMessage(), e); - } catch (Exception e) { - log.error("Failed to obtain user token: unexpected response: {}", e.getMessage(), e); - throw new ServiceException("Failed to obtain user token: unexpected response: " + e.getMessage(), e); - } - if (!response.getStatusCode().equals(HttpStatus.OK)) { - log.error("Failed to obtain user token: service responded unsuccessful: {}", response.getStatusCode()); - throw new ServiceException("obtain user token: service responded unsuccessful: " + response.getStatusCode()); + throw new AuthServiceConnectionException("Service unavailable", e); + } catch (HttpClientErrorException.BadRequest e) { + if (e.getResponseBodyAsByteArray() != null && e.getResponseBodyAsByteArray().length > 0) { + final KeycloakErrorDto error = e.getResponseBodyAs(KeycloakErrorDto.class); + if (error != null && error.getError().equals("invalid_grant")) { + log.error("Failed to obtain user token: {}", error.getErrorDescription()); + throw new AccountNotSetupException(error.getErrorDescription()); + } + } + log.error("Failed to obtain user token: bad request"); + throw new CredentialsInvalidException("Bad request", e); + } catch (HttpClientErrorException.Unauthorized e) { + log.error("Failed to obtain user token: invalid credentials"); + throw new CredentialsInvalidException("Invalid credentials", e); } return response.getBody(); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java index 1fcf3e50ee3df4487eae8492867aa4952413c699..a3fda6482c2d18cb75bab577644f8ce630314e6e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java @@ -46,7 +46,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedContainerDto getContainerById(Long containerId) throws RemoteUnavailableException, - ContainerNotFoundException, ServiceException { + ContainerNotFoundException, MetadataServiceException { final ResponseEntity<ContainerDto> response; try { response = restTemplate.exchange("/api/container/" + containerId, HttpMethod.GET, HttpEntity.EMPTY, @@ -60,15 +60,15 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (response.getStatusCode() != HttpStatus.OK) { log.error("Failed to find container with id {}: service responded unsuccessful: {}", containerId, response.getStatusCode()); - throw new ServiceException("Failed to find container: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find container: service responded unsuccessful: " + response.getStatusCode()); } if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { log.error("Failed to find all privileged container headers"); - throw new ServiceException("Failed to find all privileged container headers"); + throw new MetadataServiceException("Failed to find all privileged container headers"); } if (response.getBody() == null) { log.error("Failed to find container with id {}: body is empty", containerId); - throw new ServiceException("Failed to find container with id " + containerId + ": body is empty"); + throw new MetadataServiceException("Failed to find container with id " + containerId + ": body is empty"); } final PrivilegedContainerDto container = metadataMapper.containerDtoToPrivilegedContainerDto(response.getBody()); container.setUsername(response.getHeaders().get("X-Username").get(0)); @@ -78,7 +78,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException, - ServiceException { + MetadataServiceException { final ResponseEntity<PrivilegedDatabaseDto> response; try { response = restTemplate.exchange("/api/database/" + id, HttpMethod.GET, HttpEntity.EMPTY, @@ -92,15 +92,15 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (response.getStatusCode() != HttpStatus.OK) { log.error("Failed to find database with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); } if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { log.error("Failed to find all privileged database headers"); - throw new ServiceException("Failed to find all privileged database headers"); + throw new MetadataServiceException("Failed to find all privileged database headers"); } if (response.getBody() == null) { log.error("Failed to find database with id {}: body is empty", id); - throw new ServiceException("Failed to find database with id " + id + ": body is empty"); + throw new MetadataServiceException("Failed to find database with id " + id + ": body is empty"); } final PrivilegedDatabaseDto database = response.getBody(); database.getContainer().setUsername(response.getHeaders().get("X-Username").get(0)); @@ -111,7 +111,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { final ResponseEntity<PrivilegedDatabaseDto[]> response; try { response = restTemplate.exchange("/api/database/", HttpMethod.GET, HttpEntity.EMPTY, PrivilegedDatabaseDto[].class); @@ -121,7 +121,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK) || response.getBody() == null) { log.error("Failed to find database with internal name {}: service responded unsuccessful: {}", internalName, response.getStatusCode()); - throw new ServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode()); } if (response.getBody().length != 1) { log.error("Failed to find database with internal name {}: body is empty", internalName); @@ -132,7 +132,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException, - RemoteUnavailableException, ServiceException { + RemoteUnavailableException, MetadataServiceException { final ResponseEntity<TableDto> response; try { response = restTemplate.exchange("/api/database/" + databaseId + "/table/" + id, HttpMethod.GET, HttpEntity.EMPTY, TableDto.class); @@ -145,15 +145,15 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find table with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find table: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find table: service responded unsuccessful: " + response.getStatusCode()); } if (!response.getHeaders().keySet().containsAll(List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database", "X-Sidecar-Host", "X-Sidecar-Port"))) { log.error("Failed to find all privileged table headers"); - throw new ServiceException("Failed to find all privileged table headers"); + throw new MetadataServiceException("Failed to find all privileged table headers"); } if (response.getBody() == null) { log.error("Failed to find table with id {}: body is empty", id); - throw new ServiceException("Failed to find table with id " + id + ": body is empty"); + throw new MetadataServiceException("Failed to find table with id " + id + ": body is empty"); } final PrivilegedTableDto table = metadataMapper.tableDtoToPrivilegedTableDto(response.getBody()); table.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Type").get(0)); @@ -170,7 +170,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public PrivilegedViewDto getViewById(Long databaseId, Long id) throws RemoteUnavailableException, - ViewNotFoundException, ServiceException { + ViewNotFoundException, MetadataServiceException { final ResponseEntity<ViewDto> response; try { response = restTemplate.exchange("/api/database/" + databaseId + "/view/" + id, HttpMethod.GET, HttpEntity.EMPTY, ViewDto.class); @@ -183,15 +183,15 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find view with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); - throw new ServiceException("Failed to find view: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find view: service responded unsuccessful: " + response.getStatusCode()); } if (!response.getHeaders().keySet().containsAll(List.of("X-Type", "X-Host", "X-Port", "X-Username", "X-Password", "X-Database"))) { log.error("Failed to find all privileged view headers"); - throw new ServiceException("Failed to find all privileged view headers"); + throw new MetadataServiceException("Failed to find all privileged view headers"); } if (response.getBody() == null) { log.error("Failed to find view with id {}: body is empty", id); - throw new ServiceException("Failed to find view with id " + id + ": body is empty"); + throw new MetadataServiceException("Failed to find view with id " + id + ": body is empty"); } final PrivilegedViewDto table = metadataMapper.viewDtoToPrivilegedViewDto(response.getBody()); table.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Type").get(0)); @@ -205,7 +205,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException { + MetadataServiceException { final ResponseEntity<UserDto> response; try { response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); @@ -218,18 +218,18 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to find user with id {}: body is empty", userId); - throw new ServiceException("Failed to find user with id " + userId + ": body is empty"); + throw new MetadataServiceException("Failed to find user with id " + userId + ": body is empty"); } return response.getBody(); } @Override public PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, - ServiceException { + MetadataServiceException { final ResponseEntity<UserDto> response; try { response = restTemplate.exchange("/api/user/" + userId, HttpMethod.GET, HttpEntity.EMPTY, UserDto.class); @@ -242,15 +242,15 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find user: service responded unsuccessful: " + response.getStatusCode()); } if (!response.getHeaders().keySet().containsAll(List.of("X-Username", "X-Password"))) { log.error("Failed to find all privileged user headers"); - throw new ServiceException("Failed to find all privileged user headers"); + throw new MetadataServiceException("Failed to find all privileged user headers"); } if (response.getBody() == null) { log.error("Failed to find user with id {}: body is empty", userId); - throw new ServiceException("Failed to find user with id " + userId + ": body is empty"); + throw new MetadataServiceException("Failed to find user with id " + userId + ": body is empty"); } final PrivilegedUserDto user = metadataMapper.userDtoToPrivilegedUserDto(response.getBody()); user.setUsername(response.getHeaders().get("X-Username").get(0)); @@ -260,7 +260,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { @Override public DatabaseAccessDto getAccess(Long databaseId, UUID userId) throws RemoteUnavailableException, - NotAllowedException, ServiceException { + NotAllowedException, MetadataServiceException { final ResponseEntity<DatabaseAccessDto> response; try { response = restTemplate.exchange("/api/database/" + databaseId + "/access/" + userId, HttpMethod.GET, HttpEntity.EMPTY, DatabaseAccessDto.class); @@ -273,17 +273,17 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find database access for user with id {}: service responded unsuccessful: {}", userId, response.getStatusCode()); - throw new ServiceException("Failed to find database access: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find database access: service responded unsuccessful: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to find database access: body is empty"); - throw new ServiceException("Failed to find database access: body is empty"); + throw new MetadataServiceException("Failed to find database access: body is empty"); } return response.getBody(); } @Override - public List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws ServiceException, + public List<IdentifierDto> getIdentifiers(@NotNull Long databaseId, Long subsetId) throws MetadataServiceException, RemoteUnavailableException, DatabaseNotFoundException { final ResponseEntity<IdentifierDto[]> response; final String url = "/api/identifier?dbid=" + databaseId + (subsetId != null ? ("&qid=" + subsetId) : ""); @@ -299,17 +299,17 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find identifiers for database with id {} and subset with id {}: service responded unsuccessful: {}", databaseId, subsetId, response.getStatusCode()); - throw new ServiceException("Failed to find identifiers for database: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to find identifiers for database: service responded unsuccessful: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to find identifiers: body is null"); - throw new ServiceException("Failed to find identifiers: body is null"); + throw new MetadataServiceException("Failed to find identifiers: body is null"); } return List.of(response.getBody()); } @Override - public void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, ServiceException, + public void updateTableStatistics(Long databaseId, Long tableId) throws TableNotFoundException, MetadataServiceException, RemoteUnavailableException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table/" + tableId; @@ -324,7 +324,7 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to update table statistic for table with id {}: service responded unsuccessful: {}", tableId, response.getStatusCode()); - throw new ServiceException("Failed to update table statistic for database: service responded unsuccessful: " + response.getStatusCode()); + throw new MetadataServiceException("Failed to update table statistic for database: service responded unsuccessful: " + response.getStatusCode()); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java index 192fc30a61bcf68743d0f9eec36a190a3bc4941b..fac47a3d80f6030f5e7d4d561c4262123e9feea7 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java @@ -64,7 +64,7 @@ public class DefaultListener implements MessageListener { log.error("Failed to read object: {}", e.getMessage()); } catch (SQLException | RemoteUnavailableException e) { log.error("Failed to insert tuple: {}", e.getMessage()); - } catch (TableNotFoundException | ServiceException e) { + } catch (TableNotFoundException | MetadataServiceException e) { log.error("Failed to find table: {}", e.getMessage()); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 8cadf146b1e6acc6cac355d3890a492993a0fff5..b6b782a04c6c2c9c353f837caee4c8f1f2b213ec 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -94,6 +94,13 @@ public interface MariaDbMapper { return statement; } + @Named("dropView") + default String dropViewRawQuery(String viewName) { + final String statement = "DROP VIEW IF EXISTS `" + viewName + "`;"; + log.trace("mapped drop view statement: {}", statement); + return statement; + } + default String databaseViewSelectRawQuery() { final String statement = "SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'VIEW' AND t.`TABLE_NAME` != 'qs_queries' AND t.`TABLE_NAME` = ?"; log.trace("mapped select view statement: {}", statement); @@ -439,9 +446,20 @@ public interface MariaDbMapper { return statement.toString(); } - default String subsetToRawExportQuery(String query, Instant timestamp, String filePath) { - final StringBuilder statement = new StringBuilder(query.replaceAll(";", "")) - .append(" FOR SYSTEM_TIME AS OF TIMESTAMP'") + default String subsetToRawTemporaryViewQuery(String viewName, String query) { + final StringBuilder statement = new StringBuilder("CREATE VIEW `") + .append(viewName) + .append("` AS (") + .append(query) + .append(");"); + log.debug("mapped temporary view query: {}", statement); + return statement.toString(); + } + + default String subsetToRawExportQuery(String viewName, Instant timestamp, String filePath) { + final StringBuilder statement = new StringBuilder("SELECT * FROM `") + .append(viewName) + .append("` FOR SYSTEM_TIME AS OF TIMESTAMP'") .append(mariaDbFormatter.format(timestamp)) .append("'") .append(" INTO OUTFILE '") diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java index 7c2575b9cc348724f801dfd7e67d322b5ddd2070..3c3ff101fead4b51caadc8c207848d2b962f98eb 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java @@ -28,7 +28,9 @@ public interface SubsetService { QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId, Long page, Long size, SortTypeDto sortDirection, String sortColumn) - throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException; + throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, + UserNotFoundException, NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, + MetadataServiceException; QueryResultDto reExecute(PrivilegedDatabaseDto database, QueryDto query, Long page, Long size, SortTypeDto sortDirection, String sortColumn) throws TableMalformedException, @@ -45,11 +47,12 @@ public interface SubsetService { * @return The list of queries. */ List<QueryDto> findAll(PrivilegedDatabaseDto database, Boolean filterPersisted) throws SQLException, - QueryNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException; + QueryNotFoundException, NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, + MetadataServiceException; ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp, String filename) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException; + StorageUnavailableException, MetadataServiceException, RemoteUnavailableException; Long executeCountNonPersistent(PrivilegedDatabaseDto database, String statement, Instant timestamp) throws SQLException, QueryMalformedException, TableMalformedException; @@ -62,7 +65,9 @@ public interface SubsetService { * @return The query. * @throws QueryNotFoundException The query store did not return a query */ - QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, NotAllowedException, RemoteUnavailableException, UserNotFoundException, ServiceException, DatabaseNotFoundException; + QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, + NotAllowedException, RemoteUnavailableException, UserNotFoundException, DatabaseNotFoundException, + MetadataServiceException; /** * Inserts a query and metadata to the query store of a given database id. diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java index 98ed0ec7aea96a0c757d480d2829e2dfb82a2665..50894eb77a46b3b2fc0f77d7ebe0f99b73e895af 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java @@ -105,7 +105,7 @@ public interface TableService { QueryMalformedException; void importDataset(PrivilegedTableDto table, ImportCsvDto data) throws SidecarImportException, - StorageNotFoundException, SQLException, QueryMalformedException, ServiceException, RemoteUnavailableException; + StorageNotFoundException, SQLException, QueryMalformedException, RemoteUnavailableException; void deleteTuple(PrivilegedTableDto table, TupleDeleteDto data) throws SQLException, TableMalformedException, QueryMalformedException; @@ -118,5 +118,5 @@ public interface TableService { ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws SQLException, SidecarExportException, StorageNotFoundException, StorageUnavailableException, - QueryMalformedException, ServiceException, RemoteUnavailableException; + QueryMalformedException, RemoteUnavailableException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java index 3455c320cd10c2e488220843db8ac3d644ef902d..5acca0018de6bc3e29de49aea9f1da4ae95ff492 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -58,5 +58,5 @@ public interface ViewService { ExportResourceDto exportDataset(PrivilegedDatabaseDto database, ViewDto view, Instant timestamp) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException; + StorageUnavailableException, RemoteUnavailableException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java index b2d3f1b5504faec2313b6fc7b6b8b9b522b8fdab..c8b49fd4cb5b91637b14d2325806254bd1bda527 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java @@ -72,9 +72,10 @@ public class StorageServiceS3Impl implements StorageService { @Override public ExportResourceDto getResource(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException { - final InputStream stream = getObject(bucket, key); + final InputStreamResource resource = new InputStreamResource(getObject(bucket, key)); + log.trace("return export resource with filename: {}", key); return ExportResourceDto.builder() - .resource(new InputStreamResource(stream)) + .resource(resource) .filename(key) .build(); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java index 2ab2f7b349fe6cf2ba2129679a22024e9167c0fc..3d19276196895efc00834b60383ddfa226a46bc3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java @@ -19,12 +19,16 @@ import at.tuwien.mapper.MariaDbMapper; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.SubsetService; import at.tuwien.service.StorageService; +import com.google.common.hash.Hashing; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import net.sf.jsqlparser.JSQLParserException; +import org.apache.commons.lang3.RandomUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.sql.*; import java.time.Instant; import java.util.LinkedList; @@ -58,7 +62,8 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs } @Override - public void createQueryStore(PrivilegedContainerDto container, String databaseName) throws SQLException, QueryStoreCreateException { + public void createQueryStore(PrivilegedContainerDto container, String databaseName) throws SQLException, + QueryStoreCreateException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(container, databaseName); final Connection connection = dataSource.getConnection(); try { @@ -88,8 +93,8 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs public QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId, Long page, Long size, SortTypeDto sortDirection, String sortColumn) throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException, - UserNotFoundException, NotAllowedException, RemoteUnavailableException, ServiceException, - DatabaseNotFoundException { + UserNotFoundException, NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException, + MetadataServiceException { final Long queryId = storeQuery(database, statement, timestamp, userId); final QueryDto query = findById(database, queryId); return reExecute(database, query, page, size, sortDirection, sortColumn); @@ -120,7 +125,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public List<QueryDto> findAll(PrivilegedDatabaseDto database, Boolean filterPersisted) throws SQLException, - QueryNotFoundException, RemoteUnavailableException, ServiceException, DatabaseNotFoundException { + QueryNotFoundException, RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException { final List<IdentifierDto> identifiers = metadataServiceGateway.getIdentifiers(database.getId(), null); final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); @@ -153,13 +158,21 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp, String filename) throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException { + StorageUnavailableException, RemoteUnavailableException { final String filePath = s3Config.getS3FilePath() + "/" + filename; + final String viewName = "ex_" + Hashing.sha512() + .hashString(new String(RandomUtils.nextBytes(256), Charset.defaultCharset()), Charset.defaultCharset()) + .toString() + .substring(0, 60); final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); try { /* export to data database sidecar */ - connection.prepareStatement(mariaDbMapper.subsetToRawExportQuery(query.getQuery(), timestamp, filePath)) + connection.prepareStatement(mariaDbMapper.subsetToRawTemporaryViewQuery(viewName, query.getQuery())) + .executeUpdate(); + connection.prepareStatement(mariaDbMapper.subsetToRawExportQuery(viewName, timestamp, filePath)) + .executeUpdate(); + connection.prepareStatement(mariaDbMapper.dropViewRawQuery(viewName)) .executeUpdate(); connection.commit(); } catch (SQLException e) { @@ -208,7 +221,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs @Override public QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException, - RemoteUnavailableException, UserNotFoundException, ServiceException, DatabaseNotFoundException { + RemoteUnavailableException, UserNotFoundException, DatabaseNotFoundException, MetadataServiceException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); try { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java index be15d46895d37f665120f58b047ae52fb7d7742f..e913c0cb82f22cd12654c7cd23d160bf68b5ef87 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java @@ -245,8 +245,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table } @Override - public void importDataset(PrivilegedTableDto table, ImportCsvDto data) - throws StorageNotFoundException, SQLException, QueryMalformedException, ServiceException, RemoteUnavailableException { + public void importDataset(PrivilegedTableDto table, ImportCsvDto data) throws StorageNotFoundException, + SQLException, QueryMalformedException, RemoteUnavailableException, SidecarImportException { /* import .csv from blob storage to sidecar */ dataDatabaseSidecarGateway.importFile(table.getDatabase().getContainer().getSidecarHost(), table.getDatabase().getContainer().getSidecarPort(), data.getLocation()); /* import .csv from sidecar to database */ @@ -297,8 +297,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table } @Override - public void createTuple(PrivilegedTableDto table, TupleDto data) throws SQLException, - QueryMalformedException, TableMalformedException, StorageUnavailableException, StorageNotFoundException { + public void createTuple(PrivilegedTableDto table, TupleDto data) throws SQLException, QueryMalformedException, + TableMalformedException, StorageUnavailableException, StorageNotFoundException { log.trace("create tuple: {}", data); /* for each LOB-like data-column, retrieve the bytes and replace the value */ for (String key : data.getData().keySet()) { @@ -385,8 +385,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table @Override public ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws SQLException, - StorageNotFoundException, StorageUnavailableException, QueryMalformedException, ServiceException, - RemoteUnavailableException { + StorageNotFoundException, StorageUnavailableException, QueryMalformedException, RemoteUnavailableException, + SidecarExportException { final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv"; final String filePath = s3Config.getS3FilePath() + "/" + fileName; final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java index 6f88c409737605671eb31e8b151e9a35ae23afa5..3cdba35f085491334300cc3fb5a3ab3ee30801fd 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java @@ -174,7 +174,7 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe final Connection connection = dataSource.getConnection(); try { /* drop view if exists */ - connection.prepareStatement("DROP VIEW IF EXISTS `" + view.getInternalName() + "`;") + connection.prepareStatement(mariaDbMapper.dropViewRawQuery(view.getInternalName())) .execute(); connection.commit(); } catch (SQLException e) { @@ -214,8 +214,8 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe @Override public ExportResourceDto exportDataset(PrivilegedDatabaseDto database, ViewDto view, Instant timestamp) - throws SQLException, QueryMalformedException, StorageNotFoundException, - StorageUnavailableException, ServiceException, RemoteUnavailableException { + throws SQLException, QueryMalformedException, StorageNotFoundException, StorageUnavailableException, + RemoteUnavailableException, SidecarExportException { final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv"; final String filePath = s3Config.getS3FilePath() + "/" + fileName; final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); diff --git a/dbrepo-metadata-service/Dockerfile b/dbrepo-metadata-service/Dockerfile index 75fe485c16073094c202a476cd55ddf5c6fb84e7..1a37bf7e7e0a87c9c4e9caac814f005b3847badf 100644 --- a/dbrepo-metadata-service/Dockerfile +++ b/dbrepo-metadata-service/Dockerfile @@ -34,9 +34,9 @@ RUN apk add --no-cache curl bash jq WORKDIR /app -USER 65534 +USER 1001 -COPY --from=build --chown=65534 ./rest-service/target/dbrepo-metadata-service-rest-service-*.jar ./metadata-service.jar +COPY --from=build --chown=1001 ./rest-service/target/dbrepo-metadata-service-rest-service-*.jar ./metadata-service.jar # non-root port EXPOSE 8080 diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java index 4b9eefa16d30fcc264a4673aaf6ddde8f1d4aeb0..9b8ad90ea55d8d4aba75e637e4f9906fcc7e86d9 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/auth/KeycloakErrorDto.java @@ -6,6 +6,8 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; +import java.io.Serializable; + @Getter @Setter @Builder @@ -13,7 +15,7 @@ import lombok.extern.jackson.Jacksonized; @AllArgsConstructor @Jacksonized @ToString -public class KeycloakErrorDto { +public class KeycloakErrorDto implements Serializable { @NotNull @Schema(example = "invalid_grant") @@ -23,4 +25,6 @@ public class KeycloakErrorDto { @JsonProperty("error_description") private String errorDescription; + private String errorMessage; + } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java new file mode 100644 index 0000000000000000000000000000000000000000..8f7d795fdbb0a529fa4492c18f9028016e306d9e --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/RoleRepresentationDto.java @@ -0,0 +1,34 @@ +package at.tuwien.api.keycloak; + +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +import java.util.UUID; + +/** + * https://www.keycloak.org/docs-api/22.0.1/rest-api/index.html#RoleRepresentation + */ +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class RoleRepresentationDto { + + private UUID id; + + private String name; + + private String description; + + private Boolean scopeParamRequired; + + private Boolean composite; + + private Boolean clientRole; + + private UUID containerId; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java index 0ebaffff10441d984ea13005d8dc1ff3db6954cb..fe4b69550259023b135bf2ae43a70c85c888cce0 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/keycloak/UserCreateDto.java @@ -32,4 +32,8 @@ public class UserCreateDto { @NotNull private List<CredentialDto> credentials; + private List<String> realmRoles; + + private List<String> groups; + } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index 9a50f5c0545c8351b5fae16157b171d2f52dd870..c869e41637659675e317281fd55092e3b331fc6b 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -86,13 +86,13 @@ public class TableColumn implements Comparable<TableColumn> { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_concepts", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) private TableColumnConcept concept; - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_units", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index ef3bee26370857c035b7df3971f6d95e9924854a..0fdc80b428c3120888362bed339edbd9097f0ac4 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -58,6 +58,7 @@ <keycloak-testcontainer.version>3.2.0</keycloak-testcontainer.version> <aws-s3.version>2.25.23</aws-s3.version> <jackson.version>2.15.2</jackson.version> + <minio.version>8.5.7</minio.version> </properties> <dependencies> @@ -248,6 +249,11 @@ <version>${testcontainers.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>minio</artifactId> + <version>${testcontainers.version}</version> + </dependency> <dependency> <groupId>com.github.dasniko</groupId> <artifactId>testcontainers-keycloak</artifactId> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java new file mode 100644 index 0000000000000000000000000000000000000000..6efa16fa8757fbfcf218f09f0750a500d40161b3 --- /dev/null +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceConnectionException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "error.broker.connection") +public class BrokerServiceConnectionException extends Exception { + + public BrokerServiceConnectionException(String msg) { + super(msg); + } + + public BrokerServiceConnectionException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public BrokerServiceConnectionException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageUnavailableException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java similarity index 52% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageUnavailableException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java index b25bac260eba40176933114765c0633de3caa21a..86201c5d691bdede33bca6bef2606125b29775de 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/StorageUnavailableException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerServiceException.java @@ -3,18 +3,18 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.storage.missing") -public class StorageUnavailableException extends Exception { +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.broker.invalid") +public class BrokerServiceException extends Exception { - public StorageUnavailableException(String message) { + public BrokerServiceException(String message) { super(message); } - public StorageUnavailableException(String message, Throwable thr) { + public BrokerServiceException(String message, Throwable thr) { super(message, thr); } - public StorageUnavailableException(Throwable thr) { + public BrokerServiceException(Throwable thr) { super(thr); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceConnectionException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java similarity index 57% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceConnectionException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java index 069e1d774a564e7286bd6cbc73d6d501f7e81562..0125a781add4e384e43ec87690b0f8afaeb30c92 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceConnectionException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceConnectionException.java @@ -4,17 +4,17 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "error.data.connection") -public class ServiceConnectionException extends Exception { +public class DataServiceConnectionException extends Exception { - public ServiceConnectionException(String msg) { + public DataServiceConnectionException(String msg) { super(msg); } - public ServiceConnectionException(String msg, Throwable thr) { + public DataServiceConnectionException(String msg, Throwable thr) { super(msg + ": " + thr.getLocalizedMessage(), thr); } - public ServiceConnectionException(Throwable thr) { + public DataServiceConnectionException(Throwable thr) { super(thr); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java similarity index 59% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java index 70bef91528a3731b387b6ab55d95a7a1c99f4572..f76e662a655593ffe5991ec84da207b58df052b2 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ServiceException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataServiceException.java @@ -4,17 +4,17 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.data.invalid") -public class ServiceException extends Exception { +public class DataServiceException extends Exception { - public ServiceException(String message) { + public DataServiceException(String message) { super(message); } - public ServiceException(String message, Throwable thr) { + public DataServiceException(String message, Throwable thr) { super(message, thr); } - public ServiceException(Throwable thr) { + public DataServiceException(Throwable thr) { super(thr); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseUnavailableException.java diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java new file mode 100644 index 0000000000000000000000000000000000000000..d5f399c40205b886607f5fc1c22d17d9b159f6e4 --- /dev/null +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExternalServiceException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.external.invalid") +public class ExternalServiceException extends Exception { + + public ExternalServiceException(String message) { + super(message); + } + + public ExternalServiceException(String message, Throwable thr) { + super(message, thr); + } + + public ExternalServiceException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceConnectionException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java similarity index 56% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceConnectionException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java index 6a91dac23aeaf7ff7efd0b5439e344606ce968a7..329de6ffc4b82b859da0ea41aca7ed99a3b1802c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceConnectionException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceConnectionException.java @@ -4,17 +4,17 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "error.metadata.connection") -public class ServiceConnectionException extends Exception { +public class MetadataServiceConnectionException extends Exception { - public ServiceConnectionException(String msg) { + public MetadataServiceConnectionException(String msg) { super(msg); } - public ServiceConnectionException(String msg, Throwable thr) { + public MetadataServiceConnectionException(String msg, Throwable thr) { super(msg + ": " + thr.getLocalizedMessage(), thr); } - public ServiceConnectionException(Throwable thr) { + public MetadataServiceConnectionException(Throwable thr) { super(thr); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java similarity index 58% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java index a543d02c9a4fe32335332eeef980c6283e4c4450..a6784d6dd01ed0c60379246373b26d3c49a8875d 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ServiceException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/MetadataServiceException.java @@ -4,17 +4,17 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.metadata.invalid") -public class ServiceException extends Exception { +public class MetadataServiceException extends Exception { - public ServiceException(String message) { + public MetadataServiceException(String message) { super(message); } - public ServiceException(String message, Throwable thr) { + public MetadataServiceException(String message, Throwable thr) { super(message, thr); } - public ServiceException(Throwable thr) { + public MetadataServiceException(Throwable thr) { super(thr); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryMalformedException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryNotSupportedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotSupportedException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryNotSupportedException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotSupportedException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreCreateException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreCreateException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreGCException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreGCException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreGCException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreGCException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreInsertException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreInsertException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStorePersistException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStorePersistException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/RemoteUnavailableException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/RemoteUnavailableException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/SidecarExportException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SidecarExportException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/SidecarExportException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SidecarExportException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/SidecarImportException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SidecarImportException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/SidecarImportException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SidecarImportException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableMalformedException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableSchemaException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableSchemaException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableSchemaException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableSchemaException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewMalformedException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewSchemaException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewSchemaException.java similarity index 100% rename from dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewSchemaException.java rename to dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewSchemaException.java diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index fb7c80e0113838077f0a65826f636224440f9b94..557d1e49aba58b799f3dfa65fea8c4d0a8f7cf4c 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -467,8 +467,8 @@ public interface MetadataMapper { TableBriefDto tableToTableBriefDto(Table data); default UniqueDto uniqueToUniqueDto(Unique data) { - data.getTable().setOwner(null); /* loop */ - data.getTable().setCreator(null); /* loop */ +// data.getTable().setOwner(null); /* loop */ +// data.getTable().setCreator(null); /* loop */ return UniqueDto.builder() .id(data.getId()) .name(data.getName()) diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java index 7a99e839edd3b97758e713260f798ae5357c53c6..4e517625ed8bc7d700c1815a8437675d17534d85 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java @@ -18,6 +18,16 @@ public class UserUtil { .anyMatch(a -> a.getAuthority().equals(role)); } + public static boolean isSystem(Principal principal) { + if (principal == null) { + return false; + } + final Authentication authentication = (Authentication) principal; + return authentication.getAuthorities() + .stream() + .anyMatch(a -> a.getAuthority().equals("system")); + } + public static UUID getId(Principal principal) { if (principal == null) { return null; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 3c33e2b05781eb8d04362f68eb4c81f54d450312..9cdcfdedf9e88fd0138e236db6f15afb959ff2dc 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -94,8 +94,8 @@ public class AccessEndpoint { public ResponseEntity<DatabaseAccessDto> create(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto data, - @NotNull Principal principal) throws NotAllowedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, + @NotNull Principal principal) throws NotAllowedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint give access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, data.getType()); @@ -157,7 +157,7 @@ public class AccessEndpoint { @NotBlank @PathVariable("userId") UUID userId, @Valid @RequestBody UpdateDatabaseAccessDto data, @NotNull Principal principal) throws NotAllowedException, - ServiceException, ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint modify database access, databaseId={}, userId={}, access.type={}", databaseId, userId, data.getType()); @@ -176,9 +176,9 @@ public class AccessEndpoint { @RequestMapping(value = "/{userId}", method = {RequestMethod.GET, RequestMethod.HEAD}) @Transactional(readOnly = true) @Observed(name = "dbrepo_access_get") - @PreAuthorize("hasAuthority('check-database-access') or hasAuthority('admin')") + @PreAuthorize("hasAuthority('check-database-access') or hasAuthority('check-foreign-database-access')") @Operation(summary = "Find/Check access", - description = "Finds or checks access of a user with given id to a database with given id. Requests with HTTP method **GET** return the access object, requests with HTTP method **HEAD** only the status. When the user has at least *READ* access, the status 200 is returned, 403 otherwise. Requires role `check-database-access` or `admin`.", + description = "Finds or checks access of a user with given id to a database with given id. Requests with HTTP method **GET** return the access object, requests with HTTP method **HEAD** only the status. When the user has at least *READ* access, the status 200 is returned, 403 otherwise. Requires role `check-database-access` or `check-foreign-database-access`.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -204,7 +204,7 @@ public class AccessEndpoint { log.debug("endpoint get database access, databaseId={}, userId={}, principal.name={}", databaseId, userId, principal.getName()); if (!userId.equals(UserUtil.getId(principal))) { - if (!UserUtil.hasRole(principal, "admin")) { + if (!UserUtil.hasRole(principal, "check-foreign-database-access")) { log.error("Failed to find access: foreign user"); throw new NotAllowedException("Failed to find access: foreign user"); } @@ -256,8 +256,8 @@ public class AccessEndpoint { }) public ResponseEntity<Void> revoke(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("userId") UUID userId, - @NotNull Principal principal) throws NotAllowedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, + @NotNull Principal principal) throws NotAllowedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint revoke database access, databaseId={}, userId={}", databaseId, userId); final Database database = databaseService.findById(databaseId); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 77d35ec498863cd3db09531938a346e02ebb62c1..294d471e8fefe4ccafcf06f5aac47e23fce6f757 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -10,6 +10,7 @@ import at.tuwien.exception.ContainerNotFoundException; import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.ContainerService; +import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -143,14 +144,11 @@ public class ContainerEndpoint { final ContainerDto dto = metadataMapper.containerToContainerDto(container); log.trace("find container resulted in container {}", dto); final HttpHeaders headers = new HttpHeaders(); - if (principal != null) { - final Authentication authentication = (Authentication) principal; - if (authentication.isAuthenticated() && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("admin"))) { - log.trace("attach privileged credential information"); - headers.set("X-Username", container.getPrivilegedUsername()); - headers.set("X-Password", container.getPrivilegedPassword()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); - } + if (UserUtil.isSystem(principal)) { + log.trace("attach privileged credential information"); + headers.set("X-Username", container.getPrivilegedUsername()); + headers.set("X-Password", container.getPrivilegedPassword()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); } return ResponseEntity.ok() .headers(headers) 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 d974de427667f390d995a7d25fbc9789484b5bb4..8be62ea5c400719b31764b0b931a329481b75018 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 @@ -8,6 +8,7 @@ import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; +import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -25,7 +26,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -139,8 +139,8 @@ public class DatabaseEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> create(@Valid @RequestBody DatabaseCreateDto data, - @NotNull Principal principal) throws ServiceException, - ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, + @NotNull Principal principal) throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint create database, data.name={}", data.getName()); final User user = userService.findByUsername(principal.getName()); @@ -190,9 +190,10 @@ public class DatabaseEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> refreshTableMetadata(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull Principal principal) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, MalformedException { + @NotNull Principal principal) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, MalformedException, + TableNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}", databaseId); Database database = databaseService.findById(databaseId); if (!database.getOwner().equals(principal)) { @@ -238,9 +239,9 @@ public class DatabaseEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> refreshViewMetadata(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull Principal principal) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, NotAllowedException, QueryNotFoundException { + @NotNull Principal principal) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, ViewNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}", databaseId); Database database = databaseService.findById(databaseId); if (!database.getOwner().equals(principal)) { @@ -347,7 +348,7 @@ public class DatabaseEndpoint { public ResponseEntity<DatabaseDto> transfer(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody DatabaseTransferDto data, @NotNull Principal principal) throws NotAllowedException, - ServiceException, ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint transfer database, databaseId={}, transferDto.id={}", databaseId, data.getId()); final Database database = databaseService.findById(databaseId); @@ -452,8 +453,8 @@ public class DatabaseEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, - Principal principal) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { + Principal principal) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { log.debug("endpoint find database, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database); @@ -467,13 +468,10 @@ public class DatabaseEndpoint { log.debug("found {} database accesses", accesses.size()); } final HttpHeaders headers = new HttpHeaders(); - if (principal != null) { - final Authentication authentication = (Authentication) principal; - if (authentication.isAuthenticated() && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("admin"))) { - headers.set("X-Username", database.getContainer().getPrivilegedUsername()); - headers.set("X-Password", database.getContainer().getPrivilegedPassword()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); - } + if (UserUtil.isSystem(principal)) { + headers.set("X-Username", database.getContainer().getPrivilegedUsername()); + headers.set("X-Password", database.getContainer().getPrivilegedPassword()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index 781e5c44e89c961a1f33d8797aded12ff08b511f..831e9cd28d7148b0eaec5b44c3cb4f3059726461 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -205,7 +205,7 @@ public class IdentifierEndpoint { }) public ResponseEntity<?> find(@Valid @PathVariable("identifierId") Long identifierId, @RequestHeader(HttpHeaders.ACCEPT) String accept) throws IdentifierNotFoundException, - ServiceException, ServiceConnectionException, MalformedException, FormatNotAvailableException, + DataServiceException, DataServiceConnectionException, MalformedException, FormatNotAvailableException, QueryNotFoundException { log.debug("endpoint find identifier, identifierId={}, accept={}", identifierId, accept); final Identifier identifier = identifierService.find(identifierId); @@ -300,8 +300,9 @@ public class IdentifierEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> delete(@NotNull @PathVariable("identifierId") Long identifierId) - throws IdentifierNotFoundException, NotAllowedException, ServiceException, ServiceConnectionException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { + throws IdentifierNotFoundException, NotAllowedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException { log.debug("endpoint delete identifier, identifierId={}", identifierId); final Identifier identifier = identifierService.find(identifierId); if (identifier.getStatus().equals(IdentifierStatusType.PUBLISHED)) { @@ -354,7 +355,7 @@ public class IdentifierEndpoint { }) public ResponseEntity<IdentifierDto> publish(@Valid @PathVariable("identifierId") Long identifierId) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, - MalformedException, ServiceConnectionException, IdentifierNotFoundException { + MalformedException, DataServiceConnectionException, IdentifierNotFoundException, ExternalServiceException { log.debug("endpoint publish identifier, identifierId={}", identifierId); identifierService.find(identifierId); return ResponseEntity.status(HttpStatus.CREATED) @@ -403,9 +404,10 @@ public class IdentifierEndpoint { public ResponseEntity<IdentifierDto> save(@NotNull @PathVariable("identifierId") Long identifierId, @NotNull @Valid @RequestBody IdentifierSaveDto data, @NotNull Principal principal) throws UserNotFoundException, - DatabaseNotFoundException, MalformedException, NotAllowedException, ServiceException, - ServiceConnectionException, SearchServiceException, QueryNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, TableNotFoundException { + DatabaseNotFoundException, MalformedException, NotAllowedException, DataServiceException, + DataServiceConnectionException, SearchServiceException, QueryNotFoundException, + SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + TableNotFoundException, ExternalServiceException { log.debug("endpoint save identifier, identifierId={}, data.id={}, principal.name={}", identifierId, data.getId(), principal.getName()); final Database database = databaseService.findById(data.getDatabaseId()); @@ -524,9 +526,9 @@ public class IdentifierEndpoint { }) public ResponseEntity<IdentifierDto> create(@NotNull @Valid @RequestBody IdentifierCreateDto data, @NotNull Principal principal) throws DatabaseNotFoundException, - UserNotFoundException, NotAllowedException, MalformedException, ServiceConnectionException, - SearchServiceException, ServiceException, QueryNotFoundException, SearchServiceConnectionException, - IdentifierNotFoundException, ViewNotFoundException { + UserNotFoundException, NotAllowedException, MalformedException, DataServiceConnectionException, + SearchServiceException, DataServiceException, QueryNotFoundException, SearchServiceConnectionException, + IdentifierNotFoundException, ViewNotFoundException, ExternalServiceException { log.debug("endpoint create identifier, data.databaseId={}", data.getDatabaseId()); final Database database = databaseService.findById(data.getDatabaseId()); final User user = userService.findByUsername(principal.getName()); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index c8f01bf26a2e1eaa6f020ed80eefc5673aefc2d2..4fb8240b1d00f00f39a233cd3492e0b06940314a 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -35,7 +35,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -152,7 +151,7 @@ public class TableEndpoint { @PutMapping("/{tableId}") @Transactional - @PreAuthorize("hasAuthority('update-table-statistic') or hasAuthority('admin')") + @PreAuthorize("hasAuthority('update-table-statistic')") @Observed(name = "dbrepo_statistic_table_update") @Operation(summary = "Update statistics", description = "Updates basic statistical properties (min, max, mean, median, std.dev) for numerical columns in a table with id. Requires role `update-table-statistic`", @@ -184,7 +183,7 @@ public class TableEndpoint { public ResponseEntity<Void> updateStatistic(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId) throws TableNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException, MalformedException, ServiceException, ServiceConnectionException { + SearchServiceConnectionException, MalformedException, DataServiceException, DataServiceConnectionException { log.debug("endpoint update table statistics, databaseId={}, tableId={}", databaseId, tableId); final Table table = tableService.findById(databaseId, tableId); tableService.updateStatistics(table); @@ -236,7 +235,7 @@ public class TableEndpoint { @NotNull @PathVariable("columnId") Long columnId, @NotNull @Valid @RequestBody ColumnSemanticsUpdateDto updateDto, @NotNull Principal principal) throws NotAllowedException, - MalformedException, ServiceException, ServiceConnectionException, UserNotFoundException, + MalformedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { log.debug("endpoint update table, databaseId={}, tableId={}, columnId={}", databaseId, tableId, columnId); @@ -343,7 +342,7 @@ public class TableEndpoint { public ResponseEntity<TableDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @Valid @RequestBody TableCreateDto data, @NotNull Principal principal) throws NotAllowedException, MalformedException, - ServiceException, ServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); @@ -401,26 +400,22 @@ public class TableEndpoint { }) public ResponseEntity<TableDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, - Principal principal) throws ServiceException, - ServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, QueueNotFoundException { + Principal principal) throws DataServiceException, + DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, QueueNotFoundException { log.debug("endpoint find table, databaseId={}, tableId={}", databaseId, tableId); final Table table = tableService.findById(databaseId, tableId); final TableDto dto = metadataMapper.customTableToTableDto(table); final HttpHeaders headers = new HttpHeaders(); - if (principal != null) { - /* extra effort only when logged-in */ - final Authentication authentication = (Authentication) principal; - if (authentication.isAuthenticated() && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("admin"))) { - headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Host", table.getDatabase().getContainer().getHost()); - headers.set("X-Port", "" + table.getDatabase().getContainer().getPort()); - headers.set("X-Type", table.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("X-Database", table.getDatabase().getInternalName()); - headers.set("X-Sidecar-Host", table.getDatabase().getContainer().getSidecarHost()); - headers.set("X-Sidecar-Port", "" + table.getDatabase().getContainer().getSidecarPort()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Sidecar-Host X-Sidecar-Port"); - } + if (UserUtil.isSystem(principal)) { + headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); + headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); + headers.set("X-Host", table.getDatabase().getContainer().getHost()); + headers.set("X-Port", "" + table.getDatabase().getContainer().getPort()); + headers.set("X-Type", table.getDatabase().getContainer().getImage().getJdbcMethod()); + headers.set("X-Database", table.getDatabase().getInternalName()); + headers.set("X-Sidecar-Host", table.getDatabase().getContainer().getSidecarHost()); + headers.set("X-Sidecar-Port", "" + table.getDatabase().getContainer().getSidecarPort()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Sidecar-Host X-Sidecar-Port"); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) @@ -466,7 +461,7 @@ public class TableEndpoint { public ResponseEntity<Void> delete(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @NotNull Principal principal) throws NotAllowedException, - ServiceException, ServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, + DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint delete table, databaseId={}, tableId={}", databaseId, tableId); final Table table = tableService.findById(databaseId, tableId); 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 1ee680e0169bfa24ca68eece30737de0763792bd..19e3a1df06cc7e67dae6cd6fdcadd3664abb9ee9 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 @@ -6,7 +6,6 @@ import at.tuwien.api.auth.SignupRequestDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.api.user.*; -import at.tuwien.config.KeycloakConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.user.User; import at.tuwien.exception.*; @@ -187,14 +186,19 @@ public class UserEndpoint { userService.findByUsername(data.getUsername()); } catch (UserNotFoundException e) { /* need to sync */ - log.debug("User with username {} does not exist in metadata database yet", data.getUsername()); + log.warn("User with username {} does not exist in metadata database yet", data.getUsername()); final SignupRequestDto request = SignupRequestDto.builder() .username(data.getUsername()) .email("noreply@example.com") .password(data.getPassword()) .build(); - userService.create(request, authenticationService.findByUsername(data.getUsername()).getId()); - log.info("Fetched user information from auth service and stored it into metadata database"); + final at.tuwien.api.keycloak.UserDto user = authenticationService.findByUsername(data.getUsername()); + if (user.getAttributes().getLdapId().length != 1) { + log.error("Failed to map ldap id for user with username: {}", data.getUsername()); + throw new UserNotFoundException("Failed to map ldap id"); + } + userService.create(request, user.getAttributes().getLdapId()[0]); + log.info("Patched missing user information for user with username: {}", data.getUsername()); } return ResponseEntity.accepted() .body(token); @@ -266,7 +270,7 @@ public class UserEndpoint { /* check */ final User user = userService.findById(userId); if (!user.equals(principal)) { - if (!UserUtil.hasRole(principal, "admin")) { + if (!UserUtil.hasRole(principal, "find-foreign-user")) { log.error("Failed to find user: foreign user"); throw new NotAllowedException("Failed to find user: foreign user"); } @@ -360,8 +364,8 @@ public class UserEndpoint { public ResponseEntity<Void> password(@NotNull @PathVariable("userId") UUID userId, @NotNull @Valid @RequestBody UserPasswordDto data, @NotNull Principal principal) throws NotAllowedException, AuthServiceException, - AuthServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ServiceException, - ServiceConnectionException, CredentialsInvalidException { + AuthServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, DataServiceException, + DataServiceConnectionException, CredentialsInvalidException { log.debug("endpoint modify a user password, userId={}, data.password=(hidden)", userId); User user = userService.findById(userId); if (!user.equals(principal)) { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index a22bdff267e906fcd372e32b5ba36c70944d2188..79981ee6d1fdcaaa5344915f7a0f3d3c43514926 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -4,7 +4,6 @@ import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.ViewCreateDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.config.KeycloakConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.View; import at.tuwien.entities.user.User; @@ -13,6 +12,7 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; import at.tuwien.service.ViewService; +import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -29,7 +29,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -136,7 +135,7 @@ public class ViewEndpoint { public ResponseEntity<ViewBriefDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @Valid @RequestBody ViewCreateDto data, @NotNull Principal principal) throws NotAllowedException, - MalformedException, ServiceException, ServiceConnectionException, DatabaseNotFoundException, + MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); @@ -184,17 +183,14 @@ public class ViewEndpoint { final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); final HttpHeaders headers = new HttpHeaders(); - if (principal != null) { - final Authentication authentication = (Authentication) principal; - if (authentication.isAuthenticated() && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("admin"))) { - headers.set("X-Username", view.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", view.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Host", view.getDatabase().getContainer().getHost()); - headers.set("X-Port", "" + view.getDatabase().getContainer().getPort()); - headers.set("X-Type", view.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("X-Database", view.getDatabase().getInternalName()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database"); - } + if (UserUtil.isSystem(principal)) { + headers.set("X-Username", view.getDatabase().getContainer().getPrivilegedUsername()); + headers.set("X-Password", view.getDatabase().getContainer().getPrivilegedPassword()); + headers.set("X-Host", view.getDatabase().getContainer().getHost()); + headers.set("X-Port", "" + view.getDatabase().getContainer().getPort()); + headers.set("X-Type", view.getDatabase().getContainer().getImage().getJdbcMethod()); + headers.set("X-Database", view.getDatabase().getInternalName()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database"); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) @@ -244,8 +240,8 @@ public class ViewEndpoint { }) public ResponseEntity<View> delete(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("viewId") Long viewId, - @NotNull Principal principal) throws NotAllowedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, + @NotNull Principal principal) throws NotAllowedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index 6b981eb62f8b395e16cd18aa74dc2a88e4c4c502..f6764895556ac07fe0321ae3e4a580f17e873d54 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -44,6 +44,20 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_GATEWAY) + @ExceptionHandler(BrokerServiceConnectionException.class) + public ResponseEntity<ApiErrorDto> handle(BrokerServiceConnectionException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(BrokerServiceException.class) + public ResponseEntity<ApiErrorDto> handle(BrokerServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(ConceptNotFoundException.class) @@ -72,6 +86,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) + @ExceptionHandler(DatabaseMalformedException.class) + public ResponseEntity<ApiErrorDto> handle(DatabaseMalformedException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(DatabaseNotFoundException.class) @@ -79,6 +100,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(DatabaseUnavailableException.class) + public ResponseEntity<ApiErrorDto> handle(DatabaseUnavailableException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(DoiNotFoundException.class) @@ -100,30 +128,37 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(ExternalServiceException.class) + public ResponseEntity<ApiErrorDto> handle(ExternalServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler({FilterBadRequestException.class}) + @ExceptionHandler(FilterBadRequestException.class) public ResponseEntity<ApiErrorDto> handle(FilterBadRequestException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE) - @ExceptionHandler({FormatNotAvailableException.class}) + @ExceptionHandler(FormatNotAvailableException.class) public ResponseEntity<ApiErrorDto> handle(FormatNotAvailableException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({IdentifierNotFoundException.class}) + @ExceptionHandler(IdentifierNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(IdentifierNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({IdentifierNotSupportedException.class}) + @ExceptionHandler(IdentifierNotSupportedException.class) public ResponseEntity<ApiErrorDto> handle(IdentifierNotSupportedException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @@ -158,18 +193,32 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { @Hidden @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler({MalformedException.class}) + @ExceptionHandler(MalformedException.class) public ResponseEntity<ApiErrorDto> handle(MalformedException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({MessageNotFoundException.class}) + @ExceptionHandler(MessageNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(MessageNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_GATEWAY) + @ExceptionHandler(MetadataServiceConnectionException.class) + public ResponseEntity<ApiErrorDto> handle(MetadataServiceConnectionException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(MetadataServiceException.class) + public ResponseEntity<ApiErrorDto> handle(MetadataServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.FORBIDDEN) @ExceptionHandler(NotAllowedException.class) @@ -193,11 +242,18 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { @Hidden @ResponseStatus(code = HttpStatus.BAD_REQUEST) - @ExceptionHandler({PaginationException.class}) + @ExceptionHandler(PaginationException.class) public ResponseEntity<ApiErrorDto> handle(PaginationException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ExceptionHandler(QueryMalformedException.class) + public ResponseEntity<ApiErrorDto> handle(QueryMalformedException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(QueryNotFoundException.class) @@ -205,52 +261,108 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.NOT_IMPLEMENTED) + @ExceptionHandler(QueryNotSupportedException.class) + public ResponseEntity<ApiErrorDto> handle(QueryNotSupportedException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({QueueNotFoundException.class}) + @ExceptionHandler(QueueNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(QueueNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) + @ExceptionHandler(QueryStoreCreateException.class) + public ResponseEntity<ApiErrorDto> handle(QueryStoreCreateException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ExceptionHandler(QueryStoreGCException.class) + public ResponseEntity<ApiErrorDto> handle(QueryStoreGCException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) + @ExceptionHandler(QueryStoreInsertException.class) + public ResponseEntity<ApiErrorDto> handle(QueryStoreInsertException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) + @ExceptionHandler(QueryStorePersistException.class) + public ResponseEntity<ApiErrorDto> handle(QueryStorePersistException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(RemoteUnavailableException.class) + public ResponseEntity<ApiErrorDto> handle(RemoteUnavailableException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({RorNotFoundException.class}) + @ExceptionHandler(RorNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(RorNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.BAD_GATEWAY) - @ExceptionHandler({SearchServiceConnectionException.class}) + @ExceptionHandler(SearchServiceConnectionException.class) public ResponseEntity<ApiErrorDto> handle(SearchServiceConnectionException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler({SearchServiceException.class}) + @ExceptionHandler(SearchServiceException.class) public ResponseEntity<ApiErrorDto> handle(SearchServiceException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({SemanticEntityNotFoundException.class}) + @ExceptionHandler(SemanticEntityNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(SemanticEntityNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.BAD_GATEWAY) - @ExceptionHandler({ServiceConnectionException.class}) - public ResponseEntity<ApiErrorDto> handle(ServiceConnectionException e) { + @ExceptionHandler(DataServiceConnectionException.class) + public ResponseEntity<ApiErrorDto> handle(DataServiceConnectionException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) - @ExceptionHandler({ServiceException.class}) - public ResponseEntity<ApiErrorDto> handle(ServiceException e) { + @ExceptionHandler(DataServiceException.class) + public ResponseEntity<ApiErrorDto> handle(DataServiceException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(SidecarExportException.class) + public ResponseEntity<ApiErrorDto> handle(SidecarExportException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(SidecarImportException.class) + public ResponseEntity<ApiErrorDto> handle(SidecarImportException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @@ -282,23 +394,37 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ExceptionHandler(TableMalformedException.class) + public ResponseEntity<ApiErrorDto> handle(TableMalformedException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(TableSchemaException.class) + public ResponseEntity<ApiErrorDto> handle(TableSchemaException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({TableNotFoundException.class}) + @ExceptionHandler(TableNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(TableNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) - @ExceptionHandler({UnitNotFoundException.class}) + @ExceptionHandler(UnitNotFoundException.class) public ResponseEntity<ApiErrorDto> handle(UnitNotFoundException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) - @ExceptionHandler({UriMalformedException.class}) + @ExceptionHandler(UriMalformedException.class) public ResponseEntity<ApiErrorDto> handle(UriMalformedException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @@ -317,6 +443,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ExceptionHandler(ViewMalformedException.class) + public ResponseEntity<ApiErrorDto> handle(ViewMalformedException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(ViewNotFoundException.class) @@ -324,6 +457,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(ViewSchemaException.class) + public ResponseEntity<ApiErrorDto> handle(ViewSchemaException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + private ResponseEntity<ApiErrorDto> generic_handle(Class<?> exceptionClass, String message) { final HttpHeaders headers = new HttpHeaders(); headers.set("Content-Type", "application/problem+json"); diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml index fd44a809ca442d50bfd670703ef0c634ba68d4f5..63675da5656eb62b90b79ad2c9f2c99895e7e7c3 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml @@ -1,10 +1,4 @@ spring: - ldap: - urls: ldap://localhost:1389 - userDn: cn=admin,dc=dbrepo,dc=at - password: adminpassword - base: dc=dbrepo,dc=at - adminDn: cn=admins,ou=users,dc=dbrepo,dc=at datasource: url: jdbc:mariadb://localhost:3306/dbrepo driver-class-name: org.mariadb.jdbc.Driver @@ -66,7 +60,7 @@ dbrepo: secretAccessKey: seaweedfsadmin importBucket: dbrepo-upload exportBucket: dbrepo-download - admin: + system: username: admin password: admin endpoints: diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml index 0552cce9cb2b14a4e88714a85339137a6ddb4e0e..9398db2b546026d422f85037c2e2b7eb8d4773b8 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml @@ -2,12 +2,6 @@ application: title: DBRepo version: '@project.version@' spring: - ldap: - urls: "${IDENTITY_SERVICE_URLS:ldap://identity-service:1389}" - userDn: "${IDENTITY_SERVICE_USERNAME:cn=admin,dc=dbrepo,dc=at}" - password: "${IDENTITY_SERVICE_PASSWORD:adminpassword}" - base: "${IDENTITY_SERVICE_BASE:dc=dbrepo,dc=at}" - adminDn: "${IDENTITY_SERVICE_ADMIN_GROUP:cn=admins,ou=users,dc=dbrepo,dc=at}" datasource: url: "jdbc:mariadb://${METADATA_HOST:metadata-db}:3306/${METADATA_DB:dbrepo}${METADATA_JDBC_EXTRA_ARGS}" driver-class-name: org.mariadb.jdbc.Driver @@ -68,9 +62,9 @@ dbrepo: secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}" importBucket: "${S3_IMPORT_BUCKET:dbrepo-upload}" exportBucket: "${S3_EXPORT_BUCKET:dbrepo-download}" - admin: - username: "${ADMIN_USERNAME:admin}" - password: "${ADMIN_PASSWORD:admin}" + system: + username: "${SYSTEM_USERNAME:admin}" + password: "${SYSTEM_PASSWORD:admin}" endpoints: searchService: "${SEARCH_SERVICE_ENDPOINT:http://gateway-service}" analyseService: "${ANALYSE_SERVICE_ENDPOINT:http://gateway-service}" diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..f8a83baf85c36852073f120f182f1819280dec67 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/RabbitConfig.java @@ -0,0 +1,41 @@ +package at.tuwien.config; + +import at.tuwien.test.BaseTest; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +@Getter +@Log4j2 +@Configuration +public class RabbitConfig extends BaseTest { + + @Value("${dbrepo.exchangeName}") + private String exchangeName; + + @Value("${dbrepo.queueName}") + private String queueName; + + @Value("${spring.rabbitmq.virtual-host}") + private String virtualHost; + + @Value("${dbrepo.endpoints.brokerService}") + private String brokerEndpoint; + + @Bean + @Primary + public RestTemplate brokerRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(brokerEndpoint)); + restTemplate.getInterceptors() + .add(new BasicAuthenticationInterceptor(USER_1_USERNAME, USER_1_PASSWORD)); + return restTemplate; + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeConverterUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeConverterUnitTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7215e5db918f226e6a826fce66e4e129ca4f0c5f --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/converters/IdentifierTypeConverterUnitTest.java @@ -0,0 +1,41 @@ +package at.tuwien.converters; + +import at.tuwien.api.identifier.IdentifierTypeDto; +import at.tuwien.test.AbstractUnitTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.*; + +@Log4j2 +@SpringBootTest +public class IdentifierTypeConverterUnitTest extends AbstractUnitTest { + + @Autowired + private IdentifierTypeConverter identifierTypeConverter; + + @BeforeEach + public void beforeEach() { + genesis(); + } + + @Test + public void identifierTypeConverter_succeeds() { + + /* test */ + final IdentifierTypeDto response = identifierTypeConverter.convert(IdentifierTypeDto.DATABASE.getName()); + assertEquals(IdentifierTypeDto.DATABASE, response); + } + + @Test + public void identifierTypeConverter_fails() { + + /* test */ + assertThrows(IllegalArgumentException.class, () -> { + identifierTypeConverter.convert("i_do_not_exist"); + }); + } +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java index 16c212a546700d3b1ecf8dfc887326764e5e9e5f..69d817afb763fa47b878b71fb315bb8dbb02f750 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java @@ -73,7 +73,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-access"}) - public void create_succeeds() throws ServiceException, ServiceConnectionException, NotAllowedException, + public void create_succeeds() throws DataServiceException, DataServiceConnectionException, NotAllowedException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -115,12 +115,12 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"admin"}) + @WithMockUser(username = USER_1_USERNAME, authorities = {"check-foreign-database-access"}) public void find_hasRoleHasAccessForeign_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ - generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_LOCAL_ADMIN_PRINCIPAL, USER_1_ID, USER_1); + generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_1_ID, USER_1); } @Test @@ -155,7 +155,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"update-database-access"}) - public void update_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void update_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -190,7 +190,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-database-access"}) - public void revoke_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void revoke_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -208,7 +208,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* ################################################################################################### */ protected void generic_create(Principal principal, UUID userId, String username, User user) - throws NotAllowedException, ServiceException, ServiceConnectionException, UserNotFoundException, + throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -269,7 +269,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } protected void generic_update(DatabaseAccess access, String otherUsername, User otherUser, Principal principal, - User user) throws NotAllowedException, ServiceException, ServiceConnectionException, + User user) throws NotAllowedException, DataServiceException, DataServiceConnectionException, AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -307,8 +307,8 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { assertNull(response.getBody()); } - protected void generic_revoke(Principal principal, User user) throws ServiceConnectionException, - NotAllowedException, ServiceException, UserNotFoundException, DatabaseNotFoundException, + protected void generic_revoke(Principal principal, User user) throws DataServiceConnectionException, + NotAllowedException, DataServiceException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java index cb230377f3fb443c864a35fcc0486cb3ee915769..7706e185bd3721fdddec7daed15ce8df628b0bad 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ContainerEndpointUnitTest.java @@ -42,7 +42,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void findById_anonymous_succeeds() throws ContainerNotFoundException { /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, null, false); + findById_generic(CONTAINER_1_ID, CONTAINER_1, null); } @Test @@ -50,7 +50,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void findById_hasRole_succeeds() throws ContainerNotFoundException { /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, USER_1_PRINCIPAL, false); + findById_generic(CONTAINER_1_ID, CONTAINER_1, USER_1_PRINCIPAL); } @Test @@ -58,15 +58,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { public void findById_noRole_succeeds() throws ContainerNotFoundException { /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, USER_4_PRINCIPAL, false); - } - - @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void findById_admin_succeeds() throws ContainerNotFoundException { - - /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, USER_LOCAL_ADMIN_PRINCIPAL, true); + findById_generic(CONTAINER_1_ID, CONTAINER_1, USER_4_PRINCIPAL); } @Test @@ -173,7 +165,7 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void findById_generic(Long containerId, Container container, Principal principal, Boolean isAdmin) + public void findById_generic(Long containerId, Container container, Principal principal) throws ContainerNotFoundException { /* mock */ @@ -184,15 +176,6 @@ public class ContainerEndpointUnitTest extends AbstractUnitTest { final ResponseEntity<ContainerDto> response = containerEndpoint.findById(containerId, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); - if (isAdmin) { - assertNotNull(response.getHeaders()); - final List<String> xUsername = response.getHeaders().get("X-Username"); - assertNotNull(xUsername); - assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, xUsername.get(0)); - final List<String> xPassword = response.getHeaders().get("X-Password"); - assertNotNull(xPassword); - assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, xPassword.get(0)); - } } public void delete_generic(Long containerId, Container container) throws ContainerNotFoundException { 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 7e53274f504ea36838ce1deda16f3390d372e98b..02ba52ecaa930f1747ee55f80cff2ea36379ffc1 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 @@ -94,10 +94,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database"}) - public void create_succeeds() throws ServiceException, ServiceConnectionException, UserNotFoundException, + public void create_succeeds() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, AuthServiceException, AuthServiceConnectionException, - CredentialsInvalidException { + CredentialsInvalidException, BrokerServiceException, BrokerServiceConnectionException { final DatabaseCreateDto request = DatabaseCreateDto.builder() .cid(CONTAINER_1_ID) .name(DATABASE_1_NAME) @@ -302,7 +302,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-database-owner"}) - public void transfer_hasRole_succeeds() throws ServiceConnectionException, ServiceException, + public void transfer_hasRole_succeeds() throws DataServiceConnectionException, DataServiceException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { @@ -345,7 +345,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_anonymous_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_anonymous_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { /* test */ @@ -364,7 +364,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) - public void findById_hasRole_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_hasRole_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { /* pre-condition */ @@ -376,7 +376,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) - public void findById_hasRoleForeign_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_hasRoleForeign_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { /* pre-condition */ @@ -388,7 +388,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) - public void findById_ownerSeesAccessRights_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_ownerSeesAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { /* mock */ @@ -430,9 +430,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { assertEquals(databases.size(), body.size()); } - public void create_generic(DatabaseCreateDto data, Principal principal, User user) throws ServiceException, - ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, - SearchServiceException, SearchServiceConnectionException { + public void create_generic(DatabaseCreateDto data, Principal principal, User user) throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, + BrokerServiceException, BrokerServiceConnectionException { /* mock */ doNothing() @@ -468,7 +469,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } public DatabaseDto findById_generic(Long databaseId, Database database, Principal principal) - throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException { + throws DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, + DataServiceException { /* mock */ if (database != null) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java index 7a83d2558f92c93eee618a05ec427d11bb4d1b3a..af98f87e571bac44fd2e422848cbfc8e37262ffd 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java @@ -78,8 +78,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_json0_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_json0_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "application/json"; final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata0.json"), StandardCharsets.UTF_8), IdentifierDto.class); @@ -109,8 +110,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_json1_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_json1_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "application/json"; final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata1.json"), StandardCharsets.UTF_8), IdentifierDto.class); @@ -160,8 +162,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_csv_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_csv_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/csv"; final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv"))); final InputStreamResource mock = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv"))); @@ -182,7 +185,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @Disabled("not testable with xml") - public void find_xml0_succeeds() throws IOException, MalformedException, ServiceException, ServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException, FormatNotAvailableException { + public void find_xml0_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException, + FormatNotAvailableException { final String accept = "text/xml"; final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata0.xml"))); @@ -200,8 +205,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @Disabled("not testable with xml") - public void find_xml1_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_xml1_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/xml"; final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata1.xml"))); @@ -220,8 +226,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliography_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliography_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa1.txt"), StandardCharsets.UTF_8); @@ -242,8 +249,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyApa0_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyApa0_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=apa"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa0.txt"), StandardCharsets.UTF_8); @@ -264,8 +272,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyApa1_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyApa1_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=apa"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa1.txt"), StandardCharsets.UTF_8); @@ -286,8 +295,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyApa2_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyApa2_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=apa"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa2.txt"), StandardCharsets.UTF_8); @@ -308,8 +318,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyApa3_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyApa3_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=apa"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa3.txt"), StandardCharsets.UTF_8); @@ -330,8 +341,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyApa4_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyApa4_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=apa"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_apa4.txt"), StandardCharsets.UTF_8); @@ -352,8 +364,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyIeee0_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyIeee0_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=ieee"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee0.txt"), StandardCharsets.UTF_8); @@ -374,8 +387,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyIeee1_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyIeee1_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=ieee"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee1.txt"), StandardCharsets.UTF_8); @@ -396,8 +410,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyIeee2_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyIeee2_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=ieee"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee2.txt"), StandardCharsets.UTF_8); @@ -418,8 +433,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyIeee3_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyIeee3_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=ieee"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_ieee3.txt"), StandardCharsets.UTF_8); @@ -440,8 +456,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyBibtex0_succeeds() throws IOException, MalformedException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyBibtex0_succeeds() throws IOException, MalformedException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=bibtex"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex0.txt"), StandardCharsets.UTF_8); @@ -462,8 +479,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyBibtex1_succeeds() throws MalformedException, IOException, ServiceException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyBibtex1_succeeds() throws MalformedException, IOException, DataServiceException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=bibtex"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex1.txt"), StandardCharsets.UTF_8); @@ -484,8 +502,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyBibtex2_succeeds() throws MalformedException, ServiceException, IOException, - ServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + public void find_bibliographyBibtex2_succeeds() throws MalformedException, DataServiceException, IOException, + DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, + FormatNotAvailableException { final String accept = "text/bibliography; style=bibtex"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex2.txt"), StandardCharsets.UTF_8); @@ -506,8 +525,8 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_bibliographyBibtex3_succeeds() throws MalformedException, ServiceException, - ServiceConnectionException, IOException, QueryNotFoundException, IdentifierNotFoundException, + public void find_bibliographyBibtex3_succeeds() throws MalformedException, DataServiceException, + DataServiceConnectionException, IOException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { final String accept = "text/bibliography; style=bibtex"; final String compare = FileUtils.readFileToString(new File("src/test/resources/bibliography/style_bibtex3.txt"), @@ -545,9 +564,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-identifier"}) - public void delete_hasRole_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, - DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, - SearchServiceConnectionException { + public void delete_hasRole_succeeds() throws NotAllowedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, + SearchServiceException, SearchServiceConnectionException { /* test */ this.generic_delete(); @@ -555,7 +574,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_json_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void find_json_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, FormatNotAvailableException, QueryNotFoundException, IdentifierNotFoundException { final String accept = "application/json"; @@ -582,7 +601,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_xml_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void find_xml_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, IOException, QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { final InputStreamResource resource = new InputStreamResource(FileUtils.openInputStream( new File("src/test/resources/xml/datacite-example-dataset-v4.xml"))); @@ -598,8 +617,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void find_httpRedirect_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, - FormatNotAvailableException, QueryNotFoundException, IdentifierNotFoundException { + public void find_httpRedirect_succeeds() throws MalformedException, DataServiceException, + DataServiceConnectionException, FormatNotAvailableException, QueryNotFoundException, + IdentifierNotFoundException { /* test */ final ResponseEntity<?> response = generic_find(null, null); @@ -611,10 +631,10 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_hasRoleDatabase_succeeds() throws MalformedException, NotAllowedException, ServiceException, - ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, + public void save_hasRoleDatabase_succeeds() throws MalformedException, NotAllowedException, DataServiceException, + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueryNotFoundException, IdentifierNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException, TableNotFoundException { + SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { /* test */ generic_save(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, IDENTIFIER_1, IDENTIFIER_1_SAVE_DTO, USER_1_PRINCIPAL, USER_1); @@ -633,9 +653,9 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"create-identifier"}) public void save_hasRoleReadAccessQuery_succeeds() throws MalformedException, NotAllowedException, - ServiceException, ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueryNotFoundException, IdentifierNotFoundException, ViewNotFoundException, - SearchServiceException, SearchServiceConnectionException, TableNotFoundException { + SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { /* mock */ when(dataServiceGateway.findQuery(DATABASE_2_ID, IDENTIFIER_5_QUERY_ID)) @@ -798,10 +818,10 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { protected void generic_save(Long databaseId, Database database, DatabaseAccess access, Identifier identifier, IdentifierSaveDto data, Principal principal, User user) throws MalformedException, - NotAllowedException, ServiceException, ServiceConnectionException, UserNotFoundException, + NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueryNotFoundException, IdentifierNotFoundException, ViewNotFoundException, SearchServiceException, - SearchServiceConnectionException, TableNotFoundException { + SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { /* mock */ if (access != null) { @@ -842,7 +862,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { } protected ResponseEntity<?> generic_find(String accept, InputStreamResource resource) - throws MalformedException, ServiceException, ServiceConnectionException, FormatNotAvailableException, + throws MalformedException, DataServiceException, DataServiceConnectionException, FormatNotAvailableException, QueryNotFoundException, IdentifierNotFoundException { /* mock */ @@ -863,7 +883,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { return IOUtils.toString(inputStream, StandardCharsets.UTF_8); } - protected void generic_delete() throws NotAllowedException, ServiceException, ServiceConnectionException, + protected void generic_delete() throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, SearchServiceConnectionException { 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 b9a67d9911292efaa0234cb9e61d9ea5c778d03f..154ebda86c3a32554c2c83a3330846ebdee8f939 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 @@ -348,7 +348,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_publicAnonymous_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_publicAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -367,7 +367,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_publicHasRoleDatabaseNotFound_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_publicHasRoleDatabaseNotFound_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -376,7 +376,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_publicHasRole_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_publicHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -388,7 +388,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_publicNoRole_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_publicNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -497,8 +497,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"}) - public void update_publicHasRoleHasOwnWriteAccess_succeeds() throws MalformedException, ServiceException, - NotAllowedException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, + public void update_publicHasRoleHasOwnWriteAccess_succeeds() throws MalformedException, DataServiceException, + NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() @@ -540,8 +540,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) - public void update_publicHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, ServiceException, - NotAllowedException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, + public void update_publicHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, DataServiceException, + NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() @@ -601,8 +601,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"}) - public void update_privateHasRoleHasOwnWriteAccess_succeeds() throws MalformedException, ServiceException, - NotAllowedException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, + public void update_privateHasRoleHasOwnWriteAccess_succeeds() throws MalformedException, DataServiceException, + NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() @@ -644,8 +644,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"}) - public void update_privateHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, ServiceException, - NotAllowedException, ServiceConnectionException, UserNotFoundException, TableNotFoundException, + public void update_privateHasRoleForeignHasAllWriteAccess_succeeds() throws MalformedException, DataServiceException, + NotAllowedException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() @@ -731,7 +731,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_privateAnonymous_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_privateAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -750,7 +750,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_privateHasRoleDatabaseNotFound_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_privateHasRoleDatabaseNotFound_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -759,7 +759,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_privateHasRole_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_privateHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, @@ -771,7 +771,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_privateNoRole_succeeds() throws ServiceException, ServiceConnectionException, + public void findById_privateNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* test */ @@ -790,7 +790,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table"}) - public void delete_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void delete_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -810,9 +810,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-foreign-table"}) - public void delete_foreign_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void delete_foreign_succeeds() throws NotAllowedException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, DataServiceException { /* test */ generic_delete(USER_2_PRINCIPAL, TABLE_1); @@ -895,9 +895,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<TableDto> generic_create(Long databaseId, Database database, TableCreateDto data, Principal principal, User user, DatabaseAccess access) - throws MalformedException, NotAllowedException, ServiceException, ServiceConnectionException, + throws MalformedException, NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, TableNotFoundException, - TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { + TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, + SemanticEntityNotFoundException { /* mock */ if (principal != null) { @@ -927,8 +928,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<TableDto> generic_findById(Long databaseId, Database database, Long tableId, Table table, Principal principal, User user, - DatabaseAccess access) throws ServiceException, - ServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, + DatabaseAccess access) throws DataServiceException, + DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { /* mock */ @@ -964,7 +965,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } protected ResponseEntity<?> generic_delete(Principal principal, Table table) throws NotAllowedException, - ServiceException, ServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, + DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -978,7 +979,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { protected ResponseEntity<ColumnDto> generic_update(Long databaseId, Database database, Long tableId, Table table, Long columnId, TableColumn column, Principal principal, User user, ColumnSemanticsUpdateDto data, DatabaseAccess access) - throws ServiceException, ServiceConnectionException, MalformedException, NotAllowedException, + throws DataServiceException, DataServiceConnectionException, MalformedException, NotAllowedException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { @@ -990,7 +991,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { when(tableService.update(column, data)) .thenReturn(column); } else { - doThrow(ServiceException.class) + doThrow(DataServiceException.class) .when(tableService) .update(column, data); doThrow(TableNotFoundException.class) 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 f21e13711b88b25cdf981f674edaa103c80b7fe6..f5e413e0e9de10192bca89d4fe823db02924712d 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 @@ -216,7 +216,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) - public void password_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void password_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { final UserPasswordDto request = UserPasswordDto.builder() @@ -302,7 +302,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } protected void password_generic(Principal principal, UserPasswordDto data) throws NotAllowedException, - ServiceException, ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index 724d43ca16a94d354c0f5a72a0bbcb3996eb2733..74e418f42b1ca4fc4cbceec451f645ec05c1223d 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -196,8 +196,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-database-view"}) - public void delete_publicOwner_succeeds() throws NotAllowedException, ServiceException, - ServiceConnectionException, ViewNotFoundException, DatabaseNotFoundException, AccessNotFoundException, + public void delete_publicOwner_succeeds() throws NotAllowedException, DataServiceException, + DataServiceConnectionException, ViewNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { /* test */ @@ -352,7 +352,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-database-view"}) - public void delete_privateOwner_succeeds() throws NotAllowedException, ServiceException, ServiceConnectionException, + public void delete_privateOwner_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -401,8 +401,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } protected void create_generic(Long databaseId, Database database, Principal principal, UUID userId, User user, - DatabaseAccess access) throws MalformedException, ServiceException, - ServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, + DatabaseAccess access) throws MalformedException, DataServiceException, + DataServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { final ViewCreateDto request = ViewCreateDto.builder() .name(VIEW_1_NAME) @@ -469,7 +469,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void delete_generic(Long databaseId, Database database, Long viewId, View view, Principal principal, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, - ServiceException, ServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, AccessNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java index ffa2ff6c1b163d0defbd4d8fa1fe3d608e923309..a812bd5de49af37c5eca041a2fb36653d243dafc 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java @@ -14,6 +14,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; @@ -33,7 +34,8 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { private BrokerServiceGateway brokerServiceGateway; @Test - public void grantTopicPermission_exchangeNoRightsBefore_succeeds() throws ServiceException, ServiceConnectionException { + public void grantTopicPermission_exchangeNoRightsBefore_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED) .build(); @@ -46,7 +48,8 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void grantTopicPermission_exchangeRightsSame_succeeds() throws ServiceException, ServiceConnectionException { + public void grantTopicPermission_exchangeRightsSame_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT) .build(); @@ -68,13 +71,14 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .thenReturn(mock); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO); }); } @Test - public void grantVirtualHostPermission_virtualHostNoRightsBefore_succeeds() throws ServiceConnectionException, ServiceException { + public void grantVirtualHostPermission_virtualHostNoRightsBefore_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED) .build(); @@ -87,7 +91,8 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void grantVirtualHostPermission_virtualHostRightsSame_succeeds() throws ServiceConnectionException, ServiceException { + public void grantVirtualHostPermission_virtualHostRightsSame_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT) .build(); @@ -109,7 +114,7 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .thenReturn(mock); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { brokerServiceGateway.grantVirtualHostPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO); }); } @@ -123,7 +128,21 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { + brokerServiceGateway.grantVirtualHostPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO); + }); + } + + @Test + public void grantVirtualHostPermission_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(BrokerServiceConnectionException.class, () -> { brokerServiceGateway.grantVirtualHostPermission(USER_1_USERNAME, VIRTUAL_HOST_GRANT_DTO); }); } @@ -137,13 +156,28 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO); }); } @Test - public void grantExchangePermission_succeeds() throws ServiceConnectionException, ServiceException { + public void grantTopicPermission_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(BrokerServiceConnectionException.class, () -> { + brokerServiceGateway.grantTopicPermission(USER_1_USERNAME, VIRTUAL_HOST_EXCHANGE_UPDATE_DTO); + }); + } + + @Test + public void grantExchangePermission_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.CREATED) .build(); @@ -156,7 +190,8 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { } @Test - public void grantExchangePermission_exists_succeeds() throws ServiceConnectionException, ServiceException { + public void grantExchangePermission_exists_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT) .build(); @@ -178,7 +213,21 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .thenReturn(mock); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { + brokerServiceGateway.grantExchangePermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO); + }); + } + + @Test + public void grantExchangePermission_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(BrokerServiceConnectionException.class, () -> { brokerServiceGateway.grantExchangePermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO); }); } @@ -192,7 +241,7 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(BrokerServiceException.class, () -> { brokerServiceGateway.grantExchangePermission(USER_1_USERNAME, USER_1_RABBITMQ_GRANT_TOPIC_DTO); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java index 8d056ad48daab05a38308e047bb167df13e94f9c..881f29ed04b9559884fa26ace511a0627984c963 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/CrossrefGatewayUnitTest.java @@ -15,9 +15,11 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @Log4j2 @@ -26,7 +28,6 @@ import static org.mockito.Mockito.*; public class CrossrefGatewayUnitTest extends AbstractUnitTest { @MockBean - @Qualifier("keycloakRestTemplate") private RestTemplate restTemplate; @Autowired @@ -45,15 +46,17 @@ public class CrossrefGatewayUnitTest extends AbstractUnitTest { } @Test - public void findById_fails() throws DoiNotFoundException { + public void findById_fails() { /* mock */ - doThrow(ResourceAccessException.class) + doThrow(HttpServerErrorException.class) .when(restTemplate) .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(CrossrefDto.class)); /* test */ - crossrefGateway.findById("501100004729"); + assertThrows(DoiNotFoundException.class, () -> { + crossrefGateway.findById("501100004729"); + }); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java index d8369bb6dabf926d0435320c360872b4724ca53e..8183ea90808ea6c7e48e1530ea2a88a62a34df9b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java @@ -1,16 +1,1119 @@ package at.tuwien.gateway; +import at.tuwien.ExportResourceDto; +import at.tuwien.api.database.AccessTypeDto; +import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewDto; +import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.exception.*; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest @ExtendWith(SpringExtension.class) public class DataServiceGatewayUnitTest extends AbstractUnitTest { - // TODO check mapping of databaseService too!! + @MockBean + @Qualifier("dataServiceRestTemplate") + private RestTemplate dataServiceRestTemplate; + + @Autowired + private DataServiceGateway dataServiceGateway; + + @Test + public void createAccess_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .build()); + + /* test */ + dataServiceGateway.createAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + } + + @Test + public void createAccess_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.createAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void createAccess_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + dataServiceGateway.createAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void createAccess_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void createAccess_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void updateAccess_succeeds() throws DataServiceException, DataServiceConnectionException, AccessNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dataServiceGateway.updateAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + } + + @Test + public void updateAccess_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.updateAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void updateAccess_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(AccessNotFoundException.class, () -> { + dataServiceGateway.updateAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void updateAccess_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.updateAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void updateAccess_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.updateAccess(DATABASE_1_ID, USER_1_ID, AccessTypeDto.READ); + }); + } + + @Test + public void deleteAccess_succeeds() throws DataServiceException, DataServiceConnectionException, AccessNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dataServiceGateway.deleteAccess(DATABASE_1_ID, USER_1_ID); + } + + @Test + public void deleteAccess_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.deleteAccess(DATABASE_1_ID, USER_1_ID); + }); + } + + @Test + public void deleteAccess_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(AccessNotFoundException.class, () -> { + dataServiceGateway.deleteAccess(DATABASE_1_ID, USER_1_ID); + }); + } + + @Test + public void deleteAccess_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteAccess(DATABASE_1_ID, USER_1_ID); + }); + } + + @Test + public void deleteAccess_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteAccess(DATABASE_1_ID, USER_1_ID); + }); + } + + @Test + public void createDatabase_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(DatabaseDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .body(DATABASE_1_DTO)); + + /* test */ + dataServiceGateway.createDatabase(DATABASE_1_CREATE_INTERNAL); + } + + @Test + public void createDatabase_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(DatabaseDto.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.createDatabase(DATABASE_1_CREATE_INTERNAL); + }); + } + + @Test + public void createDatabase_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(DatabaseDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createDatabase(DATABASE_1_CREATE_INTERNAL); + }); + } + + @Test + public void createDatabase_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(DatabaseDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createDatabase(DATABASE_1_CREATE_INTERNAL); + }); + } + + @Test + public void createDatabase_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(DatabaseDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createDatabase(DATABASE_1_CREATE_INTERNAL); + }); + } + + @Test + public void updateDatabase_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + } + + @Test + public void updateDatabase_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + }); + } + + @Test + public void updateDatabase_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + }); + } + + @Test + public void updateDatabase_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + }); + } + + @Test + public void updateDatabase_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + }); + } + + @Test + public void updateDatabase_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.updateDatabase(DATABASE_1_ID, USER_1_UPDATE_PASSWORD_DTO); + }); + } + + @Test + public void createTable_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, TableExistsException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .build()); + + /* test */ + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + } + + @Test + public void createTable_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void createTable_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void createTable_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void createTable_exists_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Conflict.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(TableExistsException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void createTable_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void createTable_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createTable(DATABASE_1_ID, TABLE_1_CREATE_DTO); + }); + } + + @Test + public void deleteTable_succeeds() throws DataServiceException, DataServiceConnectionException, + TableNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dataServiceGateway.deleteTable(DATABASE_1_ID, TABLE_1_ID); + } + + @Test + public void deleteTable_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.deleteTable(DATABASE_1_ID, TABLE_1_ID); + }); + } + + @Test + public void deleteTable_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteTable(DATABASE_1_ID, TABLE_1_ID); + }); + } + + @Test + public void deleteTable_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(TableNotFoundException.class, () -> { + dataServiceGateway.deleteTable(DATABASE_1_ID, TABLE_1_ID); + }); + } + + @Test + public void deleteTable_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteTable(DATABASE_1_ID, TABLE_1_ID); + }); + } + + @Test + public void createView_succeeds() throws DataServiceException, DataServiceConnectionException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .body(VIEW_1_DTO)); + + /* test */ + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + } + + @Test + public void createView_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + }); + } + + @Test + public void createView_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + }); + } + + @Test + public void createView_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + }); + } + + @Test + public void createView_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + }); + } + + @Test + public void createView_emptyBody_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ViewDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.CREATED) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.createView(DATABASE_1_ID, VIEW_1_CREATE_DTO); + }); + } + + @Test + public void deleteView_succeeds() throws DataServiceException, DataServiceConnectionException, + ViewNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .build()); + + /* test */ + dataServiceGateway.deleteView(DATABASE_1_ID, VIEW_1_ID); + } + + @Test + public void deleteView_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.deleteView(DATABASE_1_ID, VIEW_1_ID); + }); + } + + @Test + public void deleteView_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteView(DATABASE_1_ID, VIEW_1_ID); + }); + } + + @Test + public void deleteView_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class)); + + /* test */ + assertThrows(ViewNotFoundException.class, () -> { + dataServiceGateway.deleteView(DATABASE_1_ID, VIEW_1_ID); + }); + } + + @Test + public void deleteView_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.deleteView(DATABASE_1_ID, VIEW_1_ID); + }); + } + + @Test + public void findQuery_succeeds() throws DataServiceException, DataServiceConnectionException, + QueryNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(QUERY_1_DTO)); + + /* test */ + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + } + + @Test + public void findQuery_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void findQuery_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void findQuery_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class)); + + /* test */ + assertThrows(QueryNotFoundException.class, () -> { + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void findQuery_notAcceptable_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotAcceptable.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void findQuery_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(QueryDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.findQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void exportQuery_succeeds() throws DataServiceException, DataServiceConnectionException, + QueryNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ExportResourceDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + dataServiceGateway.exportQuery(DATABASE_1_ID, QUERY_1_ID); + } + + @Test + public void exportQuery_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ExportResourceDto.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.exportQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void exportQuery_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ExportResourceDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.exportQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void exportQuery_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ExportResourceDto.class)); + + /* test */ + assertThrows(QueryNotFoundException.class, () -> { + dataServiceGateway.exportQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void exportQuery_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ExportResourceDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.exportQuery(DATABASE_1_ID, QUERY_1_ID); + }); + } + + @Test + public void getTableSchemas_succeeds() throws DataServiceException, DataServiceConnectionException, TableNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(new TableDto[]{})); + + /* test */ + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + } + + @Test + public void getTableSchemas_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getTableSchemas_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getTableSchemas_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class)); + + /* test */ + assertThrows(TableNotFoundException.class, () -> { + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getTableSchemas_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getTableSchemas_emptyBody_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getViewSchemas_succeeds() throws DataServiceException, DataServiceConnectionException, + ViewNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(new ViewDto[]{})); + + /* test */ + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + } + + @Test + public void getViewSchemas_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getViewSchemas_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getViewSchemas_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class)); + + /* test */ + assertThrows(ViewNotFoundException.class, () -> { + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getViewSchemas_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getViewSchemas_emptyBody_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(ViewDto[].class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getViewSchemas(DATABASE_1_ID); + }); + } + + @Test + public void getTableStatistics_succeeds() throws DataServiceException, DataServiceConnectionException, + TableNotFoundException { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TABLE_8_STATISTIC_DTO)); + + /* test */ + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + } + + @Test + public void getTableStatistics_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class)); + + /* test */ + assertThrows(DataServiceConnectionException.class, () -> { + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + }); + } + + @Test + public void getTableStatistics_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class)); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + }); + } + + @Test + public void getTableStatistics_notFound_fails() { + + /* mock */ + doThrow(HttpClientErrorException.NotFound.class) + .when(dataServiceRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class)); + + /* test */ + assertThrows(TableNotFoundException.class, () -> { + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + }); + } + + @Test + public void getTableStatistics_responseCode_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + }); + } + + @Test + public void getTableStatistics_emptyBody_fails() { + + /* mock */ + when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableStatisticDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .build()); + + /* test */ + assertThrows(DataServiceException.class, () -> { + dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID); + }); + } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java index 06e75c62fec70377bf0dabb56b11036cedce22a9..f60211d5902972641a8e2473fd5fd76b289ee571 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/KeycloakGatewayUnitTest.java @@ -16,12 +16,11 @@ import org.springframework.http.*; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @Log4j2 @@ -31,6 +30,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { @MockBean @Qualifier("keycloakRestTemplate") + private RestTemplate keycloakRestTemplate; + + @MockBean + @Qualifier("restTemplate") private RestTemplate restTemplate; @Autowired @@ -41,7 +44,7 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { CredentialsInvalidException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); @@ -50,11 +53,11 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void obtainToken_fails() { + public void obtainToken_connection_fails() { /* mock */ - doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) - .when(restTemplate) + doThrow(HttpServerErrorException.BadGateway.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); /* test */ @@ -63,15 +66,43 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { }); } + @Test + public void obtainToken_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + keycloakGateway.obtainToken(); + }); + } + + @Test + public void obtainToken_unexpected_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(AuthServiceException.class, () -> { + keycloakGateway.obtainToken(); + }); + } + @Test public void createUser_succeeds() throws UserExistsException, EmailExistsException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.CREATED) .build()); @@ -83,10 +114,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { public void createUser_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -96,32 +127,15 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { }); } - @Test - public void createUser_sameEMail_fails() { - - /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .body(TOKEN_DTO)); - doThrow(HttpClientErrorException.Conflict.create(HttpStatus.CONFLICT, "same email", new HttpHeaders(), new byte[]{}, null)) - .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); - - /* test */ - assertThrows(EmailExistsException.class, () -> { - keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); - }); - } - @Test public void createUser_sameUsername_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpClientErrorException.Conflict.create(HttpStatus.CONFLICT, "same username", new HttpHeaders(), new byte[]{}, null)) - .when(restTemplate) + doThrow(HttpClientErrorException.Conflict.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); /* test */ @@ -131,14 +145,14 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void createUser_unexpected_fails() { + public void createUser_connection_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) - .when(restTemplate) + doThrow(HttpServerErrorException.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); /* test */ @@ -151,10 +165,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { public void deleteUser_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .build()); @@ -169,10 +183,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { AuthServiceConnectionException, CredentialsInvalidException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -181,48 +195,48 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void deleteUser_unexpected_fails() { + public void deleteUser_notFound_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(ResourceAccessException.class) - .when(restTemplate) + doThrow(HttpClientErrorException.NotFound.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(AuthServiceException.class, () -> { + assertThrows(UserNotFoundException.class, () -> { keycloakGateway.deleteUser(USER_1_ID); }); } @Test - public void deleteUser_notFound_fails() { + public void deleteUser_unexpected_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpClientErrorException.NotFound.create(HttpStatus.NOT_FOUND, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) - .when(restTemplate) + doThrow(HttpClientErrorException.Conflict.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(UserNotFoundException.class, () -> { + assertThrows(AuthServiceException.class, () -> { keycloakGateway.deleteUser(USER_1_ID); }); } @Test - public void deleteUser_unexpected2_fails() { + public void deleteUser_connection_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) - .when(restTemplate) + doThrow(HttpServerErrorException.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); /* test */ @@ -236,10 +250,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { CredentialsInvalidException { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) .build()); @@ -251,10 +265,10 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { public void updateUserCredentials_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .build()); @@ -265,14 +279,14 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void updateUserCredentials_unexpected_fails() { + public void updateUserCredentials_connection_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) - .when(restTemplate) + doThrow(HttpServerErrorException.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ @@ -281,14 +295,31 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { }); } + @Test + public void updateUserCredentials_unexpected_fails() { + + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + doThrow(HttpClientErrorException.Conflict.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(AuthServiceException.class, () -> { + keycloakGateway.updateUserCredentials(USER_1_ID, USER_1_PASSWORD_DTO); + }); + } + @Test public void findByUsername_notFound_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(new UserDto[]{})); @@ -299,18 +330,18 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { } @Test - public void findByUsername_remote_fails() { + public void findByUsername_connection_fails() { /* mock */ - when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(ResourceAccessException.class) - .when(restTemplate) + doThrow(HttpServerErrorException.class) + .when(keycloakRestTemplate) .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class)); /* test */ - assertThrows(AuthServiceException.class, () -> { + assertThrows(AuthServiceConnectionException.class, () -> { keycloakGateway.findByUsername(USER_1_USERNAME); }); } @@ -318,17 +349,196 @@ public class KeycloakGatewayUnitTest extends AbstractUnitTest { @Test public void findByUsername_unexpected_fails() { + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + doThrow(HttpClientErrorException.Conflict.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class)); + + /* test */ + assertThrows(AuthServiceException.class, () -> { + keycloakGateway.findByUsername(USER_1_USERNAME); + }); + } + + @Test + public void findById_succeeds() throws UserNotFoundException, AuthServiceException, AuthServiceConnectionException, + CredentialsInvalidException { + + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(USER_1_KEYCLOAK_DTO)); + + /* test */ + final UserDto response = keycloakGateway.findById(USER_1_ID); + assertEquals(USER_1_ID, response.getId()); + } + + @Test + public void findById_notFound_fails() { + + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + doThrow(HttpClientErrorException.NotFound.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto.class)); + + /* test */ + assertThrows(UserNotFoundException.class, () -> { + keycloakGateway.findById(USER_1_ID); + }); + } + + @Test + public void findById_connection_fails() { + + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + doThrow(HttpServerErrorException.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto.class)); + + /* test */ + assertThrows(AuthServiceConnectionException.class, () -> { + keycloakGateway.findById(USER_1_ID); + }); + } + + @Test + public void findById_unexpected_fails() { + + /* mock */ + when(keycloakRestTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + doThrow(HttpClientErrorException.Conflict.class) + .when(keycloakRestTemplate) + .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto.class)); + + /* test */ + assertThrows(AuthServiceException.class, () -> { + keycloakGateway.findById(USER_1_ID); + }); + } + + @Test + public void refreshUserToken_succeeds() throws AuthServiceConnectionException, CredentialsInvalidException { + /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .body(TOKEN_DTO)); - doThrow(HttpServerErrorException.BadGateway.create(HttpStatus.BAD_GATEWAY, "", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) + + /* test */ + final TokenDto response = keycloakGateway.refreshUserToken(TOKEN_DTO.getRefreshToken()); + assertNotNull(response.getAccessToken()); + } + + @Test + public void refreshUserToken_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) .when(restTemplate) - .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(UserDto[].class)); + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); /* test */ assertThrows(AuthServiceConnectionException.class, () -> { - keycloakGateway.findByUsername(USER_1_USERNAME); + keycloakGateway.refreshUserToken(TOKEN_DTO.getRefreshToken()); + }); + } + + @Test + public void refreshUserToken_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + keycloakGateway.refreshUserToken(TOKEN_DTO.getRefreshToken()); + }); + } + + @Test + public void refreshUserToken_badRequest_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + keycloakGateway.refreshUserToken(TOKEN_DTO.getRefreshToken()); + }); + } + + @Test + public void refreshUserToken_badRequestInactiveSession_fails() { + + /* mock */ + doThrow(HttpClientErrorException.BadRequest.create(HttpStatus.BAD_REQUEST, "Session not active", new HttpHeaders(), new byte[]{}, Charset.defaultCharset())) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + keycloakGateway.refreshUserToken(TOKEN_DTO.getRefreshToken()); + }); + } + + @Test + public void obtainUserToken_succeeds() throws AuthServiceConnectionException, CredentialsInvalidException, + AccountNotSetupException { + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class))) + .thenReturn(ResponseEntity.status(HttpStatus.OK) + .body(TOKEN_DTO)); + + /* test */ + final TokenDto response = keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); + assertNotNull(response.getAccessToken()); + } + + @Test + public void obtainUserToken_connection_fails() { + + /* mock */ + doThrow(HttpServerErrorException.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(AuthServiceConnectionException.class, () -> { + keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); + }); + } + + @Test + public void obtainUserToken_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(TokenDto.class)); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + keycloakGateway.obtainUserToken(USER_1_USERNAME, USER_1_PASSWORD); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java index 4572711ed228bf6007d79ced93100663e05e2b07..bcd27107bc0189614b4086e0b333fa16cf16cb84 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/OrcidGatewayUnitTest.java @@ -15,9 +15,11 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @Log4j2 @@ -26,7 +28,6 @@ import static org.mockito.Mockito.*; public class OrcidGatewayUnitTest extends AbstractUnitTest { @MockBean - @Qualifier("keycloakRestTemplate") private RestTemplate restTemplate; @Autowired @@ -45,15 +46,17 @@ public class OrcidGatewayUnitTest extends AbstractUnitTest { } @Test - public void findByUrl_fails() throws OrcidNotFoundException { + public void findByUrl_fails() { /* mock */ - doThrow(ResourceAccessException.class) + doThrow(HttpServerErrorException.class) .when(restTemplate) .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(OrcidDto.class)); /* test */ - orcidGateway.findByUrl(USER_1_ORCID_URL); + assertThrows(OrcidNotFoundException.class, () -> { + orcidGateway.findByUrl(USER_1_ORCID_URL); + }); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java index 384cd290b36e6696bd14c4a6d74cb88838729d5c..ff9d4f741c18b2dfcd94dca91c344912fddd2167 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/RorGatewayUnitTest.java @@ -7,14 +7,14 @@ import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.*; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @Log4j2 @@ -23,7 +23,6 @@ import static org.mockito.Mockito.*; public class RorGatewayUnitTest extends AbstractUnitTest { @MockBean - @Qualifier("keycloakRestTemplate") private RestTemplate restTemplate; @Autowired @@ -42,15 +41,17 @@ public class RorGatewayUnitTest extends AbstractUnitTest { } @Test - public void findById_fails() throws RorNotFoundException { + public void findById_fails() { /* mock */ - doThrow(ResourceAccessException.class) + doThrow(HttpServerErrorException.class) .when(restTemplate) .exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(RorDto.class)); /* test */ - rorGateway.findById("04d836q62"); + assertThrows(RorNotFoundException.class, () -> { + rorGateway.findById("04d836q62"); + }); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java index b4b205d4f49ceee118774909ea8f568a23deff3b..aa1c9d4f056f61680aeb341f2cebafdbe262a2b5 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java @@ -135,6 +135,20 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { }); } + @Test + public void delete_unauthorized_fails() { + + /* mock */ + doThrow(HttpClientErrorException.Unauthorized.class) + .when(restTemplate) + .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); + + /* test */ + assertThrows(SearchServiceException.class, () -> { + searchServiceGateway.delete(DATABASE_1_ID); + }); + } + @Test public void delete_unexpectedResponse_fails() { final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.OK) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java index 732c11124f38fc0bbf2338a93f6d33d04b14d38f..8a72f2cabbe0f4eda33ff77ef125eed2c842e12d 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java @@ -15,9 +15,7 @@ import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserDto; import at.tuwien.entities.container.Container; import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierType; +import at.tuwien.entities.identifier.*; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -104,12 +102,42 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { /* test */ final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_1_CREATE_DTO); - assertNull(response.getDatabase()); - assertNull(response.getViewId()); - assertNull(response.getQueryId()); - assertNull(response.getTableId()); - assertNull(response.getDoi()); - assertEquals(IDENTIFIER_1_TYPE, response.getType()); + assertNotNull(response.getTitles()); + final List<IdentifierTitle> titles = response.getTitles(); + assertEquals(2, titles.size()); + final IdentifierTitle title0 = titles.get(0); + assertEquals(IDENTIFIER_1_TITLE_1_TITLE, title0.getTitle()); + assertEquals(IDENTIFIER_1_TITLE_1_LANG, title0.getLanguage()); + assertEquals(IDENTIFIER_1_TITLE_1_TYPE, title0.getTitleType()); + final IdentifierTitle title1 = titles.get(1); + assertEquals(IDENTIFIER_1_TITLE_2_TITLE, title1.getTitle()); + assertEquals(IDENTIFIER_1_TITLE_2_LANG, title1.getLanguage()); + assertEquals(IDENTIFIER_1_TITLE_2_TYPE, title1.getTitleType()); + assertNotNull(response.getDescriptions()); + assertEquals(1, response.getDescriptions().size()); + final List<IdentifierDescription> descriptions = response.getDescriptions(); + final IdentifierDescription description0 = descriptions.get(0); + assertNull(description0.getId()); + assertEquals(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION, description0.getDescription()); + assertEquals(IDENTIFIER_1_DESCRIPTION_1_LANG, description0.getLanguage()); + assertEquals(IDENTIFIER_1_DESCRIPTION_1_TYPE, description0.getDescriptionType()); + assertNotNull(response.getCreators()); + assertEquals(1, response.getCreators().size()); + final Creator creator0 = response.getCreators().get(0); + assertNotNull(creator0); + assertNull(creator0.getId()); + assertEquals(IDENTIFIER_1_CREATOR_1_FIRSTNAME, creator0.getFirstname()); + assertEquals(IDENTIFIER_1_CREATOR_1_LASTNAME, creator0.getLastname()); + assertEquals(IDENTIFIER_1_CREATOR_1_NAME, creator0.getCreatorName()); + assertEquals(IDENTIFIER_1_CREATOR_1_ORCID, creator0.getNameIdentifier()); + assertEquals(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE, creator0.getNameIdentifierScheme()); + assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION, creator0.getAffiliation()); + assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER, creator0.getAffiliationIdentifier()); + assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME, creator0.getAffiliationIdentifierScheme()); + assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI, creator0.getAffiliationIdentifierSchemeUri()); + assertNotNull(response.getFunders()); + assertEquals(1, response.getFunders().size()); + assertNull(response.getRelatedIdentifiers()); /* mapstruct strategy for empty values is to set null */ } @Test @@ -154,6 +182,8 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { @Test public void customDatabaseToDatabaseDto_succeeds() { + final Database debug = DATABASE_1; + /* test */ final DatabaseDto response = metadataMapper.customDatabaseToDatabaseDto(DATABASE_1); assertEquals(DATABASE_1_ID, response.getId()); @@ -193,7 +223,9 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(TABLE_1_DESCRIPTION, table0.getDescription()); assertEquals(DATABASE_1_ID, table0.getTdbid()); assertEquals(USER_1_ID, table0.getCreatedBy()); + assertNotNull(table0.getOwner()); assertEquals(USER_1_ID, table0.getOwner().getId()); + assertNotNull(table0.getCreator()); assertEquals(USER_1_ID, table0.getCreator().getId()); assertEquals(TABLE_1_AVG_ROW_LENGTH, table0.getAvgRowLength()); assertEquals(TABLE_1_NUM_ROWS, table0.getNumRows()); @@ -244,7 +276,9 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(TABLE_2_DESCRIPTION, table1.getDescription()); assertEquals(DATABASE_1_ID, table1.getTdbid()); assertEquals(USER_2_ID, table1.getCreatedBy()); + assertNotNull(table1.getOwner()); assertEquals(USER_2_ID, table1.getOwner().getId()); + assertNotNull(table1.getCreator()); assertEquals(USER_2_ID, table1.getCreator().getId()); assertEquals(TABLE_2_AVG_ROW_LENGTH, table1.getAvgRowLength()); assertEquals(TABLE_2_NUM_ROWS, table1.getNumRows()); @@ -316,7 +350,9 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(TABLE_3_DESCRIPTION, table2.getDescription()); assertEquals(DATABASE_1_ID, table2.getTdbid()); assertEquals(USER_3_ID, table2.getCreatedBy()); + assertNotNull(table2.getOwner()); assertEquals(USER_3_ID, table2.getOwner().getId()); + assertNotNull(table2.getCreator()); assertEquals(USER_3_ID, table2.getCreator().getId()); assertEquals(TABLE_3_AVG_ROW_LENGTH, table2.getAvgRowLength()); assertEquals(TABLE_3_NUM_ROWS, table2.getNumRows()); @@ -359,7 +395,9 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertEquals(TABLE_4_DESCRIPTION, table3.getDescription()); assertEquals(DATABASE_1_ID, table3.getTdbid()); assertEquals(USER_1_ID, table3.getCreatedBy()); + assertNotNull(table3.getOwner()); assertEquals(USER_1_ID, table3.getOwner().getId()); + assertNotNull(table3.getCreator()); assertEquals(USER_1_ID, table3.getCreator().getId()); assertEquals(TABLE_4_AVG_ROW_LENGTH, table3.getAvgRowLength()); assertEquals(TABLE_4_NUM_ROWS, table3.getNumRows()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c1ca4ab2f2bb168a77051a269c6a3ef79fd9d63b --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationIntegrationTest.java @@ -0,0 +1,293 @@ +package at.tuwien.mvc; + +import at.tuwien.exception.AuthServiceConnectionException; +import at.tuwien.exception.AuthServiceException; +import at.tuwien.exception.CredentialsInvalidException; +import at.tuwien.gateway.KeycloakGateway; +import at.tuwien.repository.ContainerRepository; +import at.tuwien.repository.DatabaseRepository; +import at.tuwien.repository.LicenseRepository; +import at.tuwien.repository.UserRepository; +import at.tuwien.test.AbstractUnitTest; +import at.tuwien.utils.KeycloakUtils; +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.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.List; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@Log4j2 +@ExtendWith(SpringExtension.class) +@AutoConfigureMockMvc +@Testcontainers +@SpringBootTest +public class AuthenticationIntegrationTest extends AbstractUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private KeycloakUtils keycloakUtils; + + @Autowired + private KeycloakGateway keycloakGateway; + + @Autowired + private UserRepository userRepository; + + @Autowired + private LicenseRepository licenseRepository; + + @Autowired + private ContainerRepository containerRepository; + + @Autowired + private DatabaseRepository databaseRepository; + + @Container + private static KeycloakContainer keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:21.0") + .withImagePullPolicy(PullPolicy.alwaysPull()) + .withAdminUsername("admin") + .withAdminPassword("admin") + .withRealmImportFile("./init/dbrepo-realm.json") + .withEnv("KC_HOSTNAME_STRICT_HTTPS", "false"); + + @DynamicPropertySource + static void keycloakProperties(DynamicPropertyRegistry registry) { + registry.add("dbrepo.endpoints.authService", () -> "http://localhost:" + keycloakContainer.getMappedPort(8080)); + } + + @BeforeEach + public void beforeEach() throws AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { + genesis(); + /* metadata database */ + licenseRepository.save(LICENSE_1); + containerRepository.save(CONTAINER_1); + userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4)); + databaseRepository.save(DATABASE_1); + /* keycloak */ + keycloakUtils.deleteUser(USER_1_USERNAME); + } + + @Test + public void findById_database_basicUser_fails() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().doesNotExist("X-Username")) + .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) + .andExpect(status().isOk()); + } + + @Test + public void findById_database_basicAdmin_succeeds() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(username = "admin", authorities = {"system"}) + public void findById_database_bearerAdmin_succeeds() throws Exception { + + /* test */ + this.mockMvc.perform(get("/api/database/1")) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) + .andExpect(status().isOk()); + } + + @Test + public void findById_table_basicUser_fails() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().doesNotExist("X-Username")) + .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("X-Host")) + .andExpect(header().doesNotExist("X-Port")) + .andExpect(header().doesNotExist("X-Type")) + .andExpect(header().doesNotExist("X-Database")) + .andExpect(header().doesNotExist("X-Sidecar-Host")) + .andExpect(header().doesNotExist("X-Sidecar-Port")) + .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) + .andExpect(status().isOk()); + } + + @Test + public void findById_table_basicAdmin_succeeds() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1/table/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("X-Host", CONTAINER_1_HOST)) + .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) + .andExpect(header().string("X-Type", IMAGE_1_JDBC)) + .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) + .andExpect(header().string("X-Sidecar-Host", CONTAINER_1_SIDECAR_HOST)) + .andExpect(header().string("X-Sidecar-Port", "" + CONTAINER_1_SIDECAR_PORT)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Sidecar-Host X-Sidecar-Port")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(username = "admin", authorities = {"system"}) + public void findById_table_bearerAdmin_succeeds() throws Exception { + + /* test */ + this.mockMvc.perform(get("/api/database/1/table/1")) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("X-Host", CONTAINER_1_HOST)) + .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) + .andExpect(header().string("X-Type", IMAGE_1_JDBC)) + .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) + .andExpect(header().string("X-Sidecar-Host", CONTAINER_1_SIDECAR_HOST)) + .andExpect(header().string("X-Sidecar-Port", "" + CONTAINER_1_SIDECAR_PORT)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Sidecar-Host X-Sidecar-Port")) + .andExpect(status().isOk()); + } + + @Test + public void findById_view_basicUser_fails() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1/view/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().doesNotExist("X-Username")) + .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("X-Host")) + .andExpect(header().doesNotExist("X-Port")) + .andExpect(header().doesNotExist("X-Type")) + .andExpect(header().doesNotExist("X-Database")) + .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) + .andExpect(status().isOk()); + } + + @Test + public void findById_view_basicAdmin_succeeds() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/database/1/view/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("X-Host", CONTAINER_1_HOST)) + .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) + .andExpect(header().string("X-Type", IMAGE_1_JDBC)) + .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(username = "admin", authorities = {"system"}) + public void findById_view_bearerAdmin_succeeds() throws Exception { + + /* test */ + this.mockMvc.perform(get("/api/database/1/view/1")) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("X-Host", CONTAINER_1_HOST)) + .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT)) + .andExpect(header().string("X-Type", IMAGE_1_JDBC)) + .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database")) + .andExpect(status().isOk()); + } + + @Test + public void findById_container_basicUser_fails() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/container/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().doesNotExist("X-Username")) + .andExpect(header().doesNotExist("X-Password")) + .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) + .andExpect(status().isOk()); + } + + @Test + public void findById_container_basicAdmin_succeeds() throws Exception { + + /* mock */ + keycloakGateway.createUser(USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST); + + /* test */ + this.mockMvc.perform(get("/api/container/1").with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(username = "admin", authorities = {"system"}) + public void findById_container_bearerAdmin_succeeds() throws Exception { + + /* test */ + this.mockMvc.perform(get("/api/container/1")) + .andDo(print()) + .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) + .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) + .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password")) + .andExpect(status().isOk()); + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index 2b2df73909dfa67fe416d279f864b580f6a776b2..d3f75d70602ffb2dad2a6b2adc8797eb7636135c 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -500,7 +500,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-table", "delete-table", - "modify-table-column-semantics", "modify-foreign-table-column-semantics", "admin", + "modify-table-column-semantics", "modify-foreign-table-column-semantics", "update-table-statistic", "table-semantic-analyse"}) public void prometheusTableEndpoint_succeeds() { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java index 75a08540b0cae6f9528a25b3c6c855bff9358991..fa939b0cb1795b08257b743ddb239bd075871cf0 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java @@ -73,7 +73,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { } @Test - public void create_succeeds() throws ServiceException, ServiceConnectionException, + public void create_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -99,7 +99,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { accessService.create(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -113,7 +113,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { accessService.create(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -141,7 +141,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { accessService.create(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -223,7 +223,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { } @Test - public void update_succeeds() throws ServiceException, ServiceConnectionException, AccessNotFoundException, + public void update_succeeds() throws DataServiceException, DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -249,7 +249,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { accessService.update(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -263,7 +263,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { accessService.update(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -291,7 +291,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { accessService.update(DATABASE_1, USER_1, AccessTypeDto.WRITE_ALL); }); } @@ -373,7 +373,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { } @Test - public void delete_succeeds() throws ServiceException, ServiceConnectionException, AccessNotFoundException, + public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -401,7 +401,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { accessService.delete(DATABASE_1, USER_1); }); } @@ -429,7 +429,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class)); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { accessService.delete(DATABASE_1, USER_1); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java index ba560f0e47ff2426f2bb3623048a03f5f6c58d13..8b7be04cb6b4c2b383e54c02c18966855eeeca25 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AuthenticationServiceIntegrationTest.java @@ -64,8 +64,8 @@ public class AuthenticationServiceIntegrationTest extends AbstractUnitTest { } @Test - public void create_succeeds() throws EmailExistsException, UserExistsException, ServiceException, - ServiceConnectionException, AuthServiceException, AuthServiceConnectionException, + public void create_succeeds() throws EmailExistsException, UserExistsException, + DataServiceConnectionException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java index a340e293452b135d8d37b8bd212ea3ee425cbd60..c9a2ad62b61d324934236c885bf6be2aca586e9e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/BrokerServiceIntegrationTest.java @@ -1,15 +1,13 @@ package at.tuwien.service; import at.tuwien.config.RabbitConfig; +import at.tuwien.exception.*; import at.tuwien.test.AbstractUnitTest; import at.tuwien.api.amqp.GrantExchangePermissionsDto; import at.tuwien.api.amqp.TopicPermissionDto; import at.tuwien.api.amqp.VirtualHostPermissionDto; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; -import at.tuwien.exception.ServiceConnectionException; -import at.tuwien.exception.ServiceException; -import at.tuwien.repository.*; import at.tuwien.utils.AmqpUtils; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -44,9 +42,6 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Autowired private BrokerService brokerService; - @Autowired - private AmqpUtils amqpUtils; - @Container private static final RabbitMQContainer rabbitContainer = new RabbitMQContainer("rabbitmq:3-management") .withUser(USER_1_USERNAME, USER_1_PASSWORD, Set.of("administrator")) @@ -55,10 +50,6 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @DynamicPropertySource static void rabbitProperties(DynamicPropertyRegistry registry) { registry.add("dbrepo.endpoints.brokerService", rabbitContainer::getHttpUrl); - registry.add("spring.rabbitmq.host", rabbitContainer::getHost); - registry.add("spring.rabbitmq.port", rabbitContainer::getAmqpPort); - registry.add("spring.rabbitmq.username", rabbitContainer::getAdminUsername); - registry.add("spring.rabbitmq.password", rabbitContainer::getAdminPassword); } @BeforeEach @@ -67,7 +58,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updatePermissions_empty_succeeds() throws ServiceException, ServiceConnectionException { + public void updatePermissions_empty_succeeds() throws BrokerServiceException, BrokerServiceConnectionException { /* test */ final VirtualHostPermissionDto permissions = setVirtualHostPermissions_generic(); @@ -79,7 +70,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updatePermissions_writeAll_succeeds() throws ServiceException, ServiceConnectionException { + public void updatePermissions_writeAll_succeeds() throws BrokerServiceException, BrokerServiceConnectionException { /* test */ final VirtualHostPermissionDto permissions = setVirtualHostPermissions_generic(); @@ -91,7 +82,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updatePermissions_writeOwn_succeeds() throws ServiceException, ServiceConnectionException { + public void updatePermissions_writeOwn_succeeds() throws BrokerServiceException, BrokerServiceConnectionException { /* test */ final VirtualHostPermissionDto permissions = setVirtualHostPermissions_generic(); @@ -103,7 +94,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { } @Test - public void updatePermissions_read_succeeds() throws ServiceException, ServiceConnectionException { + public void updatePermissions_read_succeeds() throws BrokerServiceException, BrokerServiceConnectionException { /* test */ final VirtualHostPermissionDto permissions = setVirtualHostPermissions_generic(); @@ -116,7 +107,8 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void setTopicExchangePermissions_empty_succeeds() throws ServiceException, ServiceConnectionException { + public void setTopicExchangePermissions_empty_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { /* test */ final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of()); @@ -129,7 +121,8 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void setTopicExchangePermissions_writeAll_succeeds() throws ServiceException, ServiceConnectionException { + public void setTopicExchangePermissions_writeAll_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { /* test */ final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of(DATABASE_1_USER_1_WRITE_ALL_ACCESS)); @@ -142,7 +135,8 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void setTopicExchangePermissions_writeOwn_succeeds() throws ServiceException, ServiceConnectionException { + public void setTopicExchangePermissions_writeOwn_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { /* test */ final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of(DATABASE_1_USER_1_WRITE_OWN_ACCESS)); @@ -155,7 +149,8 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void setTopicExchangePermissions_read_succeeds() throws ServiceException, ServiceConnectionException { + public void setTopicExchangePermissions_read_succeeds() throws BrokerServiceException, + BrokerServiceConnectionException { /* test */ final TopicPermissionDto permissions = setTopicExchangePermissions_generic(List.of(DATABASE_1_USER_1_READ_ACCESS)); @@ -170,8 +165,9 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - protected VirtualHostPermissionDto setVirtualHostPermissions_generic() throws ServiceException, - ServiceConnectionException { + protected VirtualHostPermissionDto setVirtualHostPermissions_generic() throws BrokerServiceException, + BrokerServiceConnectionException { + final AmqpUtils amqpUtils = new AmqpUtils(rabbitContainer.getHttpUrl()); /* mock */ amqpUtils.setVirtualHostPermissions(REALM_DBREPO_NAME, USER_1_USERNAME, USER_1_RABBITMQ_GRANT_DTO); @@ -183,13 +179,14 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { @Transactional(readOnly = true) protected TopicPermissionDto setTopicExchangePermissions_generic(List<DatabaseAccess> accesses) - throws ServiceException, ServiceConnectionException { + throws BrokerServiceException, BrokerServiceConnectionException { + final AmqpUtils amqpUtils = new AmqpUtils(rabbitContainer.getHttpUrl()); final GrantExchangePermissionsDto request = GrantExchangePermissionsDto.builder() .exchange(rabbitConfig.getExchangeName()) .read("") .write("") .build(); - final User user1 = User.builder() + final User user = User.builder() .id(USER_1_ID) .username(USER_1_USERNAME) .accesses(accesses) @@ -200,7 +197,7 @@ public class BrokerServiceIntegrationTest extends AbstractUnitTest { amqpUtils.setTopicPermissions(REALM_DBREPO_NAME, USER_1_USERNAME, request); /* test */ - brokerService.setTopicExchangePermissions(user1); + brokerService.setTopicExchangePermissions(user); return amqpUtils.getTopicPermissions(USER_1_USERNAME); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java index 164f335eb73f68c986583da9881b743a32c44a06..7cec5e624187fcb5c5285fc4fc0b4787b6a4e9a0 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java @@ -6,6 +6,7 @@ import at.tuwien.test.AbstractUnitTest; import at.tuwien.entities.database.table.columns.TableColumnConcept; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java index 7443439608dbf6c353a5873c42aafcf9368b3db2..0c0cf075c4d83645a7df6bae035cbae4d458ad1e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java @@ -1,6 +1,10 @@ package at.tuwien.service; +import at.tuwien.api.identifier.BibliographyTypeDto; +import at.tuwien.entities.identifier.Creator; import at.tuwien.entities.identifier.Identifier; +import at.tuwien.entities.identifier.IdentifierStatusType; +import at.tuwien.entities.identifier.NameIdentifierSchemeType; import at.tuwien.repository.ContainerRepository; import at.tuwien.repository.DatabaseRepository; import at.tuwien.repository.LicenseRepository; @@ -19,6 +23,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -38,7 +43,7 @@ import static org.mockito.Mockito.when; @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -@SpringBootTest(properties = "spring.profiles.active:local,doi") +@SpringBootTest(properties = "spring.profiles.active:local,junit,doi") public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { @MockBean @@ -71,15 +76,62 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); - containerRepository.save(CONTAINER_1); - userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4)); - databaseRepository.save(DATABASE_1); + containerRepository.saveAll(List.of(CONTAINER_1, CONTAINER_2, CONTAINER_3, CONTAINER_4)); + userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_5)); + databaseRepository.saveAll(List.of(DATABASE_1, DATABASE_2, DATABASE_3, DATABASE_4)); } @Test - public void save_database_succeeds() throws ServiceException, ServiceConnectionException, + public void findAll_succeeds() { + + /* test */ + final List<Identifier> response = dataCiteIdentifierService.findAll(null, null, null, null, null); + assertEquals(7, response.size()); + for (Long id : List.of(IDENTIFIER_1_ID, IDENTIFIER_2_ID, IDENTIFIER_3_ID, IDENTIFIER_4_ID, IDENTIFIER_5_ID, IDENTIFIER_6_ID, IDENTIFIER_7_ID)) { + assertTrue(response.stream().map(Identifier::getId).toList().contains(id)); + } + } + + @Test + public void findAll_databaseId_succeeds() { + + /* test */ + final List<Identifier> response = dataCiteIdentifierService.findAll(null, DATABASE_1_ID, null, null, null); + assertEquals(4, response.size()); + assertTrue(response.stream().map(Identifier::getId).toList().contains(IDENTIFIER_1_ID)); + assertTrue(response.stream().map(Identifier::getId).toList().contains(IDENTIFIER_2_ID)); + assertTrue(response.stream().map(Identifier::getId).toList().contains(IDENTIFIER_3_ID)); + assertTrue(response.stream().map(Identifier::getId).toList().contains(IDENTIFIER_4_ID)); + } + + @Test + public void findAll_queryId_succeeds() { + + /* test */ + final List<Identifier> response = dataCiteIdentifierService.findAll(null, null, QUERY_1_ID, null, null); + assertEquals(1, response.size()); + } + + @Test + public void findAll_empty_succeeds() { + + /* test */ + final List<Identifier> response = dataCiteIdentifierService.findAll(null, DATABASE_2_ID, QUERY_1_ID, null, null); + assertEquals(0, response.size()); + } + + @Test + public void find_succeeds() throws IdentifierNotFoundException { + + /* test */ + final Identifier response = dataCiteIdentifierService.find(IDENTIFIER_1_ID); + assertEquals(IDENTIFIER_1, response); + } + + @Test + public void save_database_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, MalformedException, IdentifierNotFoundException, ViewNotFoundException, - QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) .body(IDENTIFIER_1_DATA_CITE); @@ -122,15 +174,16 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { .thenReturn(DATABASE_1_DTO); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { dataCiteIdentifierService.save(DATABASE_1, USER_1, IDENTIFIER_1_SAVE_DTO); }); } @Test - public void create_succeeds() throws SearchServiceException, MalformedException, ServiceException, - QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { + public void create_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + ExternalServiceException { final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) .body(IDENTIFIER_1_DATA_CITE); @@ -144,9 +197,10 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, ServiceException, - QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { + public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + ExternalServiceException { final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) .body(IDENTIFIER_1_DATA_CITE); @@ -159,4 +213,128 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { assertEquals(IDENTIFIER_1_DOI_NOT_NULL, response.getDoi()); } + @Test + public void publish_succeeds() throws MalformedException, DataServiceConnectionException, SearchServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, + ExternalServiceException { + final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) + .body(IDENTIFIER_7_DATA_CITE); + + /* mock */ + when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(dataCiteBodyParameterizedTypeReference))) + .thenReturn(mock); + + /* test */ + final Identifier response = dataCiteIdentifierService.publish(IDENTIFIER_7_ID); + assertEquals(IDENTIFIER_7_ID, response.getId()); + assertEquals(IdentifierStatusType.PUBLISHED, response.getStatus()); + } + + @Test + public void exportMetadata_succeeds() { + + /* test */ + final InputStreamResource response = dataCiteIdentifierService.exportMetadata(IDENTIFIER_1); + assertNotNull(response); + } + + @Test + public void exportBibliography_apa_succeeds() throws MalformedException { + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(IDENTIFIER_1, BibliographyTypeDto.APA); + assertTrue(response.contains(IDENTIFIER_1_TITLE_1.getTitle())); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR)); + assertTrue(response.contains(IDENTIFIER_1_CREATOR_1.getLastname())); + } + + @Test + public void exportBibliography_apaMixedPersonAndOrg_succeeds() throws MalformedException { + final Creator org = Creator.builder() + .id(CREATOR_2_ID) + .creatorName("Institute of Science and Technology Austria") + .nameIdentifier("https://ror.org/03gnh5541") + .nameIdentifierScheme(NameIdentifierSchemeType.ROR) + .build(); + final Identifier identifier = IDENTIFIER_1.toBuilder() + .creators(List.of(IDENTIFIER_1_CREATOR_1, org)) + .build(); + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(identifier, BibliographyTypeDto.APA); + final String title = IDENTIFIER_1_CREATOR_1.getFirstname().charAt(0) + "., " + IDENTIFIER_1_CREATOR_1.getLastname() + " & Institute of Science and Technology Austria"; + assertTrue(response.contains(title), "expected title not found: " + title); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR), "expected publication year not found: " + IDENTIFIER_1_PUBLICATION_YEAR); + } + + @Test + public void exportBibliography_bibtex_succeeds() throws MalformedException { + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(IDENTIFIER_1, BibliographyTypeDto.BIBTEX); + assertTrue(response.contains(IDENTIFIER_1_TITLE_1.getTitle())); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR)); + assertTrue(response.contains(IDENTIFIER_1_CREATOR_1.getLastname())); + } + + @Test + public void exportBibliography_bibtexMixedPersonAndOrg_succeeds() throws MalformedException { + final Creator org = Creator.builder() + .id(CREATOR_2_ID) + .creatorName("Institute of Science and Technology Austria") + .nameIdentifier("https://ror.org/03gnh5541") + .nameIdentifierScheme(NameIdentifierSchemeType.ROR) + .build(); + final Identifier identifier = IDENTIFIER_1.toBuilder() + .creators(List.of(IDENTIFIER_1_CREATOR_1, org)) + .build(); + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(identifier, BibliographyTypeDto.BIBTEX); + final String title = IDENTIFIER_5_CREATOR_1.getLastname() + ", " + IDENTIFIER_1_CREATOR_1.getFirstname() + " and Institute of Science and Technology Austria"; + assertTrue(response.contains(title), "expected title not found: " + title); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR), "expected publication year not found: " + IDENTIFIER_1_PUBLICATION_YEAR); + } + + @Test + public void exportBibliography_ieee_succeeds() throws MalformedException { + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(IDENTIFIER_1, BibliographyTypeDto.IEEE); + assertTrue(response.contains(IDENTIFIER_1_TITLE_1.getTitle())); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR)); + assertTrue(response.contains(IDENTIFIER_1_CREATOR_1.getLastname())); + } + + @Test + public void exportBibliography_ieeeMixedPersonAndOrg_succeeds() throws MalformedException { + final Creator org = Creator.builder() + .id(CREATOR_2_ID) + .creatorName("Institute of Science and Technology Austria") + .nameIdentifier("https://ror.org/03gnh5541") + .nameIdentifierScheme(NameIdentifierSchemeType.ROR) + .build(); + final Identifier identifier = IDENTIFIER_1.toBuilder() + .creators(List.of(IDENTIFIER_1_CREATOR_1, org)) + .build(); + + /* test */ + final String response = dataCiteIdentifierService.exportBibliography(identifier, BibliographyTypeDto.IEEE); + final String title = IDENTIFIER_1_CREATOR_1.getFirstname().charAt(0) + ". " + IDENTIFIER_1_CREATOR_1.getLastname() + ", Institute of Science and Technology Austria"; + assertTrue(response.contains(title), "expected title not found: " + title); + assertTrue(response.contains("" + IDENTIFIER_1_PUBLICATION_YEAR), "expected publication year not found: " + IDENTIFIER_1_PUBLICATION_YEAR); + } + + @Test + public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, + IdentifierNotFoundException, SearchServiceException, SearchServiceConnectionException { + + /* mock */ + when(searchServiceGateway.update(any(Database.class))) + .thenReturn(DATABASE_1_DTO); + + /* test */ + dataCiteIdentifierService.delete(IDENTIFIER_1); + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java index 8ccb486638447039360f17b08d4a42712d77bdd0..283450cc256197b1add589295304bd69fbe89dab 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java @@ -47,9 +47,9 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { genesis(); /* metadata database */ licenseRepository.save(LICENSE_1); - containerRepository.save(CONTAINER_1); - userRepository.saveAll(List.of(USER_1, USER_2, USER_3)); - databaseRepository.save(DATABASE_1); + containerRepository.saveAll(List.of(CONTAINER_1, CONTAINER_2, CONTAINER_3, CONTAINER_4)); + userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4, USER_5)); + databaseRepository.saveAll(List.of(DATABASE_1, DATABASE_2, DATABASE_3, DATABASE_4)); } @Test @@ -94,4 +94,46 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { assertNotNull(response.getCreator().getAccesses()); } + @Test + @Transactional + public void findByInternalName_succeeds() throws DatabaseNotFoundException { + + /* test */ + final Database response = databaseService.findByInternalName(DATABASE_1_INTERNALNAME); + assertEquals(DATABASE_1_ID, response.getId()); + assertEquals(CONTAINER_1_ID, response.getCid()); + /* container */ + assertNotNull(response.getContainer()); + assertEquals(CONTAINER_1_ID, response.getContainer().getId()); + assertEquals(CONTAINER_1_NAME, response.getContainer().getName()); + assertEquals(CONTAINER_1_INTERNALNAME, response.getContainer().getInternalName()); + assertEquals(CONTAINER_1_HOST, response.getContainer().getHost()); + assertEquals(CONTAINER_1_PORT, response.getContainer().getPort()); + assertEquals(CONTAINER_1_UI_HOST, response.getContainer().getUiHost()); + assertEquals(CONTAINER_1_UI_PORT, response.getContainer().getUiPort()); + assertEquals(CONTAINER_1_UI_ADDITIONAL_FLAGS, response.getContainer().getUiAdditionalFlags()); + assertEquals(CONTAINER_1_SIDECAR_HOST, response.getContainer().getSidecarHost()); + assertEquals(CONTAINER_1_SIDECAR_PORT, response.getContainer().getSidecarPort()); + assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, response.getContainer().getPrivilegedUsername()); + assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, response.getContainer().getPrivilegedPassword()); + assertNotNull(response.getContainer().getImage()); + assertEquals(IMAGE_1_NAME, response.getContainer().getImage().getName()); + assertEquals(IMAGE_1_VERSION, response.getContainer().getImage().getVersion()); + assertEquals(IMAGE_1_DIALECT, response.getContainer().getImage().getDialect()); + assertEquals(IMAGE_1_JDBC, response.getContainer().getImage().getJdbcMethod()); + assertEquals(IMAGE_1_DRIVER, response.getContainer().getImage().getDriverClass()); + assertEquals(IMAGE_1_REGISTRY, response.getContainer().getImage().getRegistry()); + assertEquals(IMAGE_1_PORT, response.getContainer().getImage().getDefaultPort()); + assertNotNull(response.getContainer().getImage().getDateFormats()); + assertEquals(4, response.getContainer().getImage().getDateFormats().size()); + /* creator */ + assertNotNull(response.getCreator()); + assertEquals(USER_1_ID, response.getCreator().getId()); + assertEquals(USER_1_USERNAME, response.getCreator().getUsername()); + assertEquals(USER_1_EMAIL, response.getCreator().getEmail()); + assertEquals(USER_1_THEME, response.getCreator().getTheme()); + assertEquals(USER_1_LANGUAGE, response.getCreator().getLanguage()); + assertNotNull(response.getCreator().getAccesses()); + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java index ede17383813eb46445a33833d680644641b90a20..ea58ae16e4ac35931bb5f713b197bacdc37b6958 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java @@ -161,33 +161,35 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { } @Test - public void create_dataServiceError_fails() throws ServiceException, ServiceConnectionException { + public void create_dataServiceError_fails() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException { /* mock */ when(containerRepository.findById(DATABASE_1.getCid())) .thenReturn(Optional.of(CONTAINER_1)); - doThrow(ServiceException.class) + doThrow(DataServiceException.class) .when(dataServiceGateway) .createDatabase(any(CreateDatabaseDto.class)); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { generic_create(DATABASE_1_CREATE, DATABASE_1); }); } @Test - public void create_dataServiceConnection_fails() throws ServiceException, ServiceConnectionException { + public void create_dataServiceConnection_fails() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException { /* mock */ when(containerRepository.findById(DATABASE_1.getCid())) .thenReturn(Optional.of(CONTAINER_1)); - doThrow(ServiceConnectionException.class) + doThrow(DataServiceConnectionException.class) .when(dataServiceGateway) .createDatabase(any(CreateDatabaseDto.class)); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { generic_create(DATABASE_1_CREATE, DATABASE_1); }); } @@ -302,8 +304,8 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - protected Database generic_create(DatabaseCreateDto createDto, Database database) throws ServiceException, - ServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + protected Database generic_create(DatabaseCreateDto createDto, Database database) throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java index e664abd5163000e21029836faf0b8db536ddda65..6b3ff624b0e5ebf47757824f645e4a120e43b243 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java @@ -39,7 +39,6 @@ import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest -@Disabled("keep failing on CI but works locally") @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) public class IdentifierServicePersistenceTest extends AbstractUnitTest { @@ -154,9 +153,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_database_succeeds() throws ServiceException, ServiceConnectionException, MalformedException, - DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, QueryNotFoundException, - SearchServiceException, SearchServiceConnectionException { + public void save_database_succeeds() throws DataServiceException, DataServiceConnectionException, + MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { /* mock */ when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), eq(QueryDto.class))) @@ -168,9 +167,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_existsSubset_succeeds() throws ServiceException, ServiceConnectionException, MalformedException, - DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, QueryNotFoundException, - SearchServiceException, SearchServiceConnectionException { + public void save_existsSubset_succeeds() throws DataServiceException, DataServiceConnectionException, + MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { /* mock */ when(dataServiceGateway.findQuery(IDENTIFIER_5_DATABASE_ID, IDENTIFIER_5_QUERY_ID)) @@ -183,9 +182,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_existsDatabase_succeeds() throws MalformedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, - QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + public void save_existsDatabase_succeeds() throws MalformedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, + ViewNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, + ExternalServiceException { /* test */ identifierService.save(DATABASE_1, USER_1, IDENTIFIER_1_SAVE_DTO); @@ -279,8 +279,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void delete_succeeds() throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, - IdentifierNotFoundException, SearchServiceException, SearchServiceConnectionException { + public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, + SearchServiceConnectionException { /* mock */ when(searchServiceGateway.update(any(Database.class))) @@ -300,9 +301,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { @Test @Transactional - public void save_subsetRelatedIdentifiers_succeeds() throws ServiceException, ServiceConnectionException, + public void save_subsetRelatedIdentifiers_succeeds() throws DataServiceException, DataServiceConnectionException, MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, - QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { /* mock */ when(dataServiceGateway.findQuery(IDENTIFIER_5_DATABASE_ID, IDENTIFIER_5_QUERY_ID)) @@ -339,9 +340,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void save_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, QueryNotFoundException, - SearchServiceException, SearchServiceConnectionException { + SearchServiceException, SearchServiceConnectionException, ExternalServiceException { /* test */ final Identifier response = identifierService.save(DATABASE_1, USER_1, IDENTIFIER_1_SAVE_DTO); @@ -384,9 +385,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_repeatedRemoveChildren_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, - DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, QueryNotFoundException, - SearchServiceException, SearchServiceConnectionException { + public void save_repeatedRemoveChildren_succeeds() throws MalformedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, + ViewNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, + ExternalServiceException { /* test */ final Identifier response = identifierService.save(DATABASE_1, USER_1, IDENTIFIER_1_SAVE_MODIFY_DTO); @@ -413,9 +415,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_noRelatedTitleDescription_succeeds() throws ServiceException, ServiceConnectionException, + public void save_noRelatedTitleDescription_succeeds() throws DataServiceException, DataServiceConnectionException, MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, ViewNotFoundException, - QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException { /* test */ final Identifier response = identifierService.save(DATABASE_4, USER_4, IDENTIFIER_7_SAVE_DTO); @@ -430,9 +432,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_subsetHasDatabaseIdentifier_succeeds() throws ServiceException, ServiceConnectionException, + public void save_subsetHasDatabaseIdentifier_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, ViewNotFoundException, - SearchServiceConnectionException, MalformedException, IdentifierNotFoundException { + SearchServiceConnectionException, MalformedException, IdentifierNotFoundException, + ExternalServiceException { /* mock */ when(dataServiceGateway.findQuery(IDENTIFIER_2_DATABASE_ID, IDENTIFIER_2_QUERY_ID)) @@ -449,9 +452,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void save_viewIdentifier_succeeds() throws SearchServiceException, MalformedException, ServiceException, - QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { + public void save_viewIdentifier_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + ExternalServiceException { /* test */ final Identifier response = identifierService.save(DATABASE_1, USER_1, IDENTIFIER_3_SAVE_DTO); @@ -465,9 +469,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void create_succeeds() throws MalformedException, ServiceConnectionException, SearchServiceException, - ServiceException, QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, - IdentifierNotFoundException, ViewNotFoundException { + public void create_succeeds() throws MalformedException, DataServiceConnectionException, SearchServiceException, + DataServiceException, QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, + IdentifierNotFoundException, ViewNotFoundException, ExternalServiceException { /* test */ final Identifier response = identifierService.create(DATABASE_1, USER_1, IDENTIFIER_1_CREATE_DTO); @@ -475,9 +479,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, ServiceException, - QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { + public void create_hasDoi_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, + ExternalServiceException { /* test */ final Identifier response = identifierService.create(DATABASE_1, USER_1, IDENTIFIER_1_CREATE_WITH_DOI_DTO); @@ -486,8 +491,9 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { } @Test - public void publish_succeeds() throws MalformedException, ServiceConnectionException, SearchServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException { + public void publish_succeeds() throws MalformedException, DataServiceConnectionException, SearchServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, + ExternalServiceException { /* test */ final Identifier response = identifierService.publish(IDENTIFIER_7_ID); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aa3a460b999c4e1dbfe78d9e9b50f3d0053e1bf7 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/StorageServiceIntegrationTest.java @@ -0,0 +1,139 @@ +package at.tuwien.service; + +import at.tuwien.config.S3Config; +import at.tuwien.exception.*; +import at.tuwien.test.AbstractUnitTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.testcontainers.containers.MinIOContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; + +import java.io.File; +import java.io.InputStream; +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@Log4j2 +@Testcontainers +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@SpringBootTest +@ExtendWith(SpringExtension.class) +public class StorageServiceIntegrationTest extends AbstractUnitTest { + + @Autowired + private StorageService storageService; + + @Autowired + private S3Client s3Client; + + @Autowired + private S3Config s3Config; + + @Container + private static final MinIOContainer minIOContainer = new MinIOContainer("minio/minio:RELEASE.2024-06-06T09-36-42Z"); + + @DynamicPropertySource + static void dynamicProperties(DynamicPropertyRegistry registry) { + registry.add("dbrepo.endpoints.storageService", minIOContainer::getS3URL); + } + + @BeforeEach + public void beforeEach() throws SQLException { + genesis(); + /* s3 */ + if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3ImportBucket()))) { + s3Client.createBucket(CreateBucketRequest.builder() + .bucket(s3Config.getS3ImportBucket()) + .build()); + } + if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3ExportBucket()))) { + s3Client.createBucket(CreateBucketRequest.builder() + .bucket(s3Config.getS3ExportBucket()) + .build()); + } + } + + @Test + public void getObject_succeeds() throws StorageUnavailableException, StorageNotFoundException { + final String key = "s3key"; + + /* mock */ + log.trace("mock object with key {} to bucket {}", key, s3Config.getS3ImportBucket()); + s3Client.putObject(PutObjectRequest.builder() + .key(key) + .bucket(s3Config.getS3ImportBucket()) + .build(), RequestBody.fromFile(new File("src/test/resources/csv/keyboard.csv"))); + + /* test */ + final InputStream response = storageService.getObject(s3Config.getS3ImportBucket(), key); + assertNotNull(response); + } + + @Test + public void getObject_notFound_fails() { + + /* test */ + assertThrows(StorageNotFoundException.class, () -> { + storageService.getObject(s3Config.getS3ImportBucket(), "i_do_not_exist"); + }); + } + + @Test + public void getObject_bucketNotFound_fails() { + + /* test */ + assertThrows(StorageUnavailableException.class, () -> { + storageService.getObject("i_do_not_exist", "i_do_neither"); + }); + } + + @Test + public void getBytes_succeeds() throws StorageUnavailableException, StorageNotFoundException { + final String key = "s3key"; + + /* mock */ + log.trace("mock object with key {} to bucket {}", key, s3Config.getS3ImportBucket()); + s3Client.putObject(PutObjectRequest.builder() + .key(key) + .bucket(s3Config.getS3ImportBucket()) + .build(), RequestBody.fromFile(new File("src/test/resources/csv/keyboard.csv"))); + + /* test */ + final byte[] response = storageService.getBytes(key); + assertNotNull(response); + } + + @Test + public void getBytes_notExists_fails() { + + /* test */ + assertThrows(StorageNotFoundException.class, () -> { + storageService.getBytes("i_do_not_exist"); + }); + } + + @Test + public void getBytes_bucketNotExists_fails() { + + /* test */ + assertThrows(StorageUnavailableException.class, () -> { + storageService.getBytes("i_do_not_exist", "i_do_neither"); + }); + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java index f30bf485f3be9a75eaa43f28e0d57fecd7d96b2a..e66d35d8ea0d8b0f9aff850cf4baf880e4240c12 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java @@ -78,7 +78,7 @@ public class TableServicePersistenceTest extends AbstractUnitTest { @Test @Transactional - public void create_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { final TableCreateDto request = TableCreateDto.builder() .name("New Table") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index d32189f944767a41aea777728ce7d1c58cf05a10..33b4594424956b584ff2910898f18d336c1aec7b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -8,11 +8,9 @@ import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.entities.database.table.constraints.Constraints; import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnConcept; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; import at.tuwien.gateway.SearchServiceGateway; @@ -117,9 +115,9 @@ public class TableServiceUnitTest extends AbstractUnitTest { } @Test - public void createTable_succeeds() throws ServiceException, ServiceConnectionException, UserNotFoundException, - TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, - SearchServiceConnectionException, MalformedException, OntologyNotFoundException, + public void createTable_succeeds() throws DataServiceException, DataServiceConnectionException, + UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, + SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException { /* mock */ @@ -139,10 +137,10 @@ public class TableServiceUnitTest extends AbstractUnitTest { } @Test - public void createTable_nonStandardColumnNames_succeeds() throws ServiceException, ServiceConnectionException, - UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, - SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, - SemanticEntityNotFoundException { + public void createTable_nonStandardColumnNames_succeeds() throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, + TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, + OntologyNotFoundException, SemanticEntityNotFoundException { final TableCreateDto request = TableCreateDto.builder() .name("New Table") .description("A wonderful table") @@ -202,7 +200,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { } @Test - public void createTable_dateFormatNotFound_fails() throws ServiceException, ServiceConnectionException, + public void createTable_dateFormatNotFound_fails() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException { final TableCreateDto request = TableCreateDto.builder() @@ -240,7 +238,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { } @Test - public void create_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { @@ -262,31 +260,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { } @Test - @Transactional - public void update_succeeds() throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, - SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, - SemanticEntityNotFoundException { - final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() - .conceptUri(CONCEPT_1_URI) - .build(); - - /* mock */ - when(ontologyService.find(anyString())) - .thenReturn(ONTOLOGY_2); - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4, ONTOLOGY_5)); - when(searchServiceGateway.update(any(Database.class))) - .thenReturn(DATABASE_1_DTO); - - /* test */ - final TableColumn response = tableService.update(TABLE_1_COLUMNS.get(0), request); - assertNotNull(response.getConcept()); - final TableColumnConcept concept = response.getConcept(); - assertEquals(CONCEPT_1_URI, concept.getUri()); - } - - @Test - public void create_dataServiceError_fails() throws ServiceException, ServiceConnectionException, + public void create_dataServiceError_fails() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException { @@ -295,14 +269,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { .thenReturn(USER_1); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); - doThrow(ServiceException.class) + doThrow(DataServiceException.class) .when(dataServiceGateway) .createTable(DATABASE_1_ID, TABLE_5_CREATE_DTO); when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { tableService.createTable(DATABASE_1, TABLE_5_CREATE_DTO, USER_1_PRINCIPAL); }); } @@ -388,8 +362,9 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Test @Transactional - public void delete_succeeds() throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, - TableNotFoundException, SearchServiceException, SearchServiceConnectionException { + public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, TableNotFoundException, SearchServiceException, + SearchServiceConnectionException { /* mock */ doNothing() @@ -404,7 +379,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { @Test @Transactional - public void delete_hasIdentifier_succeeds() throws ServiceException, ServiceConnectionException, + public void delete_hasIdentifier_succeeds() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ 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 f85d4663700427aaca2f55bae9c88e26e441f45b..5a4690892f890097f636a868ab9d69aadb0c6ef2 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 @@ -72,7 +72,7 @@ public class UserServiceUnitTest extends AbstractUnitTest { @Test public void create_succeeds() throws UserNotFoundException, UserExistsException, EmailExistsException, - ServiceException, ServiceConnectionException, AuthServiceException, AuthServiceConnectionException, + DataServiceException, DataServiceConnectionException, AuthServiceException, AuthServiceConnectionException, CredentialsInvalidException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java index fc83d3a650b5642bbe0e8cdc252e95ef59c9dcf5..e23320017c54592662f42b24c3eb7039a3f1a540 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java @@ -79,7 +79,7 @@ public class ViewServicePersistenceTest extends AbstractUnitTest { } @Test - public void delete_succeeds() throws SearchServiceException, ServiceException, ServiceConnectionException, + public void delete_succeeds() throws SearchServiceException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceConnectionException, ViewNotFoundException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java index 517661ce1a03220bb536ef1fbacfe81e3d0f32c9..cd9fe03c655d33b014239af4f05f0f0ae9b6d1e9 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java @@ -48,7 +48,7 @@ public class ViewServiceUnitTest extends AbstractUnitTest { } @Test - public void create_succeeds() throws MalformedException, ServiceException, ServiceConnectionException, + public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { final ViewCreateDto request = ViewCreateDto.builder() .name(VIEW_1_NAME) @@ -107,8 +107,8 @@ public class ViewServiceUnitTest extends AbstractUnitTest { } @Test - public void delete_succeeds() throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, - ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { + public void delete_succeeds() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ doNothing() @@ -124,37 +124,37 @@ public class ViewServiceUnitTest extends AbstractUnitTest { } @Test - public void delete_dataServiceException_fails() throws ServiceException, ServiceConnectionException, + public void delete_dataServiceException_fails() throws DataServiceException, DataServiceConnectionException, ViewNotFoundException { /* mock */ - doThrow(ServiceException.class) + doThrow(DataServiceException.class) .when(dataServiceGateway) .deleteView(DATABASE_1_ID, VIEW_1_ID); /* test */ - assertThrows(ServiceException.class, () -> { + assertThrows(DataServiceException.class, () -> { viewService.delete(VIEW_1); }); } @Test - public void delete_dataServiceConnection_fails() throws ServiceException, ServiceConnectionException, + public void delete_dataServiceConnection_fails() throws DataServiceException, DataServiceConnectionException, ViewNotFoundException { /* mock */ - doThrow(ServiceConnectionException.class) + doThrow(DataServiceConnectionException.class) .when(dataServiceGateway) .deleteView(DATABASE_1_ID, VIEW_1_ID); /* test */ - assertThrows(ServiceConnectionException.class, () -> { + assertThrows(DataServiceConnectionException.class, () -> { viewService.delete(VIEW_1); }); } @Test - public void delete_searchServiceError_fails() throws ServiceException, ServiceConnectionException, + public void delete_searchServiceError_fails() throws DataServiceException, DataServiceConnectionException, ViewNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -174,7 +174,7 @@ public class ViewServiceUnitTest extends AbstractUnitTest { } @Test - public void delete_searchServiceConnection_fails() throws ServiceException, ServiceConnectionException, + public void delete_searchServiceConnection_fails() throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ @@ -194,7 +194,7 @@ public class ViewServiceUnitTest extends AbstractUnitTest { } @Test - public void delete_searchServiceNotFound_fails() throws ServiceException, ServiceConnectionException, + public void delete_searchServiceNotFound_fails() throws DataServiceException, DataServiceConnectionException, ViewNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java index a0588a6e1b118f206e8fb17c3507dcdb4efacaad..df86598714d65600e0dc79b5f6a3048fb3df16b5 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java @@ -1,18 +1,22 @@ package at.tuwien.utils; import at.tuwien.api.amqp.*; +import at.tuwien.test.BaseTest; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; import java.nio.charset.Charset; import java.util.Arrays; @@ -20,13 +24,17 @@ import java.util.List; import java.util.stream.Collectors; @Log4j2 -@Service -public class AmqpUtils { +public class AmqpUtils extends BaseTest { + + private static final String BASIC_AUTH = new String(Base64.encodeBase64((USER_1_USERNAME + ":" + USER_1_PASSWORD).getBytes(Charset.defaultCharset()))); private final RestTemplate restTemplate; - @Autowired - public AmqpUtils(@Qualifier("brokerRestTemplate") RestTemplate restTemplate) { + public AmqpUtils(String endpoint) { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(endpoint)); + restTemplate.getInterceptors() + .add(new BasicAuthenticationInterceptor(USER_1_USERNAME, USER_1_PASSWORD)); this.restTemplate = restTemplate; } @@ -97,10 +105,10 @@ public class AmqpUtils { public void setVirtualHostPermissions(String vhost, String username, GrantVirtualHostPermissionsDto data) { final String url = "/api/permissions/" + vhost + "/" + username; - log.debug("set virtual host permissions: {}", url); log.trace("body: {}", data); final MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); - headers.add("Authentication", "Basic " + new String(Base64.encodeBase64("guest:guest".getBytes(Charset.defaultCharset())))); + headers.add("Authentication", "Basic " + BASIC_AUTH); + log.trace("set virtual host permissions: {}", url); final ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data, headers), Void.class); if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to set virtual host permissions: {}", response.getStatusCode()); @@ -113,7 +121,7 @@ public class AmqpUtils { log.debug("set topic permissions: {}", url); log.trace("body: {}", data); final MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); - headers.add("Authentication", "Basic " + new String(Base64.encodeBase64("guest:guest".getBytes(Charset.defaultCharset())))); + headers.add("Authentication", "Basic " + BASIC_AUTH); final ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data, headers), Void.class); if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to set topic permissions: {}", response.getStatusCode()); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/H2Utils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java similarity index 97% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/H2Utils.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java index 033d1ba280c7224f447ec99ded6850dbd38a38e9..7c80d5274a386031276fdb48eab6eaa3e2989024 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/H2Utils.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/H2Utils.java @@ -1,4 +1,4 @@ -package at.tuwien.config; +package at.tuwien.utils; import jakarta.persistence.EntityManager; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..49694e6fd1dc49eb0f4bc8df35f1b6cd4965bf5e --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/utils/KeycloakUtils.java @@ -0,0 +1,40 @@ +package at.tuwien.utils; + +import at.tuwien.api.keycloak.RoleRepresentationDto; +import at.tuwien.exception.*; +import at.tuwien.gateway.KeycloakGateway; +import at.tuwien.gateway.impl.KeycloakGatewayImpl; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.UUID; + +@Log4j2 +@Component +public class KeycloakUtils { + + final static UUID realmId = UUID.fromString("82c39861-d877-4667-a0f3-4daa2ee230e0"); + + private final KeycloakGateway keycloakGateway; + + @Autowired + public KeycloakUtils(KeycloakGateway keycloakGateway) { + this.keycloakGateway = keycloakGateway; + } + + public void deleteUser(String username) throws AuthServiceException, AuthServiceConnectionException, + CredentialsInvalidException { + try { + final UUID userId = keycloakGateway.findByUsername(username).getId(); + keycloakGateway.deleteUser(userId); + } catch (UserNotFoundException e) { + /* ignore */ + } + } +} 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 1e5aa8227a077254112f2a9c4ec86d759d269bc7..f6cf4e887d4d25f2dfc201ae6d4d014f3b8c1547 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 @@ -30,8 +30,7 @@ import java.util.List; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @@ -173,7 +172,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { DatabaseNotFoundException, AccessNotFoundException { /* mock */ - when(databaseService.findById(DATABASE_3_ID)) + when(databaseService.findById(anyLong())) .thenReturn(DATABASE_3); /* test */ @@ -181,11 +180,11 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { } @Test - @Disabled("keep failing on CI but works locally") + @Disabled public void validateOnlyAccessOrPublic_privateAnonymous_fails() throws DatabaseNotFoundException { /* mock */ - when(databaseService.findById(DATABASE_1_ID)) + when(databaseService.findById(anyLong())) .thenReturn(DATABASE_1); /* test */ @@ -195,7 +194,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { } @Test - @Disabled("keep failing on CI but works locally") + @Disabled public void validateOnlyAccessOrPublic_privateNoAccess_fails() throws DatabaseNotFoundException, AccessNotFoundException { @@ -204,7 +203,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1); doThrow(AccessNotFoundException.class) .when(accessService) - .find(eq(DATABASE_1), any(User.class)); + .find(any(Database.class), any(User.class)); /* test */ assertThrows(AccessNotFoundException.class, () -> { @@ -402,11 +401,11 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { } @Test - @Disabled("keep failing on CI but works locally") + @Disabled public void validateOnlyPrivateHasRole_privatePrincipalMissing_fails() throws DatabaseNotFoundException { /* mock */ - when(databaseService.findById(DATABASE_1_ID)) + when(databaseService.findById(anyLong())) .thenReturn(DATABASE_1); /* test */ @@ -416,11 +415,11 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { } @Test - @Disabled("keep failing on CI but works locally") + @Disabled public void validateOnlyPrivateHasRole_privateRoleMissing_fails() throws DatabaseNotFoundException { /* mock */ - when(databaseService.findById(DATABASE_1_ID)) + when(databaseService.findById(anyLong())) .thenReturn(DATABASE_1); /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties index 4243bcf79e7133c183f076dd33c07269921b900b..0929175cf79929776a59fd6d27075ae6df998de6 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties @@ -14,20 +14,20 @@ spring.sql.init.mode=always spring.sql.init.schema-locations=classpath*:init/schema.sql spring.jpa.hibernate.ddl-auto=create -# LDAP -spring.ldap.userDn: cn=admin,dc=dbrepo,dc=at -spring.ldap.password: adminpassword -spring.ldap.base: dc=dbrepo,dc=at - -# admin -dbrepo.system.role: admin - # logging logging.level.root=error logging.level.at.tuwien.=trace +logging.level.org.testcontainers.=info +logging.level.tc.=info +logging.level.com.github.dockerjava.=warn +logging.level.com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.wire.=off # datacite dbrepo.datacite.url: https://api.test.datacite.org dbrepo.datacite.prefix: 10.12345 dbrepo.datacite.username: test-user dbrepo.datacite.password: test-password + +# s3 +dbrepo.s3.accessKeyId=minioadmin +dbrepo.s3.secretAccessKey=minioadmin diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json b/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json index 639d73ea15fdba309347312286e71a7f0706268e..588053e15fa6d5872c4cb83da42d71859b5f7a64 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json +++ b/dbrepo-metadata-service/rest-service/src/test/resources/init/dbrepo-realm.json @@ -1,1525 +1,2822 @@ -{ - "id": "4ef53018-8322-40ed-a44a-a7c5292a07be", - "realm": "dbrepo", - "displayName": "", - "displayNameHtml": "", - "notBefore": 0, - "defaultSignatureAlgorithm": "RS256", - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 300, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 1800, - "ssoSessionMaxLifespan": 36000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 300, - "oauth2DeviceCodeLifespan": 600, - "oauth2DevicePollingInterval": 5, - "enabled": true, - "sslRequired": "none", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "defaultRole": { - "id": "7a02acbe-09aa-4af7-8e79-fbb0cf5fd0d6", - "name": "default-roles-dbrepo", - "description": "${role_default-roles}", - "composite": true, - "clientRole": false, - "containerId": "4ef53018-8322-40ed-a44a-a7c5292a07be" - }, - "requiredCredentials": [ - "password" - ], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpPolicyCodeReusable": false, - "otpSupportedApplications": [ - "totpAppGoogleName", - "totpAppMicrosoftAuthenticatorName", - "totpAppFreeOTPName" - ], - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": [ - "offline_access" - ] - } - ], - "clientScopes": [ - { - "id": "4410371f-2840-458a-a496-375bd500f5fc", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "7001651a-7ded-4a0f-9cb7-816b058af730", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - }, - { - "id": "25e4ad82-8b9b-463d-8b35-02fae44ec64c", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "ebe0a886-5df1-48f3-9f00-a45d686b0b02", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "866be669-9799-45ad-abdd-23f5d1c82293", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "id": "be0f3000-0106-4edd-a8f5-0618e3a3f7fe", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "093f222d-cee9-495a-81b7-ddae4b730ab2", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - }, - { - "id": "2e21b9f5-c428-4a5b-9dd8-8a80bc6d9795", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "2a95813e-053d-4c20-9f2b-f7e1ad1798f5", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "9c8a5628-af2a-4ba4-9cad-a8ae58c8526a", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } - } - ] - }, - { - "id": "c6375bbe-9820-4781-8828-99020210f5bd", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "a1db2464-4e12-4696-914d-d252263e4470", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - }, - { - "id": "c5513105-d577-4ba0-bff8-f96e9272f6fd", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "66901106-8ea3-4712-8bdf-bc67da4a9d2d", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - } - ] - }, - { - "id": "f0ea8ba1-794d-4b89-9ad3-b7f390c5241e", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "b3789148-8427-4af8-bc03-4dd3fae4b312", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - }, - { - "id": "552ac5e8-6e04-47d5-8ddf-89230ca31b43", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "8ff9a2f3-582c-4cda-8ea8-d08850f8a394", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "52af8bfd-44b1-4b69-bfd5-bc92cf1629aa", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} - } - ] - }, - { - "id": "b3ebaf28-e467-4c70-b993-d7b8459dfb5a", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "1025302a-104e-42e8-acf8-83579c21bfbb", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "70a9942e-85c1-4f15-9605-6408e0087b74", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "1e36c899-c472-427e-a024-c12a64d6084c", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "b5e54114-79cb-488d-9e60-6a804ca3b22a", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "3e9406b9-a0ae-48d2-98b9-66ab7360b2a2", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "aec55dcc-59e7-4ea7-9eb5-55954d983fd0", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - }, - { - "id": "11fd80da-8760-4fa6-9d1b-32da9df170bd", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "90f93a66-27d0-4890-846b-79d99e02ad76", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "long" - } - }, - { - "id": "6c8aa1f6-3aa2-4e48-9f9c-44cffe71e7d2", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "a861da8e-87e7-4b5d-92fa-4ca61671c77f", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "ae301563-61a7-413b-87a0-036e1af942bb", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - }, - { - "id": "c39e0763-48a9-4f69-84f4-4e334365f99b", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "a54ae213-5854-4f77-8646-5cc7767fb914", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "41824638-4a2f-4259-90fe-431a32371256", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "4c7c18fe-2aff-4df3-aeff-4dca9de93a79", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } - }, - { - "id": "30b249b2-c788-47ef-a8c7-daa0e3713b7c", - "name": "acr", - "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "50cf075c-fdc9-43f4-ab85-1e32cafbbb26", - "name": "acr loa level", - "protocol": "openid-connect", - "protocolMapper": "oidc-acr-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true" - } - } - ] - } - ], - "defaultDefaultClientScopes": [ - "role_list", - "profile", - "email", - "roles", - "web-origins", - "acr" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "address", - "phone", - "microprofile-jwt" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" - }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "identityProviders": [], - "identityProviderMappers": [], - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "4489b316-ab01-42cf-a224-f853a310c7c5", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-address-mapper", - "saml-user-property-mapper", - "oidc-usermodel-property-mapper", - "oidc-usermodel-attribute-mapper", - "saml-user-attribute-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-full-name-mapper", - "saml-role-list-mapper" - ] - } - }, - { - "id": "d355f2ac-bd0d-4c5c-8e2d-52f14f332354", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-full-name-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-address-mapper", - "oidc-sha256-pairwise-sub-mapper", - "saml-role-list-mapper", - "saml-user-property-mapper", - "saml-user-attribute-mapper", - "oidc-usermodel-property-mapper" - ] - } - }, - { - "id": "cefbb851-d3bd-4b6d-b582-7fc4fa51d9b6", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "b7fe23c6-f82b-4920-8062-3d9fa6fb838f", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "8332b5b7-5643-4c9f-afdb-4bda506bac55", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "bb595923-ec43-4cbc-be3c-6d65c250956d", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "4d9901ea-7d1e-484a-a5de-abb36d8a5cc8", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] - } - }, - { - "id": "44bd2392-250b-4b4a-9772-7478fbd68f67", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": [ - "200" - ] - } - } - ], - "org.keycloak.userprofile.UserProfileProvider": [ - { - "id": "0ffb33e9-2f5b-4e54-b188-19b3da816f0f", - "providerId": "declarative-user-profile", - "subComponents": {}, - "config": {} - } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "d80cf13c-e402-49e5-b347-0175bdcac7b6", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "03442c52-879c-4b3d-89c4-db02a0ad3c52", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "30ce0596-cbce-4633-a422-15873bc363bf", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] - } - }, - { - "id": "012d037c-b22a-48f2-a80a-927424d75f00", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "RSA-OAEP" - ] - } - } - ] - }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "865c209a-a080-4162-9b49-795345294601", - "alias": "Account verification options", - "description": "Method with which to verity the existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false - } - ] - }, - { - "id": "85fc1de2-5b82-40ec-bda0-91a4fec38584", - "alias": "Authentication Options", - "description": "Authentication options.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "basic-auth", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "basic-auth-otp", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "2476a340-9459-4541-9e61-226f06ec66c4", - "alias": "Browser - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "2e424297-19dd-4c09-a06a-876ef5183ca6", - "alias": "Direct Grant - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "3966485f-3455-47d2-86a2-d990b41c7953", - "alias": "First broker login - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "29098fa4-d254-44cb-a6c5-63b36b8bfdc1", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Account verification options", - "userSetupAllowed": false - } - ] - }, - { - "id": "03569e80-3083-4147-ad49-445466c191d8", - "alias": "Reset - Conditional OTP", - "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "7e660682-5eb3-4527-a5fa-53fc14a0f2f5", - "alias": "User creation or linking", - "description": "Flow for the existing/non-existing user alternatives", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false - } - ] - }, - { - "id": "4deed0f8-02f9-4581-9a91-05bc58fbffba", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "3c101100-d2dc-4e0d-beea-7bb41ee08849", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "identity-provider-redirector", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 25, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "forms", - "userSetupAllowed": false - } - ] - }, - { - "id": "f38f76db-5399-4231-82e0-bf31cf748d14", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-secret-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-x509", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "ed29eed7-d490-4985-be20-2444da957182", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "e41f4bae-aad9-4821-8597-514e6dc5796c", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "3149ebc7-481d-43bd-9d09-9e66bd9b2b7f", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "User creation or linking", - "userSetupAllowed": false - } - ] - }, - { - "id": "7aaab1d1-5357-4e71-8553-52d5613acf7d", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "c2ffc5bb-568a-4648-bc13-8e7d6a4a53b4", - "alias": "http challenge", - "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "no-cookie-redirect", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Authentication Options", - "userSetupAllowed": false - } - ] - }, - { - "id": "c6b78806-13ee-4010-b282-a6e527dda66c", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": true, - "flowAlias": "registration form", - "userSetupAllowed": false - } - ] - }, - { - "id": "b5f00ead-4f6f-4454-a925-154c1e9c2cc5", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-profile-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-password-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 50, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-recaptcha-action", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 60, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "f8370f63-f996-4039-9fbf-86e87da675dd", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-credential-email", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 40, - "autheticatorFlow": true, - "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "7f156260-804d-4848-9ea0-347281aea644", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - } - ], - "authenticatorConfig": [ - { - "id": "17f2c0cc-8dd8-4774-adcc-cd294cdadac8", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "d5be3f6c-d096-4232-88e8-b0f46e608cff", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } - } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "TERMS_AND_CONDITIONS", - "name": "Terms and Conditions", - "providerId": "TERMS_AND_CONDITIONS", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "delete_account", - "name": "Delete Account", - "providerId": "delete_account", - "enabled": false, - "defaultAction": false, - "priority": 60, - "config": {} - }, - { - "alias": "webauthn-register", - "name": "Webauthn Register", - "providerId": "webauthn-register", - "enabled": true, - "defaultAction": false, - "priority": 70, - "config": {} - }, - { - "alias": "webauthn-register-passwordless", - "name": "Webauthn Register Passwordless", - "providerId": "webauthn-register-passwordless", - "enabled": true, - "defaultAction": false, - "priority": 80, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "attributes": { - "cibaBackchannelTokenDeliveryMode": "poll", - "cibaAuthRequestedUserHint": "login_hint", - "oauth2DevicePollingInterval": "5", - "clientOfflineSessionMaxLifespan": "0", - "clientSessionIdleTimeout": "0", - "clientOfflineSessionIdleTimeout": "0", - "cibaInterval": "5", - "realmReusableOtpCode": "false", - "cibaExpiresIn": "120", - "oauth2DeviceCodeLifespan": "600", - "parRequestUriLifespan": "60", - "clientSessionMaxLifespan": "0", - "frontendUrl": "", - "acr.loa.map": "{}" - }, - "keycloakVersion": "21.0.2", - "userManagedAccessAllowed": false, - "clientProfiles": { - "profiles": [] - }, - "clientPolicies": { - "policies": [] - } +{ + "id" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "realm" : "dbrepo", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 1, + "accessTokenLifespan" : 900, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 864000, + "ssoSessionMaxLifespan" : 2592000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 1800, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "none", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : true, + "loginWithEmailAllowed" : false, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "48f38342-1e3f-427a-995d-c436eaee65cb", + "name" : "default-user-handling", + "description" : "${default-user-handling}", + "composite" : true, + "composites" : { + "realm" : [ "modify-user-theme", "modify-user-information" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "9bb4a8dc-28e0-4645-b62f-cc94425f0cb0", + "name" : "default-maintenance-handling", + "description" : "${default-maintenance-handling}", + "composite" : true, + "composites" : { + "realm" : [ "create-maintenance-message", "find-maintenance-message", "update-maintenance-message", "delete-maintenance-message", "list-maintenance-messages" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "7ee1c424-11b0-46a9-b0ed-725e9b7fc40c", + "name" : "default-system-roles", + "description" : "${default-system-roles}", + "composite" : true, + "composites" : { + "realm" : [ "delete-database-view", "update-semantic-unit", "export-query-data", "default-data-steward-roles", "execute-query", "default-user-handling", "delete-table-data", "find-query", "list-database-views", "persist-query", "update-search-index", "delete-database-access", "view-table-history", "create-ontology", "update-ontology", "modify-user-theme", "default-system-roles", "create-semantic-concept", "default-container-handling", "create-container", "create-table", "default-broker-handling", "default-maintenance-handling", "execute-semantic-query", "uma_authorization", "table-semantic-analyse", "list-containers", "check-database-access", "escalated-query-handling", "delete-identifier", "modify-database-owner", "list-tables", "export-table-data", "create-database-access", "delete-container", "re-execute-query", "create-semantic-unit", "escalated-identifier-handling", "system", "update-table-statistic", "escalated-semantics-handling", "default-database-handling", "delete-ontology", "find-database", "find-database-view", "update-semantic-concept", "find-user", "import-database-data", "publish-identifier", "default-roles-dbrepo", "find-foreign-user", "create-database", "create-maintenance-message", "find-maintenance-message", "escalated-container-handling", "default-researcher-roles", "default-identifier-handling", "escalated-user-handling", "modify-user-information", "create-database-view", "update-maintenance-message", "delete-foreign-table", "offline_access", "modify-foreign-table-column-semantics", "delete-maintenance-message", "find-container", "insert-table-data", "modify-identifier-metadata", "modify-database-image", "escalated-broker-handling", "modify-table-column-semantics", "escalated-database-handling", "default-semantics-handling", "update-database-access", "default-query-handling", "find-table", "list-queries", "default-developer-roles", "create-identifier", "escalated-table-handling", "find-identifier", "view-database-view-data", "view-table-data", "list-licenses", "default-table-handling", "list-identifiers", "create-foreign-identifier", "list-databases", "list-ontologies", "modify-database-visibility", "list-maintenance-messages", "delete-table" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "143ba359-5fa2-451e-8296-43ecf20bb251", + "name" : "update-semantic-concept", + "description" : "${update-semantic-concept}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "5136d7a3-e3f0-4585-bacd-15cb8a56095c", + "name" : "escalated-container-handling", + "description" : "${escalated-container-handling}", + "composite" : true, + "composites" : { + "realm" : [ "create-container", "delete-container" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "b0bc8649-7d84-4dd3-84f0-7f174425babe", + "name" : "list-tables", + "description" : "${list-tables}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "bfd85d9c-2772-4660-a8f0-cdc0cd8252b3", + "name" : "default-database-handling", + "description" : "${default-database-handling}", + "composite" : true, + "composites" : { + "realm" : [ "modify-database-image", "modify-database-owner", "update-database-access", "create-database", "list-databases", "create-database-access", "find-database", "modify-database-visibility", "import-database-data", "delete-database-access", "check-database-access" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "74648f9a-777e-4ef9-b97b-4c5d749d862f", + "name" : "update-search-index", + "description" : "${update-search-index}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "22492b64-c633-48a0-9678-b28669f2885b", + "name" : "execute-semantic-query", + "description" : "${execute-semantic-query}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "4ed919fa-edc5-44e5-9411-607786e4a86d", + "name" : "view-table-history", + "description" : "${view-table-history}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d89a2881-b642-4abb-b990-196e71372f6b", + "name" : "default-table-handling", + "description" : "${default-table-handling}", + "composite" : true, + "composites" : { + "realm" : [ "modify-table-column-semantics", "list-tables", "update-table-statistic", "find-table", "create-table", "delete-table" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "b0d66d3d-59b4-4aae-aa66-e3d5a49f28e3", + "name" : "view-database-view-data", + "description" : "${view-database-view-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "f5ea431a-9b2c-4195-bcb4-9511f38e4b44", + "name" : "create-database-view", + "description" : "${create-database-view}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a5ffc20e-8b11-498c-9f3b-b5740aec24c7", + "name" : "default-semantics-handling", + "description" : "${default-semantics-handling}", + "composite" : true, + "composites" : { + "realm" : [ "create-semantic-unit", "create-semantic-concept", "execute-semantic-query", "table-semantic-analyse" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "fe4a01f3-6590-4df6-9ade-5a9c1fae4736", + "name" : "create-semantic-unit", + "description" : "${create-semantic-unit}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "0e12eedf-545d-4d32-ac4d-2821dcb118b8", + "name" : "update-table-statistic", + "description" : "${update-table-statistic}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e63e61a2-d852-4ad3-bfb5-92d9ceafef6a", + "name" : "escalated-user-handling", + "description" : "${escalated-user-handling}", + "composite" : true, + "composites" : { + "realm" : [ "find-user" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "be4e1aba-e276-4241-b6ea-01dce6c52f8b", + "name" : "find-container", + "description" : "${find-container}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "3a801b48-f3c2-4bc6-aa25-c7a91d5b32a7", + "name" : "default-researcher-roles", + "description" : "${default-researcher-roles}", + "composite" : true, + "composites" : { + "realm" : [ "default-table-handling", "default-semantics-handling", "default-container-handling", "default-query-handling", "default-user-handling", "default-database-handling", "default-broker-handling", "default-identifier-handling" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "3d8104fb-8307-40f0-b4b2-c3e518957110", + "name" : "view-table-data", + "description" : "${view-table-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "fe71b907-7020-44ab-9964-da2b87264582", + "name" : "create-database", + "description" : "${create-database}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e51b63c2-48dd-4bd6-95fb-d257d21b26ba", + "name" : "import-database-data", + "description" : "${import-database-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "1f0a9b13-c2b8-474c-bc08-59dbd71835a6", + "name" : "modify-database-image", + "description" : "${modify-database-image}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a7ad038c-5c06-42fc-951c-15ac09d4df66", + "name" : "modify-database-owner", + "description" : "${modify-database-owner}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "c12c1f4e-186f-4153-a795-26e79fb623d6", + "name" : "create-ontology", + "description" : "${create-ontology}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "b60a5694-4099-4f7d-a7e9-4c433e0eb9c9", + "name" : "update-semantic-unit", + "description" : "${update-semantic-unit}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e9854bbb-4580-4757-b1ae-305934173249", + "name" : "create-database-access", + "description" : "${create-database-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "50c604c1-7c6e-43f3-9c43-2398f5eff66e", + "name" : "list-databases", + "description" : "${list-databases}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "535f1484-4514-4d24-8d97-e3f6c11a426b", + "name" : "create-container", + "description" : "${create-container}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "f4116230-8642-4bb7-bbc8-db9c5c07b558", + "name" : "create-maintenance-message", + "description" : "${create-maintenance-message}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "973f0999-cc70-4b28-9f43-979c470bea8e", + "name" : "default-data-steward-roles", + "description" : "${default-data-steward-roles}", + "composite" : true, + "composites" : { + "realm" : [ "escalated-identifier-handling", "default-semantics-handling", "escalated-semantics-handling", "default-user-handling" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e1383fb7-d54c-4732-9146-93030eb2ca50", + "name" : "escalated-query-handling", + "description" : "${escalated-query-handling}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "993b5c69-9eb2-42af-ac28-b4a46c6b61f2", + "name" : "find-user", + "description" : "${find-user}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e4cfdc4d-2373-477b-a8df-161db99aba00", + "name" : "create-foreign-identifier", + "description" : "${create-foreign-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "6a5872a5-2b51-415d-ae2d-25a6db4a35df", + "name" : "escalated-semantics-handling", + "description" : "${escalated-semantics-handling}", + "composite" : true, + "composites" : { + "realm" : [ "update-semantic-unit", "create-ontology", "update-ontology", "list-ontologies", "delete-ontology", "modify-foreign-table-column-semantics", "update-semantic-concept" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "09147c48-273b-450b-8b11-7ef9b9245244", + "name" : "export-table-data", + "description" : "${export-table-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d14af590-60a8-4d75-b864-40ee0165bd7f", + "name" : "delete-database-access", + "description" : "${delete-database-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "be051d45-cd74-4b13-8a45-f2d3351bd995", + "name" : "table-semantic-analyse", + "description" : "${table-semantic-analyse}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "272a79a7-e282-4261-8f7d-5d5d1364243a", + "name" : "update-maintenance-message", + "description" : "${update-maintenance-message}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "64c16bfb-2015-48ad-a23f-637ff24419cb", + "name" : "default-query-handling", + "description" : "${default-query-handling}", + "composite" : true, + "composites" : { + "realm" : [ "delete-database-view", "export-query-data", "execute-query", "delete-table-data", "export-table-data", "list-queries", "find-query", "list-database-views", "persist-query", "view-database-view-data", "view-table-data", "re-execute-query", "view-table-history", "create-database-view", "find-database-view", "insert-table-data" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "c047d521-cec3-4444-86c4-aef098489b7b", + "name" : "delete-maintenance-message", + "description" : "${delete-maintenance-message}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "88f82262-be80-4d18-9fb4-5529da031f33", + "name" : "system", + "description" : "${system}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e14ab76b-1c24-484d-ae2d-478b8457edea", + "name" : "list-licenses", + "description" : "${list-licenses}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d4f29937-3ca0-41e9-9786-2b7b921b6cdd", + "name" : "modify-foreign-table-column-semantics", + "description" : "${modify-foreign-table-column-semantics}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "8eda9f5c-938c-4915-bed5-6a81a1de15a8", + "name" : "list-database-views", + "description" : "${list-database-views}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "b372f8f7-d203-4293-b991-ad93fb505917", + "name" : "escalated-database-handling", + "description" : "${escalated-database-handling}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "abd2d9ee-ebc4-4d0a-839e-6b588a6d442a", + "name" : "default-roles-dbrepo", + "description" : "${role_default-roles}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "3293799a-82b9-4f47-8f25-1aad2e0222fd", + "name" : "find-identifier", + "description" : "${find-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "aaa3f804-38a0-4474-b8e9-f1020c4b3f62", + "name" : "list-queries", + "description" : "${list-queries}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "76e38f7b-99bf-4d12-8d74-1c7d8812f443", + "name" : "update-ontology", + "description" : "${update-ontology}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "11f7973e-d1eb-42cb-a35d-c59dfc122775", + "name" : "modify-user-theme", + "description" : "${modify-user-theme}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "f392bfcb-0be5-4fad-9ce4-8ac6396f176d", + "name" : "export-query-data", + "description" : "${export-query-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "da493b7e-fb9b-43ca-82a5-e274ad2e6b39", + "name" : "find-query", + "description" : "${find-query}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a4d4a788-ebcf-4d32-baed-4a85616ca037", + "name" : "escalated-identifier-handling", + "description" : "${escalated-identifier-handling}", + "composite" : true, + "composites" : { + "realm" : [ "create-foreign-identifier", "modify-identifier-metadata" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "ea38d69d-17b8-4c65-95e8-1c3501b83618", + "name" : "default-container-handling", + "description" : "${default-container-handling}", + "composite" : true, + "composites" : { + "realm" : [ "find-container", "list-containers" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "8b8813e0-af07-4d04-a8c1-e3f37192bace", + "name" : "publish-identifier", + "description" : "${publish-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "47f5eee7-9821-4bf8-b434-0da1f81c3e5a", + "name" : "default-broker-handling", + "description" : "${default-broker-handling}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "71874bde-64a5-4a69-8685-d8998303a80c", + "name" : "delete-table-data", + "description" : "${delete-table-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "7c0306fc-3b03-4c64-87d1-9a34f2073977", + "name" : "modify-table-column-semantics", + "description" : "${modify-table-column-semantics}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "cd0ee04c-4a5e-4035-a11b-f6a1165f7829", + "name" : "delete-container", + "description" : "${delete-container}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "67ee39c0-d601-4a67-a0fe-c4f0021d557e", + "name" : "list-containers", + "description" : "${list-containers}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "795c7bb8-3502-414a-a97b-2ba1cfd6a79c", + "name" : "persist-query", + "description" : "${persist-query}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d05e7698-ddf5-4f20-9027-771afb2cc3c7", + "name" : "list-identifiers", + "description" : "${list-identifiers}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e4bfaf36-9a5d-43e0-9fa3-0f4ea7bad8d0", + "name" : "default-developer-roles", + "description" : "${default-developer-roles}", + "composite" : true, + "composites" : { + "realm" : [ "escalated-query-handling", "escalated-broker-handling", "default-table-handling", "escalated-database-handling", "default-container-handling", "default-query-handling", "default-user-handling", "default-database-handling", "default-maintenance-handling", "escalated-container-handling", "escalated-table-handling", "default-identifier-handling" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "e2cb054e-ea41-4ab0-881b-e6f576f7424e", + "name" : "create-semantic-concept", + "description" : "${create-semantic-concept}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "feb612cc-96a6-4ed2-aaa5-01f39b25beb5", + "name" : "insert-table-data", + "description" : "${insert-table-data}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a0942e33-441b-4343-9f02-4353d03f7bbb", + "name" : "find-database", + "description" : "${find-database}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "6a0bb740-4448-49be-aee8-6dd183325be5", + "name" : "delete-foreign-table", + "description" : "${delete-foreign-table}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "7f3652c7-3073-4566-ab63-25385495ebc3", + "name" : "modify-database-visibility", + "description" : "${modify-database-visibility}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "4a5df51d-f14d-41a2-ad70-6521df5a5b4f", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "fd41c4c3-d2f8-4f49-84c7-dba84e9a5575", + "name" : "execute-query", + "description" : "${execute-query}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "2963c2bb-b129-4224-b98f-c8eeab8e72d1", + "name" : "create-table", + "description" : "${create-table}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "0c487c93-448f-4a82-8b9f-ebd8a0904bf8", + "name" : "find-foreign-user", + "description" : "${find-foreign-user}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "cf9735a9-fb70-4cc5-b5f4-75afc4e5654b", + "name" : "modify-identifier-metadata", + "description" : "${modify-identifier-metadata}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "64c2b8f2-1527-4928-81ea-b2651512d028", + "name" : "delete-ontology", + "description" : "${delete-ontology}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d6e38368-b40f-423b-82e4-e8aa595237c9", + "name" : "find-maintenance-message", + "description" : "${find-maintenance-message}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "fd1cc463-3e67-49d9-81b8-2cd90c1daa9c", + "name" : "check-database-access", + "description" : "${check-database-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "74013867-e426-46cc-ab98-2f4a9225ad1e", + "name" : "find-table", + "description" : "${find-table}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a2cc60df-d280-46c5-a539-92e2aa249b4a", + "name" : "modify-user-information", + "description" : "${modify-user-information}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "c367241f-b5b5-491f-84d5-07fe1bef3877", + "name" : "default-identifier-handling", + "description" : "${default-identifier-handling}", + "composite" : true, + "composites" : { + "realm" : [ "delete-identifier", "list-identifiers", "create-identifier", "find-identifier", "publish-identifier" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "ba1ad8f2-39aa-487d-987f-645e8a459559", + "name" : "delete-table", + "description" : "${delete-table}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "09f7bdb0-296f-46c8-a3a3-8f9254fb17e4", + "name" : "list-maintenance-messages", + "description" : "${list-maintenance-messages}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "fe3bc45c-61c2-4ece-bcaf-d410dc7de501", + "name" : "update-database-access", + "description" : "${update-database-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "f43e86ed-76de-4ca8-9b5e-c292c9359bfe", + "name" : "escalated-broker-handling", + "description" : "${escalated-broker-handling}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "916b1e65-f60c-42cd-96e4-5c98ffc1ba3c", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "d1afa3ed-bf4f-469a-a061-ad7325fb8d9e", + "name" : "delete-database-view", + "description" : "${delete-database-view}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "6f044bad-6651-4408-bffa-20c2d8f92eee", + "name" : "create-identifier", + "description" : "${create-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "be91195a-e30a-4d15-a8da-0aca0a68782f", + "name" : "escalated-table-handling", + "description" : "${escalated-table-handling}", + "composite" : true, + "composites" : { + "realm" : [ "delete-foreign-table" ] + }, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "98bee7d6-d78c-4e7f-b6a3-3705968b248c", + "name" : "list-ontologies", + "description" : "${list-ontologies}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "15720c6b-027d-4d53-a0ff-0124bfab7c4c", + "name" : "re-execute-query", + "description" : "${re-execute-query}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "a9b5181a-8135-41d3-9862-ef80af42211d", + "name" : "delete-identifier", + "description" : "${delete-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + }, { + "id" : "469c2e63-cda6-48d4-ab8f-eb59a2c69798", + "name" : "find-database-view", + "description" : "${find-database-view}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "4628f654-f8f3-483b-8f92-2a7fc5930b14", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "95c2cc47-12f5-4d73-8b74-67e270c45ade", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "824791f3-c345-42f8-b103-b7e6d7e40114", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "1f840202-b7e2-4195-bac9-64e64dad2037", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "3c32c096-bb13-44c9-a080-d756a48a9ea3", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "e4b85a68-7f31-4fcf-89a2-f10d7df358e9", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "7d317752-ae56-46f2-a2ce-67c64d1b35f6", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "28824208-976e-4622-b4d7-3d18efbb46fa", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-realms", "view-identity-providers", "manage-identity-providers", "manage-authorization", "query-clients", "view-authorization", "view-users", "manage-users", "view-realm", "query-users", "view-clients", "query-groups", "create-client", "manage-clients", "manage-events", "impersonation", "view-events", "manage-realm" ] + } + }, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "57e846a2-930d-4621-819d-c35086507146", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "7fad9cde-bf96-475a-9174-14a87da51f95", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "bbcac294-d78a-4ea1-a4bf-0384266d2fe1", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "480e1437-ab9e-47de-b47a-edc6b6e285de", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "b9a9a8f5-f91e-4e73-9e88-1cdf42bd49f9", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "4d1397fb-247c-436f-b26f-124cd89afb08", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "e31f522b-b283-4ae1-b875-52afcd98b1d2", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "51822d02-fa28-4a49-89da-bc534719d8a8", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "b2743ce5-0ce8-4157-ae00-f693560f0b39", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "7ea3d7e0-9bf4-438a-b773-243daf622aaa", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + }, { + "id" : "fb73f6f5-0ed5-41d0-852c-0eb3b195b15a", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "dbrepo-client" : [ ], + "admin-cli" : [ ], + "rabbitmq-client" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "de0cfd5e-c2fe-4082-ac39-e3b092139a0f", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "88694c91-753d-4c44-9740-ec9ac06bba45", + "attributes" : { } + } ], + "account" : [ { + "id" : "acd78c04-eefc-4344-a5b4-3fc83d848936", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "939be844-8c49-45b3-9ca1-4b10a454b346", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "e52fdf00-3e73-4c17-bc1c-643493710a6b", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "b02a822e-a708-420a-bddc-1a315033fd7c", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "c590e5f5-2cbf-4151-b1dc-96c454f1f654", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "15974151-6c13-426b-8cc3-7683dd1311e1", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "c12d8d94-c2df-498e-bbe4-2f934a83ae92", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + }, { + "id" : "55f85811-bded-4d6b-8f7b-45844b963875", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "attributes" : { } + } ] + } + }, + "groups" : [ { + "id" : "f2ce17fe-7b15-47a4-bbf8-86f415298fa9", + "name" : "data-stewards", + "path" : "/data-stewards", + "attributes" : { }, + "realmRoles" : [ "default-data-steward-roles" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, { + "id" : "124d9888-0b6e-46aa-8225-077dcedaf16e", + "name" : "developers", + "path" : "/developers", + "attributes" : { }, + "realmRoles" : [ "default-developer-roles" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, { + "id" : "f467c38e-9041-4faa-ae0b-39cec65ff4db", + "name" : "researchers", + "path" : "/researchers", + "attributes" : { }, + "realmRoles" : [ "default-researcher-roles" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, { + "id" : "2b9f94b4-d434-4a98-8eab-25678cfee983", + "name" : "system", + "path" : "/system", + "attributes" : { }, + "realmRoles" : [ "default-system-roles" ], + "clientRoles" : { }, + "subGroups" : [ ] + } ], + "defaultRole" : { + "id" : "abd2d9ee-ebc4-4d0a-839e-6b588a6d442a", + "name" : "default-roles-dbrepo", + "description" : "${role_default-roles}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0" + }, + "defaultGroups" : [ "/researchers" ], + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName" ], + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "scopeMappings" : [ { + "clientScope" : "rabbitmq.tag:administrator", + "roles" : [ "escalated-broker-handling" ] + }, { + "clientScope" : "rabbitmq.tag:management", + "roles" : [ "default-broker-handling" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "e767a4a6-79e9-4e08-82b7-1076e1a09142", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/dbrepo/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/dbrepo/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "d3c4a04e-39ce-4549-a34a-11e25774cd96", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/dbrepo/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/dbrepo/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "22d90d9c-9881-474c-8dfd-a62c808a9f1c", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "81ef0f59-a5ca-4be4-a1d1-0c32edf1cfd6", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "88694c91-753d-4c44-9740-ec9ac06bba45", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "6b7ef364-4132-4831-b4e2-b6e9e9dc63ee", + "clientId" : "dbrepo-client", + "name" : "${dbrepo-client}", + "description" : "", + "rootUrl" : "", + "adminUrl" : "", + "baseUrl" : "", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG", + "redirectUris" : [ "*" ], + "webOrigins" : [ "*" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : true, + "protocol" : "openid-connect", + "attributes" : { + "oidc.ciba.grant.enabled" : "false", + "client.secret.creation.time" : "1680085365", + "backchannel.logout.session.required" : "true", + "post.logout.redirect.uris" : "*", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "da0b27c1-ae2e-4baa-bf78-db233e15c78d", + "name" : "preferred_username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "userinfo.token.claim" : "true" + } + }, { + "id" : "7c94de93-f60f-487b-b4b7-1891c67f74cc", + "name" : "aud", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-hardcoded-claim-mapper", + "consentRequired" : false, + "config" : { + "claim.value" : "dbrepo", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "aud", + "access.tokenResponse.claim" : "false" + } + }, { + "id" : "030a1cd9-53d1-4a62-a375-94d50a2dc6fc", + "name" : "uid", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "aggregate.attrs" : "false", + "multivalued" : "false", + "userinfo.token.claim" : "true", + "user.attribute" : "LDAP_ID", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "uid" + } + } ], + "defaultClientScopes" : [ "roles", "attributes" ], + "optionalClientScopes" : [ "rabbitmq.read:*/*", "web-origins", "acr", "rabbitmq.write:*/*", "address", "phone", "offline_access", "profile", "microprofile-jwt", "email", "rabbitmq.configure:*/*" ] + }, { + "id" : "25741f6b-4867-4138-8238-6345c6ba8702", + "clientId" : "rabbitmq-client", + "name" : "${rabbitmq-client}", + "description" : "", + "rootUrl" : "", + "adminUrl" : "", + "baseUrl" : "", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "JEC2FexxrX4N65fLeDGukAl6R3Lc9y0u", + "redirectUris" : [ "*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : true, + "protocol" : "openid-connect", + "attributes" : { + "oidc.ciba.grant.enabled" : "false", + "client.secret.creation.time" : "1680000860", + "backchannel.logout.session.required" : "true", + "post.logout.redirect.uris" : "*", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "01a937ed-f0e8-4137-80f3-3be3c447f7fb", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "false", + "user.attribute" : "username", + "id.token.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "client_id", + "jsonType.label" : "String" + } + }, { + "id" : "f1afc22d-f595-403b-ba2e-6ab19d98205e", + "name" : "Audience", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-hardcoded-claim-mapper", + "consentRequired" : false, + "config" : { + "claim.value" : "rabbitmq", + "userinfo.token.claim" : "false", + "id.token.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "aud", + "access.tokenResponse.claim" : "false" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "rabbitmq.tag:management" ], + "optionalClientScopes" : [ "rabbitmq.read:*/*", "rabbitmq.write:*/*", "address", "phone", "offline_access", "profile", "roles", "microprofile-jwt", "email", "rabbitmq.configure:*/*" ] + }, { + "id" : "cfffd5d0-aa19-4057-8ca0-f2c51ca0e930", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "f205c451-9524-4380-acc3-947f7ecb6b7c", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/dbrepo/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/dbrepo/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "c4d54410-3f22-4259-9571-94da2c43b752", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "69f4ecf0-4165-49ab-bf0d-38409b15b706", + "name" : "rabbitmq.tag:administrator", + "description" : "administrator", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "gui.order" : "", + "consent.screen.text" : "" + } + }, { + "id" : "7f6e9b44-e2eb-417d-b0fe-db820c9a6564", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "782819fe-ba5d-4ddb-9f95-cabb69d79c8d", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "ca613fc8-bbf2-4240-8b33-a1874f1559f3", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "b9da268f-6745-49dc-a764-3c54e385accc", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "84f0487a-1d7d-470c-9b8e-5835294ae235", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "bbdcdb36-3ec0-443d-b1af-9993d40f0567", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "9faa870b-5491-4ce9-b27d-c9ce07d6a95e", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "f0e3c012-9523-4076-83ae-e466e2d08220", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "f757d8ec-e181-429c-9287-9ad0600b061f", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "18cfbf4b-0a8e-45c7-a832-c0f72c92f3f3", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "841ea785-26ab-429a-a420-09ce3948924d", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "bfba13ff-f952-4e89-bbb1-a693fdebfae8", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "475f071d-5149-4379-b928-76482f5f519c", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "b8bebfed-b5e9-4604-a0ee-9817f7d439ac", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "445232c8-6830-476c-a6f1-8bbef167595a", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "65f2e474-6ede-4872-86e4-e49504dd0f2a", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "16cd5a27-ccf3-453c-ae1e-8621813ab73c", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "f9efedfc-3388-457c-b10a-1dff4525ff9b", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "627fa054-08eb-4206-af71-9e838e984b8b", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "e6cc53e5-5d7e-468e-88c8-0737dd3dc759", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "multivalued" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "83b4444c-10fc-44e8-a0c0-0c1da1f9bba3", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "4122ff9e-ad3c-4142-afc6-9aefdecfc86d", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "bb0747fa-c008-4af3-93be-e7739650ebd5", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "2e76447d-fbe7-4fa7-a16c-54a381b960ae", + "name" : "rabbitmq.configure:*/*", + "description" : "", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false", + "gui.order" : "", + "consent.screen.text" : "" + } + }, { + "id" : "52aad832-c6c4-49df-8a04-6ad4a406fdfa", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "dae802fb-9138-408a-b80e-a40eb0f56814", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "feb06a8d-b0eb-4911-8464-368d93f566fa", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "f64d64e8-57ce-4eb2-b99e-9f02fdbd99f9", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "c6411e3b-6478-453d-b530-5fe175a4d786", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { } + } ] + }, { + "id" : "55341d34-0086-4173-ae61-d9b175b179d8", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "58ea3217-0fff-4207-9d08-919f5493b629", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "a02c2c38-923c-46ec-9899-321412b388e5", + "name" : "attributes", + "description" : "User Attributes", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "gui.order" : "", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "78c461c1-f3f9-4d10-8835-097f13bdcd60", + "name" : "Theme", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "aggregate.attrs" : "false", + "multivalued" : "false", + "userinfo.token.claim" : "true", + "user.attribute" : "theme_dark", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "attributes.theme_dark" + } + } ] + }, { + "id" : "06062e22-89c0-4e1d-a25b-2483903b02d5", + "name" : "rabbitmq.write:*/*", + "description" : "", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false", + "gui.order" : "", + "consent.screen.text" : "" + } + }, { + "id" : "db63e03b-7918-492f-997b-f2dda98f3b39", + "name" : "rabbitmq.tag:management", + "description" : "management", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "gui.order" : "", + "consent.screen.text" : "" + } + }, { + "id" : "210cc792-6c07-45a6-a77e-827cdf3b41ba", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "425abf4a-2ee2-431d-aa92-e373a36fe556", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "8d4ffe4d-1d01-4ca1-8ff4-44eacca61b30", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "c96f0b73-ea79-4b46-93ef-d1092297f855", + "name" : "rabbitmq.read:*/*", + "description" : "", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false", + "gui.order" : "", + "consent.screen.text" : "" + } + }, { + "id" : "37f61543-dad7-4a82-8e10-77acdd1eefdc", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "3b6b6914-8ad1-4a71-88ec-444f754aaacb", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + }, { + "id" : "2defedf5-9af3-4531-822c-a879dedcd29d", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "a7bd6723-e58e-47f7-95c0-2925ce99283d", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "rabbitmq.tag:administrator", "rabbitmq.tag:management" ], + "defaultOptionalClientScopes" : [ "rabbitmq.write:*/*", "offline_access", "rabbitmq.configure:*/*", "roles", "role_list", "address", "phone", "acr", "microprofile-jwt", "email", "attributes", "profile", "rabbitmq.read:*/*", "web-origins" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_CONSENT_ERROR", "GRANT_CONSENT", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REVOKE_GRANT", "UPDATE_TOTP", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "RESTART_AUTHENTICATION", "IMPERSONATE", "UPDATE_PROFILE_ERROR", "LOGIN", "OAUTH2_DEVICE_VERIFY_USER_CODE", "UPDATE_PASSWORD_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "TOKEN_EXCHANGE", "AUTHREQID_TO_TOKEN", "LOGOUT", "REGISTER", "DELETE_ACCOUNT_ERROR", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "DELETE_ACCOUNT", "UPDATE_PASSWORD", "CLIENT_DELETE", "FEDERATED_IDENTITY_LINK_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "CLIENT_DELETE_ERROR", "VERIFY_EMAIL", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "EXECUTE_ACTIONS", "REMOVE_FEDERATED_IDENTITY_ERROR", "TOKEN_EXCHANGE_ERROR", "PERMISSION_TOKEN", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "SEND_VERIFY_EMAIL", "OAUTH2_DEVICE_AUTH", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "OAUTH2_DEVICE_CODE_TO_TOKEN", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "EXECUTE_ACTION_TOKEN", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "AUTHREQID_TO_TOKEN_ERROR", "UPDATE_PROFILE", "CLIENT_REGISTER_ERROR", "FEDERATED_IDENTITY_LINK", "SEND_IDENTITY_PROVIDER_LINK", "SEND_VERIFY_EMAIL_ERROR", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "OAUTH2_DEVICE_AUTH_ERROR", "UPDATE_CONSENT", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "CUSTOM_REQUIRED_ACTION_ERROR", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "VERIFY_PROFILE", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "4d3f9f14-f5d2-4b0c-8ea7-e6d078aa2191", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "f35bce67-1e75-408b-b065-52183368d4fd", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "f565cb47-3bcf-4078-8f94-eb4179c375b8", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "0efa669d-1017-4b4a-82e1-c2eaf72de2c9", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "528fb423-d66e-472e-9120-1f03ba9e0f18", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "104ec5a9-025b-4c44-8ac0-82d22887ca3e", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-address-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper" ] + } + }, { + "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "28ca0b6d-b2e2-4785-b04b-2391e6344e30", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "6dc4834f-a1de-4cfe-a29d-e84ac8e9b1a8" ], + "secret" : [ "HpuzG_jWYKwypLeoPEMC4A" ], + "priority" : [ "100" ] + } + }, { + "id" : "bd7945cf-6d35-4e03-9c3a-197f2dc76973", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "c8500166-5cc4-4085-ad0f-853c3b0b0233" ], + "secret" : [ "TI3xg__G2Qy8C47DracpYir2X4ItQZSrhgr5KSlwRNISDbBqZ-ky3OcAyokSXMcpweSOaCPvbivpvzJNklUBvw" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + }, { + "id" : "2f53ccf3-37b0-4d34-83e7-ed497499ee51", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEA3b1tNLfcjFLUw9UShVDNf+ZD8sQqb4YBaIXcSJTX/zDQUPiCp176BBGI3s4VplDArnOW+LumozmKogeoHEnGEIDW8ovgK5uMU9tSA2p0qqGBUMOdR8YATTIfCJe7qGiiuGa3WZy3sQLM70SuRzx02YU8gvUcvl2Js4KyqAziOUX/w3Wa59H9jjGNUXYyqaPWJp73eHzbVYWySzyLG22mVlcUtBx5siL5T2/Xu0p9z4l7/bapwwmOVi1ZrcHjbEAwdGEiSMGI/uWqAF+r1BRpmJLR7HNXcL3eK4/56VYLaiwSejfyYeRFMITEn/UxGYhcXZ5xMUUCG0TxjBhLYpTBuwIDAQABAoIBAA4dwebcxkrH99Poa8+WkiE7JgaS9sahx9OBI2xwJANoIU2TpzGuNLQZ76uLgB+rPWZTD9Xm5a1iJjwOyQ9/937TzPCk91D0tpgcusRikb8jx/6TGB9acL4kBjYUVCCHr3BA2G75MKKGtJ2OMvAbCQSosZj+r2VDwYFEPUkV2jheE5JHSBkwyIRrus3JCwu8gu5fyCg9z8ljcxJxI5HIsi4v8Z21aCw/cLj7h5cMt44wCjQz4rOfYNBEFeHDtlfR1QtWKgjm4ZHHJbKrzf9b2kQXclziceEbSM0tYbROEXKi+s0Zc+z3HEG89vv0vfN400clmzzIAijKY6gg3pPRWdECgYEA+lnWYbSlXDMNYx6RBXm1RnlMUYIm4oy4/9ljgnoGJ6WCn3SjFkgaDtiKfGIG1BSB85r04pAPANgcWHf5tWDnq0ARvBVG0BX2bKd++7B3D4d3CRYKCwm88SslJXv9dfHVhq4+zViFPiUWwT20A72jCuUCvL88y5fh/YBecfdh+jECgYEA4r5RD0NB9dMaeg5/jk/GEHIo4Z9KLc6FrSoOFo2xFkPOy1sgDpDOiNtypuWvniO7k7Ose3DS3hlfTMsKzIW/CgQJ20+Y4cvBWDaOsRxfjj7w3d+jH5OSJdKKSzTrgLKc9ZhlRzVXy0J0hipIA6HG5kdVdLXmh85ITmf1CbJhE6sCgYBjPVeBNbXTHZ2x6/z62aslO5IoQVqetb/kE82hfDOSZcao5Ph9Lam+ttH2ynkAevykj4mBgi+gWwqpey2uW7KaLPSaxShj9kDQA3mP1fzsV/u0y1rB02Nlin/YIxVvOqU1FT9p8SwoXVVu1sHUNck62VtDbN9xqUx5S/ikXrclEQKBgQCoTssOwEcK+Vty9KYcdfy4onTUHZBLdjxl8Iyqkxy7QTQUYRznkvesQPDXEDGO+kk3dyx2KKZt9Hl4IFNww2quPZcvcuMx4DQxjbXXpA8OIIxcta95NepLJwA+mRai3nKCH1A2TlNP7pFeMa5o+8IPly3Ix2lKr4Wepa4PN5i1pwKBgCZ1QP6XAOERl9NznNmU0rXVcvYNP4PIIfQWfvGsldZ4QKkmjjAGiS0/oYqdWs+UDRZyCRChaVjDXO9fk0PEG5OGKAj9nyiYCT/M8xtJ3UeP5ffZZvJ/vnye3QdDIo1e38ZzsWwJHmLYw7fRqY9W5Vxo0Vsy22U3CJY70KTxVdTy" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICmzCCAYMCBgGG3GWycDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZkYnJlcG8wHhcNMjMwMzEzMTkxMzE3WhcNMzMwMzEzMTkxNDU3WjARMQ8wDQYDVQQDDAZkYnJlcG8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdvW00t9yMUtTD1RKFUM1/5kPyxCpvhgFohdxIlNf/MNBQ+IKnXvoEEYjezhWmUMCuc5b4u6ajOYqiB6gcScYQgNbyi+Arm4xT21IDanSqoYFQw51HxgBNMh8Il7uoaKK4ZrdZnLexAszvRK5HPHTZhTyC9Ry+XYmzgrKoDOI5Rf/DdZrn0f2OMY1RdjKpo9Ymnvd4fNtVhbJLPIsbbaZWVxS0HHmyIvlPb9e7Sn3PiXv9tqnDCY5WLVmtweNsQDB0YSJIwYj+5aoAX6vUFGmYktHsc1dwvd4rj/npVgtqLBJ6N/Jh5EUwhMSf9TEZiFxdnnExRQIbRPGMGEtilMG7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAK3kQ1VkQrzvSWvmXmazmNoA1ZiPzRDs1XhGUWxgsxzgPylr3dGBuqQbKvgnLUBQLSqlJHpI4fZflHswu1qrvVZYtekPcGef4WhcKAu2i1RwxrKa6RJQ1tRbrLuVYCzPv5p/DWgltWVn88aoLnqQn0SK/0PB/o4a4Cm7Kq2ZzCr1dACBr06LvOHsc7249OySmbG4HH+pLK6jVURhZ9VaObqAHe2FJBVVoIzURbdiRRURqumrIvbnpeaU1aFyg6ED5wTnXvmMPmVPt9F79mcB33bASO5wyu00X8t1hyN2Show2l2vxLACGUzVkTQt15s7uDLKE7qLmKSR3EuSGXWv3wA=" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "2293ff99-3c6d-46d1-8635-5e679d5b134a", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQABAoIBADNcMt6hAHub4JTAYS6Mra0EPRBO2XhWmACBrv3+8ETClXd5475KPLDewgRVtlmtbwU8G8awUXESQgPS9lfiqvQhPreA3cHlm6oP2WMKOEtakr2s8I+frsTBLCo0Ini9RaSzjoVVgS0zofyhASKi+T970MafSj5P3XNb8YBFdXgoYDiA7FXLH6a/+m7LScL+wGcFMAAeYESxZbMQLfH3v8L+4EcTraiwjLG17ZdlF3dpybMyUSse6ZQ/PdlyvBuzzLXhN6Ce2gd9ATfS+YWTzo7Yf+GU+ex5bIpVOfHqtuM/hyq7YGKENClsXwNZIAoFnvGCbvECAfgyapVrD30IfykCgYEA0rgsSZ82pxT40NxwgBD1g9lbNVBKXphRB/3S078qusUzJjT7AldEj4imGPhAbI7bI8gAeWJsp1XJWkjM8ktaVrh+NQl7p8e9OPh0pQF/5Bdg8ajbjXESpjnaU66pVYRQy/d+jNli/YRAHX5RUfsBl+6W4+WSVMGmKBiqJsur+ecCgYEAz1YVXClcmUnyZem5B+2E9noIzjF6ROE+jIb6rawM85P3Xd0lXtECQavtxw+Qk7I32qOwrxl1UpK2foVel3pazi+4OpMfmqtYGenRP1Zk1cZwrDo0cIemTDGjj3kJ8tYn12CGolFQpJZgK6OHzvG0tOxI5VZgjIViWNPe1PGWXtUCgYEAxXGNDe8BZs1f11S2lUlOw5yGug3hoYFXbAWJ5p7Ziuf8ZXB/QlJDC7se54a11wKEk6Jzz0lKRgE8CjzszJuOqnN0zn10QGIIC7nCklo1W6QMUmPGVWH994N976tZP6gbjQL6sT+AYcvpx7j0ubxYYeRNvnz+ACzzY964kGGHY0ECgYEAumlwPPNnMN7+VEjGNm2D7UMdJZ3wi3tkjF5ThdA5uMohTsAk+FG80KSu3RmOaGyEsUwY7+VYyYvlDm4E9PZqLBVVczyR3rMNPAcwPd0EPfvzk7WlLkOX7ct3fehaXH3VRlyfz9KCSeh1wOZ/lT1VtpD2nVOC7PSDzs92+kfXZZ0CgYAnrD1y4skgXkdwolZ3unn3EFyGm2d+X5aMTHwQPdWxqoNIAl/9wdghlzihwnPhhsxq1WzlxuC3V2IMrNPtRx70Mi+FbSmR5m4Xx5RptgMtMlwno+L40PzNJgMjHGjt0wcx3Vel8wuohDtnqMyS7P5nG1/TQx0Cyzwn7QOXlNpgbQ==" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICmzCCAYMCBgGG3GWyBTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZkYnJlcG8wHhcNMjMwMzEzMTkxMzE3WhcNMzMwMzEzMTkxNDU3WjARMQ8wDQYDVQQDDAZkYnJlcG8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqqcdDYFZZb28M0tEJzEP77FmD/Xqioyj9zWX6VwUSOMAgmMmn8eqs9hT9T0a+q4YTo9tUW1PNbUpwprA5b4Uk04DcIajxDVMUR/PjcHytmkqwVskq9AZW/Vngdoo+8tSbuIybwe/3Vwt266hbHpDcM97a+DXcYooRl7tQWCEX7RP27wQrMD9epDQ6IgKayZg9vC9/03dsIqwH9jXQRiZlFvwiEKhX2aY7lPGBaCK414JO00K/Z49iov9TRa/IYVbSt5qwgrx6DcqsBSPwOnI6A85UGfeUEZ/7coVJiL7RvBlsllapsL9eWTbQajVh94k9Ei3sibEPbtH+U2OAM78zAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAASnN1Cuif1sdfEK2kWAURSXGJCohCROLWdKFjaeHPRaEfpbFJsgxW0Yj3nwX5O3bUlOWoTyENwnXSsXMQsqnNi+At32CKaKO8+AkhAbgQL9F0B+KeJwmYv3cUj5N/LYkJjBvZBzUZ4Ugu5dcxH0k7AktLAIwimkyEnxTNolOA3UyrGGpREr8MCKWVr10RFuOpF/0CsJNNwbHXzalO9D756EUcRWZ9VSg6QVNso0YYRKTnILWDn9hcTRnqGy3SHo3anFTqQZ+BB57YbgFWy6udC0LYRB3zdp6zNti87eu/VEymiDY/mmo1AB8Tm0b6vxFz4AKcL3ax5qS6YnZ9efSzk=" ], + "priority" : [ "100" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "88e5d526-2298-413c-a904-133ad839d47f", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "bc0b483f-4a3f-4c15-bf65-b26f5320e6c9", + "alias" : "Authentication Options", + "description" : "Authentication options.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "basic-auth", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "basic-auth-otp", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "a690c715-fbae-4c20-b680-bd4010718761", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ad6d407e-c73e-4439-baf3-d7c99c6cb6ad", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "e5d03405-e10a-408a-adb2-41dbb4f24515", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "96b93843-62d0-44f1-84dd-21cc5f95f523", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "088f4051-36ab-4952-a4f2-4ba53c408083", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "05f37bb2-779d-4e3f-ad1b-f6eb33bb3de4", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "300a5647-7d2c-4348-9f1f-51504bfda1c4", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "26afc672-314b-4ad9-9711-7aaeafd7c00c", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "9b301f6c-eda7-4da0-ba09-1a6454ff910d", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "6e54f1be-dbad-4b6d-8eee-8e048d413c63", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "31da4b94-03c4-4d79-9ac3-5df1445c0781", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "2e16651d-681f-4d9b-9dd4-9acdb465cd43", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "da109a26-fefa-48a4-ae8e-1d49627c2db8", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "b8f1f963-6813-4875-bae8-ce48a813763b", + "alias" : "http challenge", + "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "no-cookie-redirect", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Authentication Options", + "userSetupAllowed" : false + } ] + }, { + "id" : "4c983c77-241f-41c5-8b8a-e2cd6fc08914", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "d62c8dd6-633c-408a-aa99-43071510efb4", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-profile-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "c8ca5be7-e76d-4e16-b5ca-3ced99d92dbb", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "389c1c37-e8af-4610-a507-e1257f55b954", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "d66ca9d0-1645-4c84-abfe-c0a696f17de4", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "061cc6b8-90be-4423-9bf9-974ead709b5d", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : false, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : false, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaAuthRequestedUserHint" : "login_hint", + "clientOfflineSessionMaxLifespan" : "0", + "oauth2DevicePollingInterval" : "5", + "clientSessionIdleTimeout" : "0", + "actionTokenGeneratedByUserLifespan-execute-actions" : "", + "actionTokenGeneratedByUserLifespan-verify-email" : "", + "clientOfflineSessionIdleTimeout" : "0", + "actionTokenGeneratedByUserLifespan-reset-credentials" : "", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false", + "cibaExpiresIn" : "120", + "oauth2DeviceCodeLifespan" : "600", + "actionTokenGeneratedByUserLifespan-idp-verify-account-via-email" : "", + "parRequestUriLifespan" : "60", + "clientSessionMaxLifespan" : "0", + "shortVerificationUri" : "" + }, + "keycloakVersion" : "21.0.2", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } } \ No newline at end of file diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index 1f8f3ced9d21bb27eccb4c9f7475bee2e5a6bc5f..80fdd15f1daff7625508eb8d46d9b54332a5150f 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -1,8 +1,6 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.api.user.UserDetailsDto; -import at.tuwien.config.GatewayConfig; import at.tuwien.exception.*; import at.tuwien.gateway.KeycloakGateway; import jakarta.servlet.ServletException; @@ -13,40 +11,24 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; -import java.util.List; - @Log4j2 @Component public class BasicAuthenticationProvider implements AuthenticationManager { - private final GatewayConfig gatewayConfig; private final AuthTokenFilter authTokenFilter; private final KeycloakGateway keycloakGateway; @Autowired - public BasicAuthenticationProvider(GatewayConfig gatewayConfig, AuthTokenFilter authTokenFilter, - KeycloakGateway keycloakGateway) { - this.gatewayConfig = gatewayConfig; + public BasicAuthenticationProvider(AuthTokenFilter authTokenFilter, KeycloakGateway keycloakGateway) { this.authTokenFilter = authTokenFilter; this.keycloakGateway = keycloakGateway; } @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { - if (auth.getName().equals(gatewayConfig.getAdminUsername()) - && auth.getCredentials().toString().equals(gatewayConfig.getAdminPassword())) { - log.trace("current user is {}: skip authentication", gatewayConfig.getAdminUsername()); - final UserDetails userDetails = UserDetailsDto.builder() - .username(auth.getName()) - .authorities(List.of(new SimpleGrantedAuthority("admin"))) - .build(); - return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } - log.trace("current user is {}: begin authentication", auth.getName()); try { final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..835b7245d1ef2ca017375990dd77c20693f3ef6f --- /dev/null +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java @@ -0,0 +1,47 @@ +package at.tuwien.auth; + +import at.tuwien.api.keycloak.TokenDto; +import at.tuwien.config.GatewayConfig; +import at.tuwien.exception.AccountNotSetupException; +import at.tuwien.exception.AuthServiceConnectionException; +import at.tuwien.exception.CredentialsInvalidException; +import at.tuwien.gateway.KeycloakGateway; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +import java.io.IOException; +import java.util.List; + +@Log4j2 +public class InternalRequestInterceptor implements ClientHttpRequestInterceptor { + + private final GatewayConfig gatewayConfig; + private final KeycloakGateway keycloakGateway; + + public InternalRequestInterceptor(GatewayConfig gatewayConfig, KeycloakGateway keycloakGateway) { + this.gatewayConfig = gatewayConfig; + this.keycloakGateway = keycloakGateway; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + final HttpHeaders headers = request.getHeaders(); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + try { + final TokenDto token = keycloakGateway.obtainUserToken(gatewayConfig.getSystemUsername(), + gatewayConfig.getSystemPassword()); + headers.setBearerAuth(token.getAccessToken()); + log.trace("set bearer token for internal user: {}", gatewayConfig.getSystemUsername()); + return execution.execute(request, body); + } catch (AuthServiceConnectionException | CredentialsInvalidException | AccountNotSetupException e) { + log.error("Failed to obtain token for internal user: {}", gatewayConfig.getSystemUsername()); + throw new IOException("Failed to obtain token for internal user", e); + } + } +} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index c64fc52282af3dc8fb3f6bc075ad080e5f162f0c..d7fc192bb6c795fb9425ff99c318f2027fe8ff8d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -1,24 +1,15 @@ package at.tuwien.config; +import at.tuwien.auth.InternalRequestInterceptor; +import at.tuwien.gateway.KeycloakGateway; import lombok.Getter; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpRequest; -import org.springframework.http.MediaType; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.context.annotation.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; -import java.io.IOException; -import java.util.List; - @Log4j2 @Getter @Configuration @@ -42,25 +33,26 @@ public class GatewayConfig { @Value("${spring.rabbitmq.password}") private String brokerPassword; - @Value("${dbrepo.admin.username}") - private String adminUsername; + @Value("${dbrepo.system.username}") + private String systemUsername; + + @Value("${dbrepo.system.password}") + private String systemPassword; - @Value("${dbrepo.admin.password}") - private String adminPassword; + private final KeycloakGateway keycloakGateway; - @Primary - public RestTemplate restTemplate() { - return new RestTemplate(); + @Autowired + public GatewayConfig(KeycloakGateway keycloakGateway) { + this.keycloakGateway = keycloakGateway; } + @Profile("!junit") @Bean("brokerRestTemplate") public RestTemplate brokerRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(brokerEndpoint)); - log.debug("add basic authentication for broker service: username={}, password=(hidden)", brokerUsername); restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword), - clientHttpRequestInterceptor())); + .add(new InternalRequestInterceptor(this, keycloakGateway)); return restTemplate; } @@ -68,10 +60,8 @@ public class GatewayConfig { public RestTemplate dataServiceRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(dataEndpoint)); - log.debug("add basic authentication for data service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), - clientHttpRequestInterceptor())); + .add(new InternalRequestInterceptor(this, keycloakGateway)); return restTemplate; } @@ -79,10 +69,8 @@ public class GatewayConfig { public RestTemplate analyseServiceRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(analyseEndpoint)); - log.debug("add basic authentication for analyse service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), - clientHttpRequestInterceptor())); + .add(new InternalRequestInterceptor(this, keycloakGateway)); return restTemplate; } @@ -90,20 +78,9 @@ public class GatewayConfig { public RestTemplate searchServiceRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(searchEndpoint)); - log.debug("add basic authentication for search service: username={}, password=(hidden)", adminUsername); restTemplate.getInterceptors() - .addAll(List.of(new BasicAuthenticationInterceptor(adminUsername, adminPassword), - clientHttpRequestInterceptor())); + .add(new InternalRequestInterceptor(this, keycloakGateway)); return restTemplate; } - @Bean - public ClientHttpRequestInterceptor clientHttpRequestInterceptor() { - return (request, body, execution) -> { - final HttpHeaders headers = request.getHeaders(); - headers.setAccept(List.of(MediaType.APPLICATION_JSON)); - return execution.execute(request, body); - }; - } - } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java index 4d258d496aa6ebe825ac2d84a1f00a1b4f9c0298..e422223e06489ff144b148b8210913c1bdff3423 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java @@ -2,16 +2,12 @@ package at.tuwien.config; import at.tuwien.interceptor.KeycloakInterceptor; import lombok.Getter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; -import java.util.List; - @Getter @Configuration public class KeycloakConfig { @@ -31,11 +27,9 @@ public class KeycloakConfig { @Value("${dbrepo.keycloak.clientSecret}") private String keycloakClientSecret; - private final ClientHttpRequestInterceptor clientHttpRequestInterceptor; - - @Autowired - public KeycloakConfig(ClientHttpRequestInterceptor clientHttpRequestInterceptor) { - this.clientHttpRequestInterceptor = clientHttpRequestInterceptor; + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); } @Bean("keycloakRestTemplate") @@ -43,8 +37,7 @@ public class KeycloakConfig { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(keycloakEndpoint)); restTemplate.getInterceptors() - .addAll(List.of(new KeycloakInterceptor(keycloakUsername, keycloakPassword, keycloakEndpoint), - clientHttpRequestInterceptor)); + .add(new KeycloakInterceptor(keycloakUsername, keycloakPassword, keycloakEndpoint)); return restTemplate; } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java index bef02350067f207e03aed94dfc0e06939c6b6c83..0ed5001dd434d400a792bd3700b902d43b435de0 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/RabbitConfig.java @@ -19,4 +19,7 @@ public class RabbitConfig { @Value("${spring.rabbitmq.virtual-host}") private String virtualHost; + @Value("${dbrepo.endpoints.brokerService}") + private String brokerEndpoint; + } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java index 769cf00b01292a131609d2241e23685289e6a888..ae15c9df2d3406a09ec6aeafbfebf571a0325a78 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java @@ -43,8 +43,8 @@ public class WebSecurityConfig { } @Bean - public SecurityFilterChain filterChain(GatewayConfig gatewayConfig, HttpSecurity http, - KeycloakGateway keycloakGateway) throws Exception { + public SecurityFilterChain filterChain(HttpSecurity http, KeycloakGateway keycloakGateway) + throws Exception { final OrRequestMatcher internalEndpoints = new OrRequestMatcher( new AntPathRequestMatcher("/actuator/**", "GET"), new AntPathRequestMatcher("/v3/api-docs.yaml"), @@ -88,8 +88,8 @@ public class WebSecurityConfig { http.addFilterBefore(authTokenFilter(), UsernamePasswordAuthenticationFilter.class ); - http.addFilterBefore(new BasicAuthenticationFilter(new BasicAuthenticationProvider(gatewayConfig, - authTokenFilter(), keycloakGateway)), + http.addFilterBefore(new BasicAuthenticationFilter(new BasicAuthenticationProvider(authTokenFilter(), + keycloakGateway)), UsernamePasswordAuthenticationFilter.class ); return http.build(); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java index 0ca0f707e45da7bc25138707eedc68ad88ab26e2..42e8912d0c1c716309ead8d8ddfc3829f3206709 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java @@ -10,31 +10,31 @@ public interface BrokerServiceGateway { * Create topic exchange permissions at the broker service. * * @param data The topic exchange permissions. - * @throws ServiceConnectionException - * @throws ServiceException + * @throws BrokerServiceConnectionException + * @throws BrokerServiceException */ - void grantExchangePermission(String username, GrantExchangePermissionsDto data) throws ServiceConnectionException, - ServiceException; + void grantExchangePermission(String username, GrantExchangePermissionsDto data) + throws BrokerServiceConnectionException, BrokerServiceException; /** * Grants a user permission at a virtual host in the queue service. * * @param username The username of the user. * @param data The grant data. - * @throws ServiceConnectionException - * @throws ServiceException + * @throws BrokerServiceConnectionException + * @throws BrokerServiceException */ - void grantTopicPermission(String username, ExchangeUpdatePermissionsDto data) throws ServiceConnectionException, - ServiceException; + void grantTopicPermission(String username, ExchangeUpdatePermissionsDto data) + throws BrokerServiceConnectionException, BrokerServiceException; /** * Grants a user permission at a virtual host in the queue service. * * @param username The username of the user. * @param data The grant data. - * @throws ServiceConnectionException - * @throws ServiceException + * @throws BrokerServiceConnectionException + * @throws BrokerServiceException */ void grantVirtualHostPermission(String username, GrantVirtualHostPermissionsDto data) - throws ServiceConnectionException, ServiceException; + throws BrokerServiceConnectionException, BrokerServiceException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java index 9edb9f388da8ef481f2ec1b18522f8bc4695b954..91fb96e5f93ca5f4fd17c120d2f8f00703f3a3e3 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java @@ -17,31 +17,163 @@ import java.util.List; import java.util.UUID; public interface DataServiceGateway { - void createAccess(Long databaseId, UUID userId, AccessTypeDto access) throws ServiceConnectionException, ServiceException, DatabaseNotFoundException; - void updateAccess(Long databaseId, UUID userId, AccessTypeDto access) throws ServiceConnectionException, ServiceException, AccessNotFoundException; - - void deleteAccess(Long databaseId, UUID userId) throws ServiceConnectionException, ServiceException, AccessNotFoundException; - - DatabaseDto createDatabase(CreateDatabaseDto data) throws ServiceConnectionException, ServiceException; - - void updateDatabase(Long databaseId, UpdateUserPasswordDto data) throws ServiceConnectionException, ServiceException, DatabaseNotFoundException; - - void createTable(Long databaseId, TableCreateDto data) throws ServiceConnectionException, ServiceException, DatabaseNotFoundException, TableExistsException; - - void deleteTable(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException; - - ViewDto createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException; - - void deleteView(Long databaseId, Long viewId) throws ServiceConnectionException, ServiceException, ViewNotFoundException; - - QueryDto findQuery(Long databaseId, Long queryId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; - - ExportResourceDto exportQuery(Long databaseId, Long queryId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; - - List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; - - List<ViewDto> getViewSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; - - TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException; + /** + * Create r/w access for a given user to a given database. + * @param databaseId The database id. + * @param userId The user id. + * @param access The access. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + */ + void createAccess(Long databaseId, UUID userId, AccessTypeDto access) throws DataServiceConnectionException, + DataServiceException, DatabaseNotFoundException; + + /** + * Update r/w access for a given user to a given database. + * @param databaseId The database id. + * @param userId The user id. + * @param access The access. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + */ + void updateAccess(Long databaseId, UUID userId, AccessTypeDto access) throws DataServiceConnectionException, + DataServiceException, AccessNotFoundException; + + /** + * Deletes access for a given user to a given database. + * @param databaseId The database id. + * @param userId The user id. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + */ + void deleteAccess(Long databaseId, UUID userId) throws DataServiceConnectionException, DataServiceException, + AccessNotFoundException; + + /** + * Creates a database in the data service. + * @param data The data. + * @return The created database, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + */ + DatabaseDto createDatabase(CreateDatabaseDto data) throws DataServiceConnectionException, DataServiceException, + DatabaseNotFoundException; + + /** + * Updates the user password in the given database in the data service. + * @param databaseId The database id. + * @param data The user password. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + */ + void updateDatabase(Long databaseId, UpdateUserPasswordDto data) throws DataServiceConnectionException, + DataServiceException, DatabaseNotFoundException; + + /** + * Creates a table in a given database. + * @param databaseId The database id. + * @param data The table data. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws TableExistsException A table with this internal name exists already in the database. + */ + void createTable(Long databaseId, TableCreateDto data) throws DataServiceConnectionException, DataServiceException, + DatabaseNotFoundException, TableExistsException; + + /** + * Deletes a given table in a given database. + * @param databaseId The database id. + * @param tableId The table id. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The given table was not found in the database. + */ + void deleteTable(Long databaseId, Long tableId) throws DataServiceConnectionException, DataServiceException, + TableNotFoundException; + + /** + * Creates a view in the given database. + * @param databaseId The database id. + * @param data The view data. + * @return The created view, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + */ + ViewDto createView(Long databaseId, ViewCreateDto data) throws DataServiceConnectionException, DataServiceException; + + /** + * Deletes a given view in the given database. + * @param databaseId The database id. + * @param viewId The view id. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws ViewNotFoundException The given view was not found in the database. + */ + void deleteView(Long databaseId, Long viewId) throws DataServiceConnectionException, DataServiceException, + ViewNotFoundException; + + /** + * Finds a given query in a given database. + * @param databaseId The database id. + * @param queryId The query id. + * @return The query, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws QueryNotFoundException The given query was not found in the query store. + */ + QueryDto findQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, DataServiceException, + QueryNotFoundException; + + /** + * Exports a given query. + * @param databaseId The database id. + * @param queryId The query id. + * @return The exported resource, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws QueryNotFoundException The given query was not found in the query store. + */ + ExportResourceDto exportQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, + DataServiceException, QueryNotFoundException; + + /** + * Obtain table schemas from a given database. + * @param databaseId The database id. + * @return The list of tables, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The table was not found in the database. + */ + List<TableDto> getTableSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, + TableNotFoundException; + + /** + * Obtain view schemas from a given database. + * @param databaseId The database id. + * @return The list of tables, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws ViewNotFoundException The table was not found in the database. + */ + List<ViewDto> getViewSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, + ViewNotFoundException; + + /** + * Obtain table statistics for a given table in a given database. + * @param databaseId The database id. + * @param tableId The table id. + * @return The statistic, if successful. + * @throws DataServiceConnectionException The connection to the data service could not be established. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The table was not found in the database. + */ + TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws DataServiceConnectionException, + DataServiceException, TableNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java index b949ddbaddb6bb6dfaba0b31f304a89266224cad..2cd5f142e6638f087265d6f605aa271fd518c51b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/OrcidGateway.java @@ -7,5 +7,11 @@ import org.springframework.stereotype.Service; @Service public interface OrcidGateway { + /** + * Finds metadata from given ORCID url. + * @param url The ORCID url. + * @return The metadata, if successful. + * @throws OrcidNotFoundException The metadata does not exist to the given ORCID. + */ OrcidDto findByUrl(String url) throws OrcidNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java index 9b3bbf4cf2ab931bad65a146a4024eebb94b41da..0313ca26edc598812ffc9f176737de1e05f4c1ec 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.*; import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; @@ -31,59 +30,61 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { @Override public void grantTopicPermission(String username, ExchangeUpdatePermissionsDto data) - throws ServiceConnectionException, ServiceException { + throws BrokerServiceConnectionException, BrokerServiceException { final String url = "/api/topic-permissions/" + rabbitConfig.getVirtualHost() + "/" + username; final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to grant topic permissions: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to grant topic permissions: " + e.getMessage()); + throw new BrokerServiceConnectionException("Failed to grant topic permissions: " + e.getMessage()); } catch (Exception e) { log.error("Failed to grant topic permissions: unexpected response: {}", e.getMessage()); - throw new ServiceException("Failed to grant topic permissions: unexpected response: " + e.getMessage(), e); + throw new BrokerServiceException("Failed to grant topic permissions: unexpected response: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to grant topic permissions: unexpected status: {}", response.getStatusCode().value()); - throw new ServiceException("Failed to grant topic permissions: unexpected status: " + response.getStatusCode().value()); + throw new BrokerServiceException("Failed to grant topic permissions: unexpected status: " + response.getStatusCode().value()); } } @Override - public void grantVirtualHostPermission(String username, GrantVirtualHostPermissionsDto data) throws ServiceConnectionException, ServiceException { + public void grantVirtualHostPermission(String username, GrantVirtualHostPermissionsDto data) + throws BrokerServiceConnectionException, BrokerServiceException { final String url = "/api/permissions/" + rabbitConfig.getVirtualHost() + "/" + username; final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to grant virtual host permissions: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to grant virtual host permissions: " + e.getMessage()); + throw new BrokerServiceConnectionException("Failed to grant virtual host permissions: " + e.getMessage()); } catch (Exception e) { log.error("Failed to grant virtual host permissions: unexpected response: {}", e.getMessage()); - throw new ServiceException("Failed to grant virtual host permissions: unexpected response: " + e.getMessage(), e); + throw new BrokerServiceException("Failed to grant virtual host permissions: unexpected response: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to grant virtual host permissions: unexpected status: {}", response.getStatusCode().value()); - throw new ServiceException("Failed to grant virtual host permissions: unexpected status: " + response.getStatusCode().value()); + throw new BrokerServiceException("Failed to grant virtual host permissions: unexpected status: " + response.getStatusCode().value()); } } @Override - public void grantExchangePermission(String username, GrantExchangePermissionsDto data) throws ServiceConnectionException, ServiceException { + public void grantExchangePermission(String username, GrantExchangePermissionsDto data) + throws BrokerServiceConnectionException, BrokerServiceException { final String url = "/api/topic-permissions/" + rabbitConfig.getVirtualHost() + "/" + username; final ResponseEntity<Void> response; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to grant exchange permissions: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to grant exchange permissions: " + e.getMessage()); + throw new BrokerServiceConnectionException("Failed to grant exchange permissions: " + e.getMessage()); } catch (Exception e) { log.error("Failed to grant exchange permissions: unexpected response: {}", e.getMessage()); - throw new ServiceException("Failed to grant exchange permissions: unexpected response: " + e.getMessage(), e); + throw new BrokerServiceException("Failed to grant exchange permissions: unexpected response: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED) && !response.getStatusCode().equals(HttpStatus.NO_CONTENT)) { log.error("Failed to grant exchange permissions: unexpected status: {}", response.getStatusCode().value()); - throw new ServiceException("Failed to grant exchange permissions: unexpected status: " + response.getStatusCode().value()); + throw new BrokerServiceException("Failed to grant exchange permissions: unexpected status: " + response.getStatusCode().value()); } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java index 7c5d4b19f553c26201a1f6653465fc66454e7e54..9b675cba348f7cc142958f9ee1cd93de198c2055 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/CrossrefGatewayImpl.java @@ -4,6 +4,7 @@ import at.tuwien.api.crossref.CrossrefDto; import at.tuwien.exception.DoiNotFoundException; import at.tuwien.gateway.CrossrefGateway; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -19,8 +20,9 @@ public class CrossrefGatewayImpl implements CrossrefGateway { private final RestTemplate restTemplate; - public CrossrefGatewayImpl() { - this.restTemplate = new RestTemplate(); + @Autowired + public CrossrefGatewayImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; } @Override @@ -32,7 +34,7 @@ public class CrossrefGatewayImpl implements CrossrefGateway { try { log.trace("find crossref doi from url {}", url); response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), CrossrefDto.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to retrieve CrossRef metadata from URL {}: {}", url, e.getMessage()); throw new DoiNotFoundException("Failed to retrieve CrossRef metadata from URL " + url + ": " + e.getMessage()); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java index 6c09d6d50067be958efc69cfbc28fa866cfec803..4a3f12f759d603a9c76ea37ae223a43e05cf897f 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java @@ -34,7 +34,7 @@ public class DataServiceGatewayImpl implements DataServiceGateway { @Override public void createAccess(Long databaseId, UUID userId, AccessTypeDto access) - throws ServiceConnectionException, ServiceException, DatabaseNotFoundException { + throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; try { @@ -42,23 +42,23 @@ public class DataServiceGatewayImpl implements DataServiceGateway { new HttpEntity<>(UpdateDatabaseAccessDto.builder().type(access).build()), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to create access: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to create access: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to create access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to create access: not found: {}", e.getMessage()); throw new DatabaseNotFoundException("Failed to create access: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to create access: {}", e.getMessage()); - throw new ServiceException("Failed to create access: " + e.getMessage(), e); + throw new DataServiceException("Failed to create access: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to create access: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to create access: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to create access: wrong http code: " + response.getStatusCode()); } } @Override public void updateAccess(Long databaseId, UUID userId, AccessTypeDto access) - throws ServiceConnectionException, ServiceException, AccessNotFoundException { + throws DataServiceConnectionException, DataServiceException, AccessNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; try { @@ -66,22 +66,22 @@ public class DataServiceGatewayImpl implements DataServiceGateway { new HttpEntity<>(UpdateDatabaseAccessDto.builder().type(access).build()), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to update access: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to update access: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to update access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to update access: not found: {}", e.getMessage()); throw new AccessNotFoundException("Failed to update access: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to update access: {}", e.getMessage()); - throw new ServiceException("Failed to update access: " + e.getMessage(), e); + throw new DataServiceException("Failed to update access: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to update access: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to update access: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to update access: wrong http code: " + response.getStatusCode()); } } @Override - public void deleteAccess(Long databaseId, UUID userId) throws ServiceConnectionException, ServiceException, + public void deleteAccess(Long databaseId, UUID userId) throws DataServiceConnectionException, DataServiceException, AccessNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/access/" + userId; @@ -89,65 +89,69 @@ public class DataServiceGatewayImpl implements DataServiceGateway { response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); } catch (HttpServerErrorException e) { log.error("Failed to delete access: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to delete access: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to delete access: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to delete access: not found: {}", e.getMessage()); throw new AccessNotFoundException("Failed to delete access: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to delete access: {}", e.getMessage()); - throw new ServiceException("Failed to delete access: " + e.getMessage(), e); + throw new DataServiceException("Failed to delete access: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to delete access: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to delete access: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to delete access: wrong http code: " + response.getStatusCode()); } } @Override - public DatabaseDto createDatabase(CreateDatabaseDto data) throws ServiceConnectionException, ServiceException { + public DatabaseDto createDatabase(CreateDatabaseDto data) throws DataServiceConnectionException, + DataServiceException, DatabaseNotFoundException { final ResponseEntity<DatabaseDto> response; final String url = "/api/database"; try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), DatabaseDto.class); } catch (HttpServerErrorException e) { log.error("Failed to create database: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to create database: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to create database: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { - log.error("Failed to create database: {}", e.getMessage()); - throw new ServiceException("Failed to create database: " + e.getMessage(), e); + log.error("Failed to create database: malformed: {}", e.getMessage()); + throw new DataServiceException("Failed to create database: malformed: " + e.getMessage(), e); + } catch (HttpClientErrorException.NotFound e) { + log.error("Failed to create database: not found: {}", e.getMessage()); + throw new DatabaseNotFoundException("Failed to create database: not found: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to create database: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to create database: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to create database: wrong http code: " + response.getStatusCode()); } return response.getBody(); } @Override - public void updateDatabase(Long databaseId, UpdateUserPasswordDto data) throws ServiceConnectionException, - ServiceException, DatabaseNotFoundException { + public void updateDatabase(Long databaseId, UpdateUserPasswordDto data) throws DataServiceConnectionException, + DataServiceException, DatabaseNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId; try { response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(data), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to update user password in database: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to update user password in database: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to update user password in database: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to update user password in database: not found: {}", e.getMessage()); throw new DatabaseNotFoundException("Failed to update user password in database: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to update user password in database: {}", e.getMessage()); - throw new ServiceException("Failed to update user password in database: " + e.getMessage(), e); + throw new DataServiceException("Failed to update user password in database: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to update user password in database: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to update user password in database: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to update user password in database: wrong http code: " + response.getStatusCode()); } } @Override - public void createTable(Long databaseId, TableCreateDto data) throws ServiceConnectionException, ServiceException, + public void createTable(Long databaseId, TableCreateDto data) throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException, TableExistsException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table"; @@ -155,7 +159,7 @@ public class DataServiceGatewayImpl implements DataServiceGateway { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to create table: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to create table: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to create table: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to create table: not found: {}", e.getMessage()); throw new DatabaseNotFoundException("Failed to create table: not found: " + e.getMessage(), e); @@ -164,16 +168,16 @@ public class DataServiceGatewayImpl implements DataServiceGateway { throw new TableExistsException("Failed to create table: already exists", e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to create table: {}", e.getMessage()); - throw new ServiceException("Failed to create table: " + e.getMessage(), e); + throw new DataServiceException("Failed to create table: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to create table: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to create table: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to create table: wrong http code: " + response.getStatusCode()); } } @Override - public void deleteTable(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, + public void deleteTable(Long databaseId, Long tableId) throws DataServiceConnectionException, DataServiceException, TableNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/table/" + tableId; @@ -181,46 +185,46 @@ public class DataServiceGatewayImpl implements DataServiceGateway { response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); } catch (HttpServerErrorException e) { log.error("Failed to delete table: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to delete table: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to delete table: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to delete table: not found: {}", e.getMessage()); throw new TableNotFoundException("Failed to delete table: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to delete table: {}", e.getMessage()); - throw new ServiceException("Failed to delete table: " + e.getMessage(), e); + throw new DataServiceException("Failed to delete table: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to delete table: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to delete table: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to delete table: wrong http code: " + response.getStatusCode()); } } @Override - public ViewDto createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException { + public ViewDto createView(Long databaseId, ViewCreateDto data) throws DataServiceConnectionException, DataServiceException { final ResponseEntity<ViewDto> response; final String url = "/api/database/" + databaseId + "/view"; try { response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), ViewDto.class); } catch (HttpServerErrorException e) { log.error("Failed to create view: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to create view: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to create view: " + e.getMessage(), e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { log.error("Failed to create view: {}", e.getMessage()); - throw new ServiceException("Failed to create view: " + e.getMessage(), e); + throw new DataServiceException("Failed to create view: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to create view: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to create view: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to create view: wrong http code: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to create view: empty body: {}", response.getStatusCode()); - throw new ServiceException("Failed to create view: empty body: " + response.getStatusCode()); + throw new DataServiceException("Failed to create view: empty body: " + response.getStatusCode()); } return response.getBody(); } @Override - public void deleteView(Long databaseId, Long viewId) throws ServiceConnectionException, ServiceException, + public void deleteView(Long databaseId, Long viewId) throws DataServiceConnectionException, DataServiceException, ViewNotFoundException { final ResponseEntity<Void> response; final String url = "/api/database/" + databaseId + "/view/" + viewId; @@ -228,22 +232,22 @@ public class DataServiceGatewayImpl implements DataServiceGateway { response = restTemplate.exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class); } catch (HttpServerErrorException e) { log.error("Failed to delete view: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to delete view: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to delete view: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to delete view: not found: {}", e.getMessage()); throw new ViewNotFoundException("Failed to delete view: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to delete view: {}", e.getMessage()); - throw new ServiceException("Failed to delete view: " + e.getMessage(), e); + throw new DataServiceException("Failed to delete view: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to delete view: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to delete view: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to delete view: wrong http code: " + response.getStatusCode()); } } @Override - public QueryDto findQuery(Long databaseId, Long queryId) throws ServiceConnectionException, ServiceException, + public QueryDto findQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, DataServiceException, QueryNotFoundException { final ResponseEntity<QueryDto> response; final String url = "/api/database/" + databaseId + "/subset/" + queryId; @@ -251,71 +255,72 @@ public class DataServiceGatewayImpl implements DataServiceGateway { response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, QueryDto.class); } catch (HttpServerErrorException e) { log.error("Failed to find query: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to find query", e); + throw new DataServiceConnectionException("Failed to find query", e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to find query: not found: {}", e.getMessage()); throw new QueryNotFoundException("Failed to find query: not found", e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to find query: unauthorized: {}", e.getMessage()); - throw new ServiceException("Failed to find query: unauthorized", e); + throw new DataServiceException("Failed to find query: unauthorized", e); } catch (HttpClientErrorException.NotAcceptable e) { log.error("Failed to find query: format not acccepted: {}", e.getMessage()); - throw new ServiceException("Failed to find query: format not accepted", e); + throw new DataServiceException("Failed to find query: format not accepted", e); } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find query: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to find query: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to find query: wrong http code: " + response.getStatusCode()); } return response.getBody(); } @Override - public ExportResourceDto exportQuery(Long databaseId, Long queryId) throws ServiceConnectionException, - ServiceException, QueryNotFoundException { + public ExportResourceDto exportQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, + DataServiceException, QueryNotFoundException { final ResponseEntity<ExportResourceDto> response; final String url = "/api/database/" + databaseId + "/subset/" + queryId; try { response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ExportResourceDto.class); } catch (HttpServerErrorException e) { log.error("Failed to export query: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to export query: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to export query: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to export query: not found: {}", e.getMessage()); throw new QueryNotFoundException("Failed to export query: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to export query: {}", e.getMessage()); - throw new ServiceException("Failed to export query: " + e.getMessage(), e); + throw new DataServiceException("Failed to export query: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to export query: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to export query: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to export query: wrong http code: " + response.getStatusCode()); } return response.getBody(); } @Override - public List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException { + public List<TableDto> getTableSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, + TableNotFoundException { final ResponseEntity<TableDto[]> response; final String url = "/api/database/" + databaseId + "/table"; try { response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableDto[].class); } catch (HttpServerErrorException e) { log.error("Failed to get table schemas: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to get table schemas: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to get table schemas: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to get table schemas: not found: {}", e.getMessage()); - throw new QueryNotFoundException("Failed to get table schemas: not found: " + e.getMessage(), e); + throw new TableNotFoundException("Failed to get table schemas: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to get table schemas: {}", e.getMessage()); - throw new ServiceException("Failed to get table schemas: " + e.getMessage(), e); + throw new DataServiceException("Failed to get table schemas: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to get table schemas: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to get table schemas: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to get table schemas: wrong http code: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to get table schemas: empty body: {}", response.getStatusCode()); - throw new ServiceException("Failed to get table schemas: empty body: " + response.getStatusCode()); + throw new DataServiceException("Failed to get table schemas: empty body: " + response.getStatusCode()); } final List<TableDto> tables = Arrays.asList(response.getBody()); log.debug("found {} table(s) in data service", tables.size()); @@ -323,28 +328,29 @@ public class DataServiceGatewayImpl implements DataServiceGateway { } @Override - public List<ViewDto> getViewSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException { + public List<ViewDto> getViewSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, + ViewNotFoundException { final ResponseEntity<ViewDto[]> response; final String url = "/api/database/" + databaseId + "/view"; try { response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, ViewDto[].class); } catch (HttpServerErrorException e) { log.error("Failed to get view schemas: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to get view schemas: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to get view schemas: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to get view schemas: not found: {}", e.getMessage()); - throw new QueryNotFoundException("Failed to get view schemas: not found: " + e.getMessage(), e); + throw new ViewNotFoundException("Failed to get view schemas: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to get view schemas: {}", e.getMessage()); - throw new ServiceException("Failed to get view schemas: " + e.getMessage(), e); + throw new DataServiceException("Failed to get view schemas: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to get view schemas: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to get view schemas: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to get view schemas: wrong http code: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to get view schemas: empty body: {}", response.getStatusCode()); - throw new ServiceException("Failed to get view schemas: empty body: " + response.getStatusCode()); + throw new DataServiceException("Failed to get view schemas: empty body: " + response.getStatusCode()); } final List<ViewDto> views = Arrays.asList(response.getBody()); log.debug("found {} view(s) in data service", views.size()); @@ -352,28 +358,28 @@ public class DataServiceGatewayImpl implements DataServiceGateway { } @Override - public TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException { + public TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws DataServiceConnectionException, DataServiceException, TableNotFoundException { final ResponseEntity<TableStatisticDto> response; final String url = "/api/database/" + databaseId + "/table/" + tableId + "/statistic"; try { response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, TableStatisticDto.class); } catch (HttpServerErrorException e) { log.error("Failed to analyse table statistic: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to analyse table statistic: " + e.getMessage(), e); + throw new DataServiceConnectionException("Failed to analyse table statistic: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to analyse table statistic: not found: {}", e.getMessage()); throw new TableNotFoundException("Failed to analyse table statistic: not found: " + e.getMessage(), e); } catch (HttpClientErrorException.Unauthorized e) { log.error("Failed to analyse table statistic: {}", e.getMessage()); - throw new ServiceException("Failed to analyse table statistic: " + e.getMessage(), e); + throw new DataServiceException("Failed to analyse table statistic: " + e.getMessage(), e); } if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to analyse table statistic: wrong http code: {}", response.getStatusCode()); - throw new ServiceException("Failed to analyse table statistic: wrong http code: " + response.getStatusCode()); + throw new DataServiceException("Failed to analyse table statistic: wrong http code: " + response.getStatusCode()); } if (response.getBody() == null) { log.error("Failed to analyse table statistic: empty body: {}", response.getStatusCode()); - throw new ServiceException("Failed to analyse table statistic: empty body: " + response.getStatusCode()); + throw new DataServiceException("Failed to analyse table statistic: empty body: " + response.getStatusCode()); } return response.getBody(); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 91ec52d8e092101704acea72ba38656e1aec008f..d05243f9a5bf81a752c085184b754acae1405ad3 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 @@ -24,12 +24,15 @@ import java.util.UUID; public class KeycloakGatewayImpl implements KeycloakGateway { private final RestTemplate restTemplate; + private final RestTemplate keycloakRestTemplate; private final KeycloakConfig keycloakConfig; private final MetadataMapper metadataMapper; - public KeycloakGatewayImpl(@Qualifier("keycloakRestTemplate") RestTemplate restTemplate, + public KeycloakGatewayImpl(@Qualifier("restTemplate") RestTemplate restTemplate, + @Qualifier("keycloakRestTemplate") RestTemplate keycloakRestTemplate, KeycloakConfig keycloakConfig, MetadataMapper metadataMapper) { this.restTemplate = restTemplate; + this.keycloakRestTemplate = keycloakRestTemplate; this.keycloakConfig = keycloakConfig; this.metadataMapper = metadataMapper; } @@ -45,13 +48,9 @@ public class KeycloakGatewayImpl implements KeycloakGateway { payload.add("client_id", "admin-cli"); final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/master/protocol/openid-connect/token"; log.trace("request admin token from url: {}", url); - log.trace("request username: {}", keycloakConfig.getKeycloakUsername()); - log.trace("request password: {}", keycloakConfig.getKeycloakPassword() != null ? "(set)" : "(not set)"); - log.trace("request client_id: admin-cli"); - log.trace("request client_secret: (not set)"); final ResponseEntity<TokenDto> response; try { - response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + response = keycloakRestTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); } catch (HttpServerErrorException e) { log.error("Failed to obtain admin token: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -78,15 +77,10 @@ public class KeycloakGatewayImpl implements KeycloakGateway { payload.add("client_id", keycloakConfig.getKeycloakClient()); payload.add("client_secret", keycloakConfig.getKeycloakClientSecret()); final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/dbrepo/protocol/openid-connect/token"; - log.trace("request user token from url: {}", url); - log.trace("request username: {}", username); - log.trace("request password: {}", password != null ? "(set)" : "(not set)"); - log.trace("request client_id: {}", keycloakConfig.getKeycloakClient()); - log.trace("request client_secret: {}", keycloakConfig.getKeycloakClientSecret()); + log.trace("request admin token from url: {}", url); final ResponseEntity<TokenDto> response; try { - response = new RestTemplate() - .exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); } catch (HttpServerErrorException e) { log.error("Failed to obtain user token: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -119,8 +113,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.trace("request user token from url: {}", url); final ResponseEntity<TokenDto> response; try { - response = new RestTemplate() - .exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); + response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); } catch (HttpServerErrorException e) { log.error("Failed to refresh user token: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -128,7 +121,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.error("Failed to refresh user token: invalid credentials"); throw new CredentialsInvalidException("Invalid credentials", e); } catch (HttpClientErrorException.BadRequest e) { - if (e.getMessage().contains("Session not active")) { + if (e.getMessage() != null && e.getMessage().contains("Session not active")) { log.error("Failed to refresh user token: inactive session", e); throw new CredentialsInvalidException("Inactive session", e); } @@ -148,18 +141,20 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("create user at url {}", url); final ResponseEntity<Void> response; try { - response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data, headers), Void.class); + response = keycloakRestTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data, headers), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to create user: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); } catch (HttpClientErrorException.Conflict e) { - if (e.getMessage().contains("same email")) { - log.error("Failed to create user: email exists: {}", e.getMessage()); - throw new EmailExistsException("E-Mail exists", e); - } else { - log.error("Failed to create user: user exists: {}", e.getMessage()); - throw new UserExistsException("User exists", e); + if (e.getResponseBodyAsByteArray() != null && e.getResponseBodyAsByteArray().length > 0) { + final KeycloakErrorDto error = e.getResponseBodyAs(KeycloakErrorDto.class); + if (error != null && error.getErrorMessage().contains("same email")) { + log.error("Failed to create user: email exists: {}", e.getMessage()); + throw new EmailExistsException("E-Mail exists", e); + } } + log.error("Failed to create user: user exists: {}", e.getMessage()); + throw new UserExistsException("User exists", e); } if (!response.getStatusCode().equals(HttpStatus.CREATED)) { log.error("Failed to create user: unexpected status: {}", response.getStatusCode().value()); @@ -178,7 +173,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("delete user at url {}", url); final ResponseEntity<Void> response; try { - response = restTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null, headers), Void.class); + response = keycloakRestTemplate.exchange(url, HttpMethod.DELETE, new HttpEntity<>(null, headers), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to delete user: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -207,7 +202,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("update user credentials at url {}", url); final ResponseEntity<Void> response; try { - response = restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(payload, headers), Void.class); + response = keycloakRestTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(payload, headers), Void.class); } catch (HttpServerErrorException e) { log.error("Failed to update user credentials: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -232,7 +227,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("find user from url {}", url); final ResponseEntity<UserDto[]> response; try { - response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), UserDto[].class); + response = keycloakRestTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), UserDto[].class); } catch (HttpServerErrorException e) { log.error("Failed to find user: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); @@ -258,7 +253,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { log.debug("find user from url {}", url); final ResponseEntity<UserDto> response; try { - response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), UserDto.class); + response = keycloakRestTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), UserDto.class); } catch (HttpServerErrorException e) { log.error("Failed to find user: {}", e.getMessage()); throw new AuthServiceConnectionException("Service unavailable", e); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java index debbe4d66c288fe5546364b1b3067718217ce894..15b73eb1931a2397d4dba3550479a839b23ec834 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/OrcidGatewayImpl.java @@ -4,6 +4,7 @@ import at.tuwien.api.orcid.OrcidDto; import at.tuwien.exception.OrcidNotFoundException; import at.tuwien.gateway.OrcidGateway; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -19,8 +20,9 @@ public class OrcidGatewayImpl implements OrcidGateway { private final RestTemplate restTemplate; - public OrcidGatewayImpl() { - this.restTemplate = new RestTemplate(); + @Autowired + public OrcidGatewayImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; } @Override @@ -31,7 +33,7 @@ public class OrcidGatewayImpl implements OrcidGateway { try { log.debug("find orcid from url {}", url); response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), OrcidDto.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to retrieve ORCID metadata from URL {}: {}", url, e.getMessage()); throw new OrcidNotFoundException("Failed to retrieve ORCID metadata from URL " + url + ": " + e.getMessage()); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java index 6eeb74c3c072f684834f90228dd755bfcb959c09..7a5a64e8e24faa22f0051cdef8b94ded85ab5da3 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/RorGatewayImpl.java @@ -4,6 +4,7 @@ import at.tuwien.api.ror.RorDto; import at.tuwien.exception.RorNotFoundException; import at.tuwien.gateway.RorGateway; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -19,8 +20,9 @@ public class RorGatewayImpl implements RorGateway { private final RestTemplate restTemplate; - public RorGatewayImpl() { - this.restTemplate = new RestTemplate(); + @Autowired + public RorGatewayImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; } @Override @@ -32,7 +34,7 @@ public class RorGatewayImpl implements RorGateway { try { log.trace("find ror from url {}", url); response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), RorDto.class); - } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) { + } catch (HttpServerErrorException e) { log.error("Failed to retrieve ROR metadata from URL {}: {}", url, e.getMessage()); throw new RorNotFoundException("Failed to retrieve ROR metadata from URL " + url + ": " + e.getMessage(), e); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java index d5a4d03092dfaa7ee7623dc9e3a13f946ae62a02..c47bb8daa36519ff251202d14a02f38c9212aafe 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/AccessService.java @@ -5,10 +5,8 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; import at.tuwien.exception.*; -import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.UUID; public interface AccessService { @@ -37,11 +35,11 @@ public interface AccessService { * @param access The access. * @param user The user. * @return The database access, if successful. - * @throws ServiceException The data service responded with unexpected behavior. - * @throws ServiceConnectionException The connection with the data service could not be established. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. * @throws DatabaseNotFoundException The database was not found in the metadata/search database. */ - DatabaseAccess create(Database database, User user, AccessTypeDto access) throws ServiceException, ServiceConnectionException, + DatabaseAccess create(Database database, User user, AccessTypeDto access) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; /** @@ -50,11 +48,11 @@ public interface AccessService { * @param database The database. * @param user The user. * @param access The updated access. - * @throws ServiceException The data service responded with unexpected behavior. - * @throws ServiceConnectionException The connection with the data service could not be established. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. * @throws DatabaseNotFoundException The database was not found in the metadata/search database. */ - void update(Database database, User user, AccessTypeDto access) throws ServiceException, ServiceConnectionException, + void update(Database database, User user, AccessTypeDto access) throws at.tuwien.exception.DataServiceException, DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; /** @@ -62,10 +60,10 @@ public interface AccessService { * * @param database The database. * @param user The user. - * @throws ServiceException The data service responded with unexpected behavior. - * @throws ServiceConnectionException The connection with the data service could not be established. + * @throws DataServiceException The data service responded with unexpected behavior. + * @throws DataServiceConnectionException The connection with the data service could not be established. * @throws DatabaseNotFoundException The database was not found in the search database. */ - void delete(Database database, User user) throws AccessNotFoundException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; + void delete(Database database, User user) throws AccessNotFoundException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java index 6c0021b4507a339dbc34415d668389ae16c380e8..f249f7a2cf128ffd09f4fcbeee4add401609436b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/BrokerService.java @@ -10,12 +10,12 @@ public interface BrokerService { * * @param user The user. */ - void setVirtualHostPermissions(User user) throws ServiceException, ServiceConnectionException; + void setVirtualHostPermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; /** * Sets topic exchange permissions for a user. * * @param user The user. */ - void setTopicExchangePermissions(User user) throws ServiceException, ServiceConnectionException; + void setTopicExchangePermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java index 32291c8755e56c2a59409f8e4da79c292e85d8c5..aa25ee1362f825ddf060ce9c90dde9e4c965b6bf 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -2,15 +2,11 @@ package at.tuwien.service; import at.tuwien.api.database.DatabaseCreateDto; import at.tuwien.api.database.DatabaseModifyVisibilityDto; -import at.tuwien.api.database.DatabaseTransferDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; -import java.security.Principal; import java.util.List; import java.util.UUID; @@ -55,21 +51,21 @@ public interface DatabaseService { * @param user The user. * @return The database, if successful. * @throws UserNotFoundException If the container/user was not found in the metadata database. - * @throws ServiceException If the data service returned non-successfully. - * @throws ServiceConnectionException If failing to connect to the data service/search service. + * @throws DataServiceException If the data service returned non-successfully. + * @throws DataServiceConnectionException If failing to connect to the data service/search service. */ Database create(DatabaseCreateDto createDto, User user) throws UserNotFoundException, ContainerNotFoundException, - ServiceException, ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; /** * Updates the user's password. * * @param database The database. * @param user The user. - * @throws ServiceException If the data service returned non-successfully. - * @throws ServiceConnectionException If failing to connect to the data service. + * @throws DataServiceException If the data service returned non-successfully. + * @throws DataServiceConnectionException If failing to connect to the data service. */ - void updatePassword(Database database, User user) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException; + void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException; /** * Updates the visibility of the database. @@ -78,7 +74,7 @@ public interface DatabaseService { * @param data The visibility * @return The database, if successful. * @throws NotFoundException The database was not found in the metadata database. - * @throws ServiceConnectionException If failing to connect to the search service. + * @throws DataServiceConnectionException If failing to connect to the search service. */ Database modifyVisibility(Database database, DatabaseModifyVisibilityDto data) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; @@ -101,11 +97,11 @@ public interface DatabaseService { */ Database modifyImage(Database database, byte[] image) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; - Database updateTableMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + Database updateTableMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - ServiceConnectionException, MalformedException; + DataServiceConnectionException, MalformedException, TableNotFoundException; - Database updateViewMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + Database updateViewMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - ServiceConnectionException; + DataServiceConnectionException, ViewNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java index e88f75b52eae40f3280384cbd8a52dbde9331609..4d0228f4108164eb463ccecd926d6a0ea52214c8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java @@ -85,8 +85,20 @@ public interface IdentifierService { */ List<Identifier> findAll(IdentifierTypeDto type, Long databaseId, Long queryId, Long viewId, Long tableId); + /** + * Publishes a draft identifier with DataCite. + * @param identifierId The identifier id. + * @return The resulting identifier. + * @throws SearchServiceException + * @throws DatabaseNotFoundException + * @throws SearchServiceConnectionException + * @throws MalformedException + * @throws DataServiceConnectionException + * @throws IdentifierNotFoundException + */ Identifier publish(Long identifierId) throws SearchServiceException, DatabaseNotFoundException, - SearchServiceConnectionException, MalformedException, ServiceConnectionException, IdentifierNotFoundException; + SearchServiceConnectionException, MalformedException, DataServiceConnectionException, + IdentifierNotFoundException, ExternalServiceException; /** * Creates a new identifier in the metadata database for a query or database. @@ -95,10 +107,19 @@ public interface IdentifierService { * @param user The user. * @param data The data. * @return The created identifier from the metadata database if successful. + * @throws DataServiceException + * @throws DataServiceConnectionException + * @throws IdentifierNotFoundException + * @throws MalformedException + * @throws ViewNotFoundException + * @throws DatabaseNotFoundException + * @throws QueryNotFoundException + * @throws SearchServiceException + * @throws SearchServiceConnectionException */ - Identifier save(Database database, User user, IdentifierSaveDto data) throws ServiceException, - ServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, - DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException; + Identifier save(Database database, User user, IdentifierSaveDto data) throws DataServiceException, + DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, + DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException; /** * Creates a new identifier in the metadata database for a query or database. @@ -107,10 +128,19 @@ public interface IdentifierService { * @param user The user. * @param data The data. * @return The created identifier from the metadata database if successful. + * @throws DataServiceException + * @throws DataServiceConnectionException + * @throws IdentifierNotFoundException + * @throws MalformedException + * @throws ViewNotFoundException + * @throws DatabaseNotFoundException + * @throws QueryNotFoundException + * @throws SearchServiceException + * @throws SearchServiceConnectionException */ - Identifier create(Database database, User user, IdentifierCreateDto data) throws ServiceException, - ServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, - DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException; + Identifier create(Database database, User user, IdentifierCreateDto data) throws DataServiceException, + DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, + DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, ExternalServiceException; /** * Export metadata for a identifier @@ -135,8 +165,12 @@ public interface IdentifierService { * * @param identifier The identifier. * @return The XML resource, if successful. + * @throws DataServiceException + * @throws DataServiceConnectionException + * @throws IdentifierNotFoundException + * @throws QueryNotFoundException */ - InputStreamResource exportResource(Identifier identifier) throws ServiceException, ServiceConnectionException, + InputStreamResource exportResource(Identifier identifier) throws DataServiceException, DataServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException; /** @@ -144,7 +178,13 @@ public interface IdentifierService { * database, but sets it as deleted. * * @param identifier The identifier. + * @throws DataServiceException + * @throws DataServiceConnectionException + * @throws IdentifierNotFoundException + * @throws DatabaseNotFoundException + * @throws SearchServiceException + * @throws SearchServiceConnectionException */ - void delete(Identifier identifier) throws ServiceException, ServiceConnectionException, IdentifierNotFoundException, + void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, IdentifierNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java index 0bed64884e98872842531fed2b46352615288de1..7cb195ce4ee59c919ff0377ece7636be2d091827 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/StorageService.java @@ -14,6 +14,7 @@ public interface StorageService { * @param key The object key. * @return The input stream, if successful. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. + * @throws StorageNotFoundException The object could not be found in the Storage Service. */ InputStream getObject(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException; @@ -24,6 +25,7 @@ public interface StorageService { * @param key The object key. * @return The byte array. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. + * @throws StorageNotFoundException The object could not be found in the Storage Service. */ byte[] getBytes(String key) throws StorageUnavailableException, StorageNotFoundException; @@ -34,6 +36,7 @@ public interface StorageService { * @param key The object key. * @return The byte array. * @throws StorageUnavailableException The object failed to be loaded from the Storage Service. + * @throws StorageNotFoundException The object could not be found in the Storage Service. */ byte[] getBytes(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java index 0eb228ccd5d0a284b3c94e5735cff525ff86dfe1..e4767219063b8e9ee504a404be0bbfcf806270d9 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java @@ -1,17 +1,13 @@ package at.tuwien.service; import at.tuwien.api.database.table.TableCreateDto; -import at.tuwien.api.database.table.TableHistoryDto; -import at.tuwien.api.database.table.TableStatisticDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.exception.*; -import org.springframework.transaction.annotation.Transactional; import java.security.Principal; -import java.util.List; public interface TableService { @@ -43,7 +39,7 @@ public interface TableService { * @return The created table. */ Table createTable(Database database, TableCreateDto createDto, Principal principal) - throws TableNotFoundException, ServiceException, ServiceConnectionException, UserNotFoundException, + throws TableNotFoundException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; /** @@ -51,12 +47,12 @@ public interface TableService { * * @param table The table. */ - void deleteTable(Table table) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException; + void deleteTable(Table table) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException; - TableColumn update(TableColumn column, ColumnSemanticsUpdateDto updateDto) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; + TableColumn update(TableColumn column, ColumnSemanticsUpdateDto updateDto) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException; TableColumn findColumnById(Table table, Long columnId) throws MalformedException; - void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, ServiceException, ServiceConnectionException; + void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, DataServiceException, DataServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java index d19a3be73beab67d160e09dc892f2a0c46faaee1..a090ece3cb1182f23e37fcf3ba6821ab6254bd02 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -33,7 +33,7 @@ public interface ViewService { * * @param view The view. */ - void delete(View view) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, + void delete(View view) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException; /** @@ -44,6 +44,6 @@ public interface ViewService { * @param data The given query. * @return The view that was created. */ - View create(Database database, User user, ViewCreateDto data) throws MalformedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; + View create(Database database, User user, ViewCreateDto data) throws MalformedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java index e1e6924e76a0f5f32e0fae9e91544ed0a2223c7c..aaa50251c3dc0dd79e51af1c983bfda07affffaa 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java @@ -62,8 +62,8 @@ public class AccessServiceImpl implements AccessService { @Override @Transactional - public DatabaseAccess create(Database database, User user, AccessTypeDto type) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + public DatabaseAccess create(Database database, User user, AccessTypeDto type) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* create in data database */ dataServiceGateway.createAccess(database.getId(), user.getId(), type); @@ -85,8 +85,8 @@ public class AccessServiceImpl implements AccessService { @Override @Transactional - public void update(Database database, User user, AccessTypeDto access) throws ServiceException, - ServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, + public void update(Database database, User user, AccessTypeDto access) throws DataServiceException, + DataServiceConnectionException, AccessNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* update in data database */ dataServiceGateway.updateAccess(database.getId(), user.getId(), access); @@ -112,8 +112,8 @@ public class AccessServiceImpl implements AccessService { @Override @Transactional - public void delete(Database database, User user) throws AccessNotFoundException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + public void delete(Database database, User user) throws AccessNotFoundException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete in data database */ dataServiceGateway.deleteAccess(database.getId(), user.getId()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java index c0ce71c996dbff1ca4cd943261b9954f035f6e3e..2800c96bc9d376e14cb990edb4d8fe5f9cc5d3a3 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/BrokerServiceRabbitMqImpl.java @@ -27,7 +27,7 @@ public class BrokerServiceRabbitMqImpl implements BrokerService { } @Override - public void setVirtualHostPermissions(User user) throws ServiceException, ServiceConnectionException { + public void setVirtualHostPermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException { final GrantVirtualHostPermissionsDto permissions = GrantVirtualHostPermissionsDto.builder() .configure("") .write(".*") @@ -39,7 +39,7 @@ public class BrokerServiceRabbitMqImpl implements BrokerService { @Override @Transactional(readOnly = true) - public void setTopicExchangePermissions(User user) throws ServiceException, ServiceConnectionException { + public void setTopicExchangePermissions(User user) throws BrokerServiceException, BrokerServiceConnectionException { final GrantExchangePermissionsDto permissions = GrantExchangePermissionsDto.builder() .exchange(rabbitConfig.getExchangeName()) .write(userToExchangeWritePermissionString(user)) diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java index 87f178b1c0d7e0d0bdf4c2be9e883a1a56b26861..ed58148707440f4dc20728fafbbc19ad3fd06594 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java @@ -13,6 +13,7 @@ import at.tuwien.config.DataCiteConfig; import at.tuwien.config.EndpointConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.identifier.Identifier; +import at.tuwien.entities.identifier.IdentifierStatusType; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; @@ -69,9 +70,10 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional - public Identifier publish(Long identifierId) throws MalformedException, ServiceConnectionException, - IdentifierNotFoundException { + public Identifier publish(Long identifierId) throws MalformedException, DataServiceConnectionException, + IdentifierNotFoundException, ExternalServiceException { final Identifier identifier = find(identifierId); + identifier.setStatus(IdentifierStatusType.PUBLISHED); identifier.setDoi(remoteSave(identifier, DataCiteDoiEvent.PUBLISH)); return identifierRepository.save(identifier); } @@ -94,19 +96,20 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional(rollbackFor = {Exception.class}) - public Identifier save(Database database, User user, IdentifierSaveDto data) throws ServiceException, - ServiceConnectionException, MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, - ViewNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + public Identifier save(Database database, User user, IdentifierSaveDto data) throws DataServiceException, + DataServiceConnectionException, MalformedException, DatabaseNotFoundException, IdentifierNotFoundException, + ViewNotFoundException, QueryNotFoundException, SearchServiceException, SearchServiceConnectionException, + ExternalServiceException { data.setDoi(remoteSave(identifierService.save(database, user, data), DataCiteDoiEvent.REGISTER)); return identifierService.save(database, user, data); } @Override @Transactional(rollbackFor = {Exception.class}) - public Identifier create(Database database, User user, IdentifierCreateDto data) throws ServiceException, - ServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, + public Identifier create(Database database, User user, IdentifierCreateDto data) throws DataServiceException, + DataServiceConnectionException, IdentifierNotFoundException, MalformedException, ViewNotFoundException, DatabaseNotFoundException, QueryNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, ExternalServiceException { data.setDoi(remoteSave(identifierService.create(database, user, data), DataCiteDoiEvent.REGISTER)); return identifierService.create(database, user, data); } @@ -118,14 +121,15 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { * @param event The PID status event, e.g. publish * @return The DOI for this PID. * @throws MalformedException - * @throws ServiceConnectionException + * @throws DataServiceConnectionException + * @throws ExternalServiceException */ public String remoteSave(Identifier identifier, DataCiteDoiEvent event) throws MalformedException, - ServiceConnectionException { + DataServiceConnectionException, ExternalServiceException { final HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBasicAuth(dataCiteConfig.getUsername(), dataCiteConfig.getPassword()); - HttpEntity<DataCiteBody<DataCiteCreateDoi>> request = new HttpEntity<>( + final HttpEntity<DataCiteBody<DataCiteCreateDoi>> request = new HttpEntity<>( DataCiteBody.<DataCiteCreateDoi>builder() .data(DataCiteData.<DataCiteCreateDoi>builder() .type("dois") @@ -139,11 +143,11 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { final String url = dataCiteConfig.getUrl() + "/dois"; log.trace("request doi from url {}", url); try { - ResponseEntity<DataCiteBody<DataCiteDoi>> response = restTemplate.exchange(url, HttpMethod.POST, + final ResponseEntity<DataCiteBody<DataCiteDoi>> response = restTemplate.exchange(url, HttpMethod.POST, request, dataCiteBodyParameterizedTypeReference); if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null) { log.error("Failed to mint doi: {}", response); - throw new ServiceException("Failed to mint doi: " + response.getBody()); + throw new ExternalServiceException("Failed to mint doi: " + response.getBody()); } return response.getBody() .getData() @@ -154,9 +158,7 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { throw new MalformedException("Failed to mint doi: malformed metadata: " + e.getMessage(), e); } catch (RestClientException e) { log.error("Failed to mint doi: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to mint doi: " + e.getMessage(), e); - } catch (ServiceException e) { - throw new RuntimeException(e); + throw new DataServiceConnectionException("Failed to mint doi: " + e.getMessage(), e); } } @@ -196,14 +198,14 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional(readOnly = true) - public InputStreamResource exportResource(Identifier identifier) throws ServiceException, - ServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException { + public InputStreamResource exportResource(Identifier identifier) throws DataServiceException, + DataServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException { return identifierService.exportResource(identifier); } @Override @Transactional - public void delete(Identifier identifier) throws ServiceException, ServiceConnectionException, + public void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, SearchServiceConnectionException { identifierService.delete(identifier); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java index f42992781c36e438233dd1d376c17d631ac7f584..8c835864db5ed4bf69bd2bd6b29adfe4d409899d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -62,6 +62,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Override public Database findByInternalName(String internalName) throws DatabaseNotFoundException { + log.trace("find database by internal name: {}", internalName); final Optional<Database> database = databaseRepository.findByInternalName(internalName); if (database.isEmpty()) { log.error("Failed to find database with internal name {} in metadata database", internalName); @@ -84,7 +85,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Override @Transactional public Database create(DatabaseCreateDto data, User user) throws UserNotFoundException, - ContainerNotFoundException, ServiceException, ServiceConnectionException, DatabaseNotFoundException, + ContainerNotFoundException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { final Container container = containerService.find(data.getCid()); Database database = Database.builder() @@ -135,7 +136,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Override @Transactional(readOnly = true) - public void updatePassword(Database database, User user) throws ServiceException, ServiceConnectionException, + public void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException { final List<Database> databases = databaseRepository.findReadAccess(user.getId()) .stream() @@ -190,10 +191,10 @@ public class DatabaseServiceImpl implements DatabaseService { } @Override - @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) - public Database updateTableMetadata(Database database) throws DatabaseNotFoundException, ServiceException, - SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - ServiceConnectionException, MalformedException { + @Transactional(rollbackFor = {Exception.class}) + public Database updateTableMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, + SearchServiceException, SearchServiceConnectionException, DataServiceConnectionException, + MalformedException, TableNotFoundException { for (TableDto table : dataServiceGateway.getTableSchemas(database.getId())) { if (database.getTables().stream().anyMatch(t -> t.getInternalName().equals(table.getInternalName()))) { log.debug("fetched known table from data service: {}.{}", database.getInternalName(), table.getInternalName()); @@ -296,10 +297,10 @@ public class DatabaseServiceImpl implements DatabaseService { } @Override - @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) - public Database updateViewMetadata(Database database) throws DatabaseNotFoundException, ServiceException, - SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, - ServiceConnectionException { + @Transactional(rollbackFor = {Exception.class}) + public Database updateViewMetadata(Database database) throws DatabaseNotFoundException, DataServiceException, + SearchServiceException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { for (ViewDto view : dataServiceGateway.getViewSchemas(database.getId())) { if (database.getViews().stream().anyMatch(v -> v.getInternalName().equals(view.getInternalName()))) { log.debug("fetched known view from data service: {}.{}", database.getInternalName(), view.getInternalName()); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java index 37215d0787d6532eb03d8bf3ebdd8557f28d83e0..df0f895f5d2d3512444b2d3e10e28e14a70e2c45 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java @@ -155,7 +155,7 @@ public class IdentifierServiceImpl implements IdentifierService { @Override @Transactional public Identifier save(Database database, User user, IdentifierSaveDto data) throws SearchServiceException, - ServiceException, QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, + DataServiceException, QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { final Identifier identifier = find(data.getId()); identifier.setDatabase(database); @@ -223,7 +223,7 @@ public class IdentifierServiceImpl implements IdentifierService { @Override @Transactional public Identifier create(Database database, User user, IdentifierCreateDto data) throws SearchServiceException, - ServiceException, QueryNotFoundException, ServiceConnectionException, DatabaseNotFoundException, + DataServiceException, QueryNotFoundException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { final Identifier identifier = metadataMapper.identifierCreateDtoToIdentifier(data); identifier.setDatabase(database); @@ -276,9 +276,9 @@ public class IdentifierServiceImpl implements IdentifierService { } @Transactional - public Identifier save(Identifier identifier) throws ServiceException, - ServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException, DatabaseNotFoundException, - QueryNotFoundException, SearchServiceException, SearchServiceConnectionException { + public Identifier save(Identifier identifier) throws DataServiceException, DataServiceConnectionException, + IdentifierNotFoundException, ViewNotFoundException, DatabaseNotFoundException, QueryNotFoundException, + SearchServiceException, SearchServiceConnectionException { /* save identifier */ switch (identifier.getType()) { case SUBSET -> { @@ -356,15 +356,15 @@ public class IdentifierServiceImpl implements IdentifierService { @Override @Transactional(readOnly = true) - public InputStreamResource exportResource(Identifier identifier) throws ServiceException, - ServiceConnectionException, QueryNotFoundException { + public InputStreamResource exportResource(Identifier identifier) throws DataServiceException, + DataServiceConnectionException, QueryNotFoundException { final ExportResourceDto exportResource = dataServiceGateway.exportQuery(identifier.getDatabase().getId(), identifier.getQueryId()); return exportResource.getResource(); } @Override @Transactional - public void delete(Identifier identifier) throws ServiceException, ServiceConnectionException, + public void delete(Identifier identifier) throws DataServiceException, DataServiceConnectionException, IdentifierNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete in metadata database */ diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java index 40eab251c9712c30ba960f9d1fbe3b8ca1f72c79..9ad86b7f905c75a174d5cf031c2f666f460e16d8 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/StorageServiceS3Impl.java @@ -29,6 +29,7 @@ public class StorageServiceS3Impl implements StorageService { @Override public InputStream getObject(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException { + log.trace("get object with key {} from bucket {}", key, bucket); try { return s3Client.getObject(GetObjectRequest.builder() .bucket(bucket) @@ -45,11 +46,13 @@ public class StorageServiceS3Impl implements StorageService { @Override public byte[] getBytes(String key) throws StorageNotFoundException, StorageUnavailableException { + log.trace("get bytes with key {} from bucket {}", key, s3Config.getS3ImportBucket()); return getBytes(s3Config.getS3ImportBucket(), key); } @Override public byte[] getBytes(String bucket, String key) throws StorageNotFoundException, StorageUnavailableException { + log.trace("get bytes with key {} from bucket {}", key, bucket); try { return getObject(bucket, key) .readAllBytes(); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 593b612a9c36162abc5d97f1fb95ea11cbce7078..46a0602c74dd4c93cf5ef05c4ad0c51116be0cf6 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -95,9 +95,10 @@ public class TableServiceImpl implements TableService { @Override @Transactional - public Table createTable(Database database, TableCreateDto data, Principal principal) throws ServiceException, - ServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, - TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException { + public Table createTable(Database database, TableCreateDto data, Principal principal) throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, + TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, + OntologyNotFoundException, SemanticEntityNotFoundException { final User owner = userService.findByUsername(principal.getName()); /* check */ if (data.getConstraints().getPrimaryKey().isEmpty()) { @@ -217,7 +218,7 @@ public class TableServiceImpl implements TableService { @Override @Transactional - public void deleteTable(Table table) throws ServiceException, ServiceConnectionException, + public void deleteTable(Table table) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete at data service */ @@ -232,8 +233,8 @@ public class TableServiceImpl implements TableService { @Override @Transactional - public TableColumn update(TableColumn column, ColumnSemanticsUpdateDto data) throws ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + public TableColumn update(TableColumn column, ColumnSemanticsUpdateDto data) throws DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException { /* assign */ @@ -288,7 +289,7 @@ public class TableServiceImpl implements TableService { @Transactional public void updateStatistics(Table table) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, - ServiceException, ServiceConnectionException { + DataServiceException, DataServiceConnectionException { final TableStatisticDto statistic = dataServiceGateway.getTableStatistics(table.getTdbid(), table.getId()); table.setNumRows(statistic.getRows()); for (Map.Entry<String, ColumnStatisticDto> entry : statistic.getColumns().entrySet()) { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java index a91e03284403b63453f129467f6ce7adaf7c0f90..0826d9dcc88e344227f56550b2aebd6f42e3494e 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java @@ -70,7 +70,7 @@ public class ViewServiceImpl implements ViewService { @Override @Transactional - public void delete(View view) throws ServiceException, ServiceConnectionException, DatabaseNotFoundException, + public void delete(View view) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException { /* delete in data service */ dataServiceGateway.deleteView(view.getDatabase().getId(), view.getId()); @@ -84,8 +84,8 @@ public class ViewServiceImpl implements ViewService { @Override @Transactional - public View create(Database database, User creator, ViewCreateDto data) throws MalformedException, ServiceException, - ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { + public View create(Database database, User creator, ViewCreateDto data) throws MalformedException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { /* create in metadata database */ final View view = View.builder() .vdbid(database.getId()) diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/utils/FileUtil.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/utils/FileUtil.java deleted file mode 100644 index 6e8b749c5f0a4a6d2720b003d2e5561584f4e9fe..0000000000000000000000000000000000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/utils/FileUtil.java +++ /dev/null @@ -1,38 +0,0 @@ -package at.tuwien.utils; - -import lombok.extern.log4j.Log4j2; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.LinkedList; -import java.util.List; - -@Log4j2 -public class FileUtil { - - /** - * Loads a resource from the resource path when the application is compiled into a .jar and during runtime. - * - * @param resourcePath The path to the resource. - * @return The text contents of the resource. - * @throws IOException The resource could not be loaded. - */ - public static List<String> loadResource(String resourcePath) throws IOException { - final InputStream inputStream = FileUtil.class.getResourceAsStream(resourcePath); - if (inputStream == null) { - log.error("Failed to load query store input stream file {}", resourcePath); - throw new IOException("Failed to load query store input stream file"); - } - final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - final List<String> lines = new LinkedList<>(); - while(reader.ready()) { - lines.add(reader.readLine()); - } - inputStream.close(); - reader.close(); - return lines; - } - -} 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 4a8a66f729b06ac2c5287a48dccd42d9769c4acf..173a3ba9f41ce3d617b99f996d0c4bc0c482a5e3 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 @@ -1,5 +1,6 @@ package at.tuwien.test; +import at.tuwien.ExportResourceDto; import at.tuwien.api.amqp.*; import at.tuwien.api.auth.LoginRequestDto; import at.tuwien.api.auth.SignupRequestDto; @@ -75,6 +76,7 @@ import at.tuwien.entities.user.User; import at.tuwien.test.utils.ArrayUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.core.io.InputStreamResource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -82,6 +84,7 @@ import org.springframework.security.core.userdetails.UserDetails; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; @@ -453,6 +456,14 @@ public abstract class BaseTest { .credentials(List.of(USER_1_KEYCLOAK_CREDENTIAL_1)) .build(); + public final static UserCreateDto USER_1_KEYCLOAK_SYSTEM_SIGNUP_REQUEST = UserCreateDto.builder() + .username(USER_1_USERNAME) + .email(USER_1_EMAIL) + .enabled(USER_1_ENABLED) + .credentials(List.of(USER_1_KEYCLOAK_CREDENTIAL_1)) + .groups(List.of("system")) + .build(); + public final static PrivilegedUserDto USER_1_PRIVILEGED_DTO = PrivilegedUserDto.builder() .id(USER_1_ID) .username(USER_1_USERNAME) @@ -4145,7 +4156,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(64L) + .id(65L) .ordinalPosition(20) .table(TABLE_5) .name("Class Type") @@ -4376,7 +4387,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(64L) + .id(65L) .ordinalPosition(20) .tableId(TABLE_5_ID) .table(TABLE_5_DTO) @@ -4525,7 +4536,7 @@ public abstract class BaseTest { .build(); public final static List<TableColumn> TABLE_6_COLUMNS = List.of(TableColumn.builder() - .id(66L) + .id(67L) .ordinalPosition(0) .table(TABLE_6) .name("id") @@ -4535,7 +4546,7 @@ public abstract class BaseTest { .autoGenerated(true) .build(), TableColumn.builder() - .id(67L) + .id(68L) .ordinalPosition(1) .table(TABLE_6) .name("firstname") @@ -4545,7 +4556,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(68L) + .id(69L) .ordinalPosition(2) .table(TABLE_6) .name("lastname") @@ -4555,7 +4566,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(69L) + .id(70L) .ordinalPosition(3) .table(TABLE_6) .name("birth") @@ -4565,7 +4576,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(70L) + .id(71L) .ordinalPosition(4) .table(TABLE_6) .name("reminder") @@ -4576,7 +4587,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(71L) + .id(72L) .ordinalPosition(5) .table(TABLE_6) .name("ref_id") @@ -4594,7 +4605,7 @@ public abstract class BaseTest { .build(); public final static List<ColumnDto> TABLE_6_COLUMNS_DTO = List.of(ColumnDto.builder() - .id(66L) + .id(67L) .ordinalPosition(0) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4605,7 +4616,7 @@ public abstract class BaseTest { .autoGenerated(true) .build(), ColumnDto.builder() - .id(67L) + .id(68L) .ordinalPosition(1) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4616,7 +4627,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(68L) + .id(69L) .ordinalPosition(2) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4627,7 +4638,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(69L) + .id(70L) .ordinalPosition(3) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4638,7 +4649,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(70L) + .id(71L) .ordinalPosition(4) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4650,7 +4661,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(71L) + .id(72L) .ordinalPosition(5) .tableId(TABLE_6_ID) .table(TABLE_6_DTO) @@ -4714,7 +4725,7 @@ public abstract class BaseTest { .build(); public final static List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() - .id(26L) + .id(74L) .ordinalPosition(0) .table(TABLE_7) .name("name_id") @@ -4724,7 +4735,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), TableColumn.builder() - .id(27L) + .id(75L) .ordinalPosition(1) .table(TABLE_7) .name("zoo_id") @@ -4735,7 +4746,7 @@ public abstract class BaseTest { .build()); public final static List<ColumnDto> TABLE_7_COLUMNS_DTO = List.of(ColumnDto.builder() - .id(26L) + .id(74L) .ordinalPosition(0) .tableId(TABLE_7_ID) .table(TABLE_7_DTO) @@ -4746,7 +4757,7 @@ public abstract class BaseTest { .autoGenerated(false) .build(), ColumnDto.builder() - .id(27L) + .id(75L) .ordinalPosition(1) .tableId(TABLE_7_ID) .table(TABLE_7_DTO) @@ -5762,6 +5773,7 @@ public abstract class BaseTest { .build(); public final static IdentifierSaveDescriptionDto IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO = IdentifierSaveDescriptionDto.builder() + .id(null) .description(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION) .descriptionType(IDENTIFIER_1_DESCRIPTION_1_TYPE_DTO) .language(IDENTIFIER_1_DESCRIPTION_1_LANG_DTO) @@ -5807,6 +5819,7 @@ public abstract class BaseTest { .build(); public final static CreatorSaveDto IDENTIFIER_1_CREATOR_1_CREATE_DTO = CreatorSaveDto.builder() + .id(null) .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) .creatorName(IDENTIFIER_1_CREATOR_1_NAME) @@ -5990,6 +6003,7 @@ public abstract class BaseTest { .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publisher(IDENTIFIER_1_PUBLISHER) .type(IDENTIFIER_1_TYPE_DTO) + .doi(IDENTIFIER_1_DOI) .licenses(List.of(LICENSE_1_DTO)) .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) .funders(List.of(IDENTIFIER_1_FUNDER_1_CREATE_DTO)) @@ -6116,6 +6130,7 @@ public abstract class BaseTest { .build(); public final static IdentifierSaveDescriptionDto IDENTIFIER_5_DESCRIPTION_1_CREATE_DTO = IdentifierSaveDescriptionDto.builder() + .id(null) .description(IDENTIFIER_5_DESCRIPTION_1_DESCRIPTION) .language(IDENTIFIER_5_DESCRIPTION_1_LANG_DTO) .descriptionType(IDENTIFIER_5_DESCRIPTION_1_TYPE_DTO) @@ -6375,6 +6390,7 @@ public abstract class BaseTest { .build(); public final static IdentifierSaveDescriptionDto IDENTIFIER_6_DESCRIPTION_1_CREATE_DTO = IdentifierSaveDescriptionDto.builder() + .id(null) .description(IDENTIFIER_6_DESCRIPTION_1_DESCRIPTION_MODIFY) .language(IDENTIFIER_6_DESCRIPTION_1_LANG_DTO) .build(); @@ -6562,6 +6578,15 @@ public abstract class BaseTest { public final static IdentifierStatusType IDENTIFIER_7_STATUS_TYPE = IdentifierStatusType.DRAFT; public final static IdentifierStatusTypeDto IDENTIFIER_7_STATUS_TYPE_DTO = IdentifierStatusTypeDto.DRAFT; + public final static DataCiteBody<DataCiteDoi> IDENTIFIER_7_DATA_CITE = DataCiteBody.<DataCiteDoi>builder() + .data(DataCiteData.<DataCiteDoi>builder() + .type("dois") + .attributes(DataCiteDoi.builder() + .doi(IDENTIFIER_7_DOI) + .build()) + .build()) + .build(); + private final static Long IDENTIFIER_7_CREATOR_1_ID = 6L; public final static Creator IDENTIFIER_7_CREATOR_1 = Creator.builder() @@ -7823,6 +7848,11 @@ public abstract class BaseTest { .build()))) .build(); + public final static ExportResourceDto EXPORT_RESOURCE_DTO = ExportResourceDto.builder() + .filename("68b329da9893e34099c7d8ad5cb9c940") + .resource(new InputStreamResource(InputStream.nullInputStream())) + .build(); + public static void saveObservedMetrics(Map<String, String> observedMetrics) throws IOException { final int keySize = observedMetrics.keySet().stream().max(Comparator.comparingInt(String::length)).get().length(); final int valueSize = observedMetrics.values().stream().max(Comparator.comparingInt(String::length)).get().length(); diff --git a/dbrepo-search-service/app.py b/dbrepo-search-service/app.py index 47f1f0254caa7bc0f2446faffd9af98dd9630a45..9b2aba7f0294cb5eebd006ea58d89fa4201a3b79 100644 --- a/dbrepo-search-service/app.py +++ b/dbrepo-search-service/app.py @@ -199,8 +199,6 @@ app.config["JWT_PUBKEY"] = '-----BEGIN PUBLIC KEY-----\n' + os.getenv("JWT_PUBKE app.config["AUTH_SERVICE_ENDPOINT"] = os.getenv("AUTH_SERVICE_ENDPOINT", "http://localhost/api/auth") app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-client") app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG") -app.config["ADMIN_USERNAME"] = os.getenv('ADMIN_USERNAME', 'admin') -app.config["ADMIN_PASSWORD"] = os.getenv('ADMIN_PASSWORD', 'admin') app.config["OPENSEARCH_HOST"] = os.getenv('OPENSEARCH_HOST', 'localhost') app.config["OPENSEARCH_PORT"] = os.getenv('OPENSEARCH_PORT', '9200') app.config["OPENSEARCH_USERNAME"] = os.getenv('OPENSEARCH_USERNAME', 'admin') @@ -227,8 +225,6 @@ def verify_token(token: str): def verify_password(username: str, password: str) -> Any: if username is None or username == "" or password is None or password == "": return False - if username == app.config["ADMIN_USERNAME"] and password == app.config["ADMIN_PASSWORD"]: - return User(username=username, roles=["admin"]) client = KeycloakClient() try: return client.verify_jwt(access_token=client.obtain_user_token(username=username, password=password)) @@ -374,7 +370,7 @@ def post_general_search(type): if t1 is not None and t2 is not None and "unit.uri" in req_body and "concept.uri" in req_body: response = OpenSearchClient().unit_independent_search(t1, t2, req_body) else: - response = OpenSearchClient().general_search(type, t1, t2, req_body) + response = OpenSearchClient().general_search(type, req_body) # filter by type if type == 'table': tmp = [] @@ -431,7 +427,7 @@ def post_general_search(type): @app.route("/api/search/database/<int:database_id>", methods=["PUT"], endpoint="search_put_database") @metrics.gauge(name='dbrepo_search_update_database', description='Time needed to update a database in the search database') -@auth.login_required(role=['admin']) +@auth.login_required(role=['update-search-index']) def update_database(database_id: int) -> Database | ApiError: logging.debug(f"updating database with id: {database_id}") try: diff --git a/dbrepo-search-service/clients/opensearch_client.py b/dbrepo-search-service/clients/opensearch_client.py index 0af31277932407df47a513ee498d4e356ba8364c..623da7c2a07ffa220e3555a41cebf25bfea67a02 100644 --- a/dbrepo-search-service/clients/opensearch_client.py +++ b/dbrepo-search-service/clients/opensearch_client.py @@ -171,91 +171,38 @@ class OpenSearchClient: logging.info(f"Found {len(response['hits']['hits'])} result(s)") return response - def general_search(self, type=None, t1=None, t2=None, field_value_pairs=None): + def general_search(self, type: str = None, field_value_pairs: dict = None): """ Main method for searching stuff in the opensearch db all parameters are optional :param type: The index to be searched. Optional. - :param t1: The start range value. Optional. - :param t2: The end range value. Optional. :param field_value_pairs: The key-value pair of properties that need to match. Optional. :return: The object of results and HTTP status code. e.g. { "hits": { "hits": [] } }, 200 """ musts = [] if field_value_pairs is not None and len(field_value_pairs) > 0: logging.debug(f'field_value_pairs present: {field_value_pairs}') - is_range_open_end = False - is_range_open_begin = False - is_range_query = False - if t1 is not None and t2 is None: - is_range_open_begin = True - logging.debug(f"query has only start value {t1} present") - if t1 is None and t2 is not None: - is_range_open_end = True - logging.debug(f"query has only end value {t2} present") - if t1 is not None and t2 is not None: - is_range_query = True - logging.debug(f"query has start value {t1} and end value {t2} present") for key, value in field_value_pairs.items(): if field_value_pairs[key] == None: logging.debug(f"skip empty key: {key}") continue logging.debug(f"processing key: {key}") - if is_range_open_end and re.match(f"unit\.", key): - logging.debug(f"omit key={key} because query type=open end range and key is somewhat unit") - logging.info(f"add match-query for range ),{t2}]") + if '.' in key: + logging.debug(f'key {key} is nested: use nested query') musts.append({ - "range": { - "val_max": { - "lte": t2 - } - } - }) - elif is_range_open_begin and re.match(f"unit\.", key): - logging.debug(f"omit key={key} because query type=open begin range and key is somewhat unit") - logging.info(f"add match-query for range [{t1},(") - musts.append({ - "range": { - "val_min": { - "gte": t1 - } - } - }) - elif is_range_query and re.match(f"unit\.", key): - logging.debug( - f"omit key={key} because query type=full range and key is somewhat unit") - logging.info(f"add match-query for range [{t1},{t2}]") - musts.append({ - "range": { - "val_min": { - "gte": t1 - } + "match": { + key: value } }) + else: + logging.debug(f'key {key} is flat: use bool query') musts.append({ - "range": { - "val_max": { - "lte": t2 - } + "match": { + key: {"query": value, "minimum_should_match": "90%"} } }) - else: - if '.' in key: - logging.debug(f'key {key} is nested: use nested query') - musts.append({ - "match": { - key: value - } - }) - else: - logging.debug(f'key {key} is flat: use bool query') - musts.append({ - "match": { - key: {"query": value, "minimum_should_match": "90%"} - } - }) body = { "query": {"bool": {"must": musts}} } @@ -290,7 +237,7 @@ class OpenSearchClient: } } response = self._instance().search( - index="column", + index="database", body=dumps(body) ) unit_uris = [hit["key"] for hit in response["aggregations"]["units"]["buckets"]] diff --git a/dbrepo-search-service/test/test_opensearch_client.py b/dbrepo-search-service/test/test_opensearch_client.py index 906aae0ccc0862703abc740622d793ed8388192b..7fe079d0f9e9d3dadb9e8189f0bcf39f16f0dc80 100644 --- a/dbrepo-search-service/test/test_opensearch_client.py +++ b/dbrepo-search-service/test/test_opensearch_client.py @@ -3,49 +3,77 @@ import unittest import opensearchpy from dbrepo.api.dto import Database, User, UserAttributes, Container, Image, Table, Column, ColumnType, Constraints, \ - PrimaryKey, TableMinimal, ColumnMinimal + PrimaryKey, TableMinimal, ColumnMinimal, Concept, Unit + from app import app from clients.opensearch_client import OpenSearchClient +req = Database(id=1, + name="Test", + internal_name="test_tuw1", + creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo", + attributes=UserAttributes(theme="dark")), + owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo", + attributes=UserAttributes(theme="dark")), + contact=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo", + attributes=UserAttributes(theme="dark")), + created=datetime.datetime(2024, 3, 25, 16, tzinfo=datetime.timezone.utc), + exchange_name="dbrepo", + is_public=True, + container=Container(id=1, + name="MariaDB", + internal_name="mariadb", + host="data-db", + port="3306", + created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), + sidecar_host="data-db-sidecar", + sidecar_port=3305, + image=Image(id=1, + registry="docker.io", + name="mariadb", + version="11.1.3", + dialect="org.hibernate.dialect.MariaDBDialect", + driver_class="org.mariadb.jdbc.Driver", + jdbc_method="mariadb", + default_port=3306)), + tables=[Table(id=1, database_id=1, name="Data", internal_name="data", + creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo", + attributes=UserAttributes(theme="dark")), + owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + username="foo", + attributes=UserAttributes(theme="dark")), + created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), + constraints=Constraints(uniques=[], foreign_keys=[], checks=[], primary_key=[]), + is_versioned=False, + created_by="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", + queue_name="dbrepo", + routing_key="dbrepo.1.1", + is_public=True, + columns=[Column(id=1, database_id=1, table_id=1, name="ID", internal_name="id", + auto_generated=True, column_type=ColumnType.BIGINT, is_public=True, + is_null_allowed=False, size=20, d=0, + concept=Concept(id=1, uri="http://www.wikidata.org/entity/Q2221906", + created=datetime.datetime(2024, 3, 1, 10, + tzinfo=datetime.timezone.utc)), + unit=Unit(id=1, + uri="http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius", + created=datetime.datetime(2024, 3, 1, 10, + tzinfo=datetime.timezone.utc)), + val_min=0, + val_max=10)] + )]) + class OpenSearchClientTest(unittest.TestCase): def test_update_database_succeeds(self): with app.app_context(): client = OpenSearchClient() - req = Database(id=1, - name="Test", - internal_name="test_tuw1", - creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - contact=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - created=datetime.datetime(2024, 3, 25, 16, tzinfo=datetime.timezone.utc), - exchange_name="dbrepo", - is_public=True, - container=Container(id=1, - name="MariaDB", - internal_name="mariadb", - host="data-db", - port="3306", - created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), - sidecar_host="data-db-sidecar", - sidecar_port=3305, - image=Image(id=1, - registry="docker.io", - name="mariadb", - version="11.1.3", - dialect="org.hibernate.dialect.MariaDBDialect", - driver_class="org.mariadb.jdbc.Driver", - jdbc_method="mariadb", - default_port=3306)), - tables=[]) # mock client.update_database(database_id=1, data=req) @@ -132,38 +160,6 @@ class OpenSearchClientTest(unittest.TestCase): def test_update_database_create_succeeds(self): with app.app_context(): client = OpenSearchClient() - req = Database(id=1, - name="Test", - internal_name="test_tuw1", - creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - contact=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - created=datetime.datetime(2024, 3, 25, 16, tzinfo=datetime.timezone.utc), - exchange_name="dbrepo", - is_public=True, - container=Container(id=1, - name="MariaDB", - internal_name="mariadb", - host="data-db", - port="3306", - created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), - sidecar_host="data-db-sidecar", - sidecar_port=3305, - image=Image(id=1, - registry="docker.io", - name="mariadb", - version="11.1.3", - dialect="org.hibernate.dialect.MariaDBDialect", - driver_class="org.mariadb.jdbc.Driver", - jdbc_method="mariadb", - default_port=3306)), - tables=[]) # test database = client.update_database(database_id=1, data=req) @@ -186,7 +182,18 @@ class OpenSearchClientTest(unittest.TestCase): # ... self.assertEqual(1, database.container.image.id) # ... - self.assertEqual(0, len(database.tables)) + self.assertEqual(1, len(database.tables)) + + def test_update_database_malformed_fails(self): + with app.app_context(): + app.config['OPENSEARCH_USERNAME'] = 'i_do_not_exist' + client = OpenSearchClient() + + # test + try: + database = client.update_database(database_id=1, data=req) + except opensearchpy.exceptions.TransportError: + pass def test_delete_database_fails(self): with app.app_context(): @@ -201,38 +208,6 @@ class OpenSearchClientTest(unittest.TestCase): def test_delete_database_succeeds(self): with app.app_context(): client = OpenSearchClient() - req = Database(id=1, - name="Test", - internal_name="test_tuw1", - creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - contact=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - created=datetime.datetime(2024, 3, 25, 16, 0, tzinfo=datetime.timezone.utc), - exchange_name="dbrepo", - is_public=True, - container=Container(id=1, - name="MariaDB", - internal_name="mariadb", - host="data-db", - port="3306", - created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), - sidecar_host="data-db-sidecar", - sidecar_port=3305, - image=Image(id=1, - registry="docker.io", - name="mariadb", - version="11.1.3", - dialect="org.hibernate.dialect.MariaDBDialect", - driver_class="org.mariadb.jdbc.Driver", - jdbc_method="mariadb", - default_port=3306)), - tables=[]) # mock client.update_database(database_id=req.id, data=req) @@ -243,38 +218,6 @@ class OpenSearchClientTest(unittest.TestCase): def test_find_database_succeeds(self): with app.app_context(): client = OpenSearchClient() - req = Database(id=1, - name="Test", - internal_name="test_tuw1", - creator=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - owner=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - contact=User(id="c6b71ef5-2d2f-48b2-9d79-b8f23a3a0502", - username="foo", - attributes=UserAttributes(theme="dark")), - created=datetime.datetime(2024, 3, 25, 16, tzinfo=datetime.timezone.utc), - exchange_name="dbrepo", - is_public=True, - container=Container(id=1, - name="MariaDB", - internal_name="mariadb", - host="data-db", - port="3306", - created=datetime.datetime(2024, 3, 1, 10, tzinfo=datetime.timezone.utc), - sidecar_host="data-db-sidecar", - sidecar_port=3305, - image=Image(id=1, - registry="docker.io", - name="mariadb", - version="11.1.3", - dialect="org.hibernate.dialect.MariaDBDialect", - driver_class="org.mariadb.jdbc.Driver", - jdbc_method="mariadb", - default_port=3306)), - tables=[]) # mock client.update_database(database_id=req.id, data=req) @@ -286,8 +229,83 @@ class OpenSearchClientTest(unittest.TestCase): with app.app_context(): client = OpenSearchClient() + # mock + client.update_database(database_id=1, data=req) + # test try: client.get_database(database_id=1) except opensearchpy.exceptions.NotFoundError: pass + + def test_query_index_by_term_opensearch_contains_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.query_index_by_term_opensearch(term="test", mode="contains") + self.assertEqual(1, len(response)) + self.assertEqual(1, response[0]['id']) + self.assertEqual('Test', response[0]['name']) + + def test_query_index_by_term_opensearch_exact_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.query_index_by_term_opensearch(term="test", mode="exact") + self.assertEqual(1, len(response)) + self.assertEqual(1, response[0]['id']) + self.assertEqual('Test', response[0]['name']) + + def test_get_fields_for_index_database_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.get_fields_for_index(type="database") + self.assertTrue(len(response) > 0) + + def test_get_fields_for_index_user_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.get_fields_for_index(type="user") + self.assertTrue(len(response) > 0) + + def test_fuzzy_search_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.fuzzy_search(search_term="test") + self.assertTrue(len(response) > 0) + + def test_general_search_succeeds(self): + with app.app_context(): + client = OpenSearchClient() + + # mock + client.update_database(database_id=1, data=req) + + # test + response = client.general_search(type="database", field_value_pairs={"name": "Test", + "id": None}) + self.assertTrue(len(response) > 0) + diff --git a/dbrepo-ui/Dockerfile b/dbrepo-ui/Dockerfile index 14f1e57c1ecdbe729040dd929b5842ced137e6b4..d7b63d8f89b577a05878eb591b40f171e9431e0e 100644 --- a/dbrepo-ui/Dockerfile +++ b/dbrepo-ui/Dockerfile @@ -1,10 +1,8 @@ -FROM oven/bun:1.0.26-alpine as build -MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> +FROM oven/bun:1.0.26-alpine AS build WORKDIR /app COPY ./package.json ./package.json -COPY ./bun.lockb ./bun.lockb RUN bun install @@ -27,7 +25,6 @@ COPY ./nuxt.config.ts ./nuxt.config.ts RUN bun run build FROM oven/bun:1.0.26-alpine as runtime -MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> ARG APP_VERSION="latest" ARG COMMIT="" @@ -36,7 +33,9 @@ USER 1000 WORKDIR /app -COPY --from=build --chown=1000:1000 /app/.output /app/.output +COPY --from=build --chown=1000 /app/.output /app/.output + +RUN chmod -R 755 /app/.output ENV NUXT_PUBLIC_VERSION="${APP_VERSION:-}" ENV NUXT_PUBLIC_COMMIT="${COMMIT:-}" diff --git a/dbrepo-ui/bun.lockb b/dbrepo-ui/bun.lockb deleted file mode 100755 index 2ae1649f86a2cfc2d75d6e45a0c9490ad434ae02..0000000000000000000000000000000000000000 Binary files a/dbrepo-ui/bun.lockb and /dev/null differ diff --git a/dbrepo-ui/locales/de-AT.json b/dbrepo-ui/locales/de-AT.json index 7c2b2a149f4cde28256e8a92410fd76527da4e96..e32fe38ee0f835e7bd9c000b1669e2de22d289be 100644 --- a/dbrepo-ui/locales/de-AT.json +++ b/dbrepo-ui/locales/de-AT.json @@ -1179,6 +1179,13 @@ "create": "Ansicht konnte nicht erstellt werden", "missing": "Die Ansicht konnte in der Metadatendatenbank nicht gefunden werden", "invalid": "Die Ansichtsabfrage konnte den Spalten im Datendienst nicht zugeordnet werden" + }, + "broker": { + "connection": "Es konnte keine Verbindung zum Vermittlungsdienst hergestellt werden", + "invalid": "Es konnten keine Metadaten im Metadatendienst abgerufen werden" + }, + "external": { + "invalid": "Metadaten konnten nicht aus dem Datacite-System abgerufen werden" } }, "success": { diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index c914fd774cc3d552d6a721563774447abad279d1..edf6c66ca15a752e442ed3c807c4cb3d31a7c8ff 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -1182,6 +1182,13 @@ "create": "Failed to create view", "missing": "Failed to find view in metadata database", "invalid": "Failed to map view query to columns in data service" + }, + "broker": { + "connection": "Failed to contact broker service", + "invalid": "Failed to obtain metadata in the broker service" + }, + "external": { + "invalid": "Failed to obtain metadata from the datacite system" } }, "success": { diff --git a/docker-compose.yml b/docker-compose.yml index 43c3fbbfb133fe87b0d1138d2d7cbce46750a3c6..b67e23fc62ca4aec283723ce2d5495b79ea59803 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,6 +39,7 @@ services: hostname: data-db image: docker.io/bitnami/mariadb:11.1.3-debian-11-r6 volumes: + - ./dbrepo-data-db/enable_history_insert.cnf:/opt/bitnami/mariadb/conf.default/enable_history_insert.cnf - "${SHARED_VOLUME:-/tmp}:/tmp" - data-db-data:/bitnami/mariadb ports: @@ -116,8 +117,6 @@ services: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: ADMIN_EMAIL: "${ADMIN_EMAIL:-noreply@localhost}" - ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" - ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" ANALYSE_SERVICE_ENDPOINT: "${ANALYSE_SERVICE_ENDPOINT:-http://gateway-service}" AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} @@ -152,6 +151,8 @@ services: S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" SPARQL_CONNECTION_TIMEOUT: "${SPARQL_CONNECTION_TIMEOUT:-10000}" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: test: curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1 interval: 10s @@ -180,8 +181,6 @@ services: ports: - "5000:8080" environment: - ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" - ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} @@ -265,8 +264,6 @@ services: ports: - "4000:8080" environment: - ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" - ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} @@ -382,8 +379,8 @@ services: environment: LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" - LDAP_USERS: "${ADMIN_USERNAME:-admin}" - LDAP_PASSWORDS: "${ADMIN_PASSWORD:-admin}" + LDAP_USERS: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" + LDAP_PASSWORDS: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" LDAP_GROUP: "${ADMIN_GROUP:-system}" LDAP_ROOT: "${IDENTITY_SERVICE_ROOT:-dc=dbrepo,dc=at}" LDAP_ADMIN_DN: "${IDENTITY_SERVICE_ADMIN_DN:-cn=admin,dc=dbrepo,dc=at}" @@ -486,8 +483,6 @@ services: volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: - ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" - ADMIN_USERNAME: "${ADMIN_USERNAME:-admin}" AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} @@ -519,6 +514,8 @@ services: S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}" S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}" S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: test: curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1 interval: 10s diff --git a/helm/dbrepo/Chart.yaml b/helm/dbrepo/Chart.yaml index 0e708f4669f6debdef8ee7df236c2654de8c832c..28ce12c838d2b92e5e6d383fa0309eea8d72d59f 100644 --- a/helm/dbrepo/Chart.yaml +++ b/helm/dbrepo/Chart.yaml @@ -4,13 +4,13 @@ description: Helm Chart for installing DBRepo sources: - https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services type: application -version: "1.4.4" -appVersion: "1.4.4" +version: "1.4.5" +appVersion: "1.4.5" keywords: - dbrepo maintainers: - name: Martin Weise - email: martin.weise@tuwien.ac.a + email: martin.weise@tuwien.ac.at home: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/ icon: https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/dbrepo-ui/public/favicon.png dependencies: diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index 48848c588c1698d2f578a0b39543ba6610d0bc4e..b310705b11665d8906a4093a2cc1ff73376527fd 100644 --- a/helm/dbrepo/README.md +++ b/helm/dbrepo/README.md @@ -45,6 +45,13 @@ The command removes all the Kubernetes components associated with the chart and ## Parameters +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + ### Common parameters | Name | Description | Value | @@ -137,67 +144,121 @@ The command removes all the Kubernetes components associated with the chart and ### Analyse Service -| Name | Description | Value | -| ----------------------------- | ----------------------------------------------------------- | ------------------------------- | -| `analyseservice.enabled` | Enable the Broker Service. | `true` | -| `analyseservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `analyseservice.endpoint` | The url of the endpoint. | `http://analyse-service` | -| `analyseservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | -| `analyseservice.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| ------------------------------------------------------------------ | ----------------------------------------------------------- | ------------------------------- | +| `analyseservice.enabled` | Enable the Broker Service. | `true` | +| `analyseservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `analyseservice.podSecurityContext.enabled` | Enable pods' Security Context | `true` | +| `analyseservice.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `analyseservice.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `analyseservice.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `analyseservice.podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `analyseservice.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `analyseservice.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `""` | +| `analyseservice.containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `analyseservice.containerSecurityContext.runAsGroup` | Set RabbitMQ containers' Security Context runAsGroup | `1001` | +| `analyseservice.containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `analyseservice.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `analyseservice.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `analyseservice.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `analyseservice.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `analyseservice.endpoint` | The url of the endpoint. | `http://analyse-service` | +| `analyseservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | +| `analyseservice.replicaCount` | The number of replicas. | `2` | ### Metadata Service -| Name | Description | Value | -| ------------------------------------------ | ---------------------------------------------------------------------------------- | ------------------------------- | -| `metadataservice.enabled` | Enable the Metadata Service. | `true` | -| `metadataservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `metadataservice.endpoint` | The Metadata Service endpoint. | `http://metadata-service` | -| `metadataservice.admin.email` | The OAI-PMH exposed e-mail for contacting the metadata records responsible person. | `noreply@example.com` | -| `metadataservice.deletedRecord` | The OAI-PMH exposed delete policy. | `permanent` | -| `metadataservice.repositoryName` | The OAI-PMH exposed repository name. | `Database Repository` | -| `metadataservice.granularity` | The OAI-PMH exposed record granularity. | `YYYY-MM-DDThh:mm:ssZ` | -| `metadataservice.datacite.enabled` | If set to true, the service mints DOIs instead of local PIDs. | `false` | -| `metadataservice.datacite.url` | The DataCite api endpoint url. | `https://api.datacite.org` | -| `metadataservice.datacite.prefix` | The DataCite prefix. | `""` | -| `metadataservice.datacite.username` | The DataCite api username. | `""` | -| `metadataservice.datacite.password` | The DataCite api user password. | `""` | -| `metadataservice.sparql.connectionTimeout` | The connection timeout for sparql queries fetching remote data in ms. | `10000` | -| `metadataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | -| `metadataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | -| `metadataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | -| `metadataservice.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------- | +| `metadataservice.enabled` | Enable the Broker Service. | `true` | +| `metadataservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `metadataservice.podSecurityContext.enabled` | Enable pods' Security Context | `true` | +| `metadataservice.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `metadataservice.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `metadataservice.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `metadataservice.podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `metadataservice.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `metadataservice.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `""` | +| `metadataservice.containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `metadataservice.containerSecurityContext.runAsGroup` | Set RabbitMQ containers' Security Context runAsGroup | `1001` | +| `metadataservice.containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `metadataservice.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `metadataservice.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `metadataservice.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `metadataservice.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `metadataservice.endpoint` | The Metadata Service endpoint. | `http://metadata-service` | +| `metadataservice.admin.email` | The OAI-PMH exposed e-mail for contacting the metadata records responsible person. | `noreply@example.com` | +| `metadataservice.deletedRecord` | The OAI-PMH exposed delete policy. | `permanent` | +| `metadataservice.repositoryName` | The OAI-PMH exposed repository name. | `Database Repository` | +| `metadataservice.granularity` | The OAI-PMH exposed record granularity. | `YYYY-MM-DDThh:mm:ssZ` | +| `metadataservice.datacite.enabled` | If set to true, the service mints DOIs instead of local PIDs. | `false` | +| `metadataservice.datacite.url` | The DataCite api endpoint url. | `https://api.datacite.org` | +| `metadataservice.datacite.prefix` | The DataCite prefix. | `""` | +| `metadataservice.datacite.username` | The DataCite api username. | `""` | +| `metadataservice.datacite.password` | The DataCite api user password. | `""` | +| `metadataservice.sparql.connectionTimeout` | The connection timeout for sparql queries fetching remote data in ms. | `10000` | +| `metadataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | +| `metadataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | +| `metadataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | +| `metadataservice.replicaCount` | The number of replicas. | `2` | ### Data Service -| Name | Description | Value | -| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | -| `dataservice.enabled` | Enable the Metadata Service. | `true` | -| `dataservice.endpoint` | The endpoint for the microservices. | `http://data-service` | -| `dataservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `dataservice.grant.read` | The default database permissions for users with read access. | `SELECT` | -| `dataservice.grant.write` | The default database permissions for users with write access. | `SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE` | -| `dataservice.default.date` | The default date format id for dates. Default: YYYY-MM-dd (e.g. 2024-06-15). | `3` | -| `dataservice.default.time` | The default date format id for times. Default: HH:mm:ss (e.g. 14:23:42). | `4` | -| `dataservice.default.timestamp` | The default date format id for timestamps. Default: YYYY-MM-dd HH:mm:ss (e.g. 2024-06-15 14:23:42). | `1` | -| `dataservice.rabbitmq.consumerConcurrentMin` | The minimal number of RabbitMQ consumers. | `2` | -| `dataservice.rabbitmq.consumerConcurrentMax` | The maximal number of RabbitMQ consumers. | `6` | -| `dataservice.rabbitmq.requeueRejected` | If set to true, rejected tuples will be re-queued. | `false` | -| `dataservice.rabbitmq.consumer.username` | The username for the consumer to read tuples from the broker service. In many cases this value is equal to `identityservice.users`. | `admin` | -| `dataservice.rabbitmq.consumer.password` | The user password for the consumer to read tuples from the broker service. In many cases this value is equal to `identityservice.userPasswords`. | `admin` | -| `dataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | -| `dataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | -| `dataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | -| `dataservice.s3.filePath` | The local location to download/upload files from/to S3-capable endpoint. | `/s3` | -| `dataservice.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| `dataservice.enabled` | Enable the Broker Service. | `true` | +| `dataservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `dataservice.podSecurityContext.enabled` | Enable pods' Security Context | `true` | +| `dataservice.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `dataservice.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `dataservice.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `dataservice.podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `dataservice.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `dataservice.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `""` | +| `dataservice.containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `dataservice.containerSecurityContext.runAsGroup` | Set RabbitMQ containers' Security Context runAsGroup | `1001` | +| `dataservice.containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `dataservice.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `dataservice.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `dataservice.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `dataservice.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `dataservice.grant.read` | The default database permissions for users with read access. | `SELECT` | +| `dataservice.grant.write` | The default database permissions for users with write access. | `SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE` | +| `dataservice.default.date` | The default date format id for dates. Default: YYYY-MM-dd (e.g. 2024-06-15). | `3` | +| `dataservice.default.time` | The default date format id for times. Default: HH:mm:ss (e.g. 14:23:42). | `4` | +| `dataservice.default.timestamp` | The default date format id for timestamps. Default: YYYY-MM-dd HH:mm:ss (e.g. 2024-06-15 14:23:42). | `1` | +| `dataservice.rabbitmq.consumerConcurrentMin` | The minimal number of RabbitMQ consumers. | `2` | +| `dataservice.rabbitmq.consumerConcurrentMax` | The maximal number of RabbitMQ consumers. | `6` | +| `dataservice.rabbitmq.requeueRejected` | If set to true, rejected tuples will be re-queued. | `false` | +| `dataservice.rabbitmq.consumer.username` | The username for the consumer to read tuples from the broker service. In many cases this value is equal to `identityservice.users`. | `admin` | +| `dataservice.rabbitmq.consumer.password` | The user password for the consumer to read tuples from the broker service. In many cases this value is equal to `identityservice.userPasswords`. | `admin` | +| `dataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | +| `dataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | +| `dataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | +| `dataservice.s3.filePath` | The local location to download/upload files from/to S3-capable endpoint. | `/s3` | +| `dataservice.replicaCount` | The number of replicas. | `2` | ### Search Service -| Name | Description | Value | -| ---------------------------- | ----------------------------------------------------------- | ----------------------- | -| `searchservice.enabled` | Enable the Search Service. | `true` | -| `searchservice.endpoint` | The endpoint for the microservices. | `http://search-service` | -| `searchservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `searchservice.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| ----------------------------------------------------------------- | ----------------------------------------------------------- | ---------------- | +| `searchservice.enabled` | Enable the Broker Service. | `true` | +| `searchservice.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `searchservice.podSecurityContext.enabled` | Enable pods' Security Context | `true` | +| `searchservice.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `searchservice.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `searchservice.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `searchservice.podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `searchservice.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `searchservice.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `""` | +| `searchservice.containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `searchservice.containerSecurityContext.runAsGroup` | Set RabbitMQ containers' Security Context runAsGroup | `1001` | +| `searchservice.containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `searchservice.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `searchservice.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `searchservice.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `searchservice.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `searchservice.replicaCount` | The number of replicas. | `2` | ### Storage Service @@ -222,25 +283,39 @@ The command removes all the Kubernetes components associated with the chart and ### User Interface -| Name | Description | Value | -| --------------------------------- | ---------------------------------------------------------------------------- | ----------------------- | -| `ui.enabled` | Enable the User Interface. | `true` | -| `ui.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `ui.public.api.client` | The endpoint for the client api. | `""` | -| `ui.public.api.server` | The endpoint for the server api. | `""` | -| `ui.public.title` | The user interface title. | `Database Repository` | -| `ui.public.logo` | The user interface logo. | `/logo.svg` | -| `ui.public.icon` | The user interface icon. | `/favicon.ico` | -| `ui.public.touch` | The user interface apple touch icon. | `/apple-touch-icon.png` | -| `ui.public.broker.host` | The displayed broker hostname. | `example.com` | -| `ui.public.broker.port.5671` | Enable display of the broker 5671 port and mark it as secure (SSL/TLS). | `true` | -| `ui.public.broker.port.5672` | Enable display of the broker 5672 port and mark it as insecure (no SSL/TLS). | `false` | -| `ui.public.broker.extra` | Extra metadata displayed. | `""` | -| `ui.public.database.extra` | Extra metadata displayed. | `128.130.0.0/15` | -| `ui.public.pid.default.publisher` | The default dataset publisher for persisted identifiers. | `Example University` | -| `ui.public.doi.enabled` | Enable the display that DOIs are minted. | `false` | -| `ui.public.doi.endpoint` | The DOI proxy. | `https://doi.org` | -| `ui.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| ------------------------------------------------------ | ---------------------------------------------------------------------------- | ----------------------- | +| `ui.enabled` | Enable the Broker Service. | `true` | +| `ui.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `ui.podSecurityContext.enabled` | Enable pods' Security Context | `true` | +| `ui.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `ui.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `ui.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `ui.podSecurityContext.fsGroup` | Set RabbitMQ pod's Security Context fsGroup | `1001` | +| `ui.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `ui.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `""` | +| `ui.containerSecurityContext.runAsUser` | Set RabbitMQ containers' Security Context runAsUser | `1001` | +| `ui.containerSecurityContext.runAsGroup` | Set RabbitMQ containers' Security Context runAsGroup | `1001` | +| `ui.containerSecurityContext.runAsNonRoot` | Set RabbitMQ container's Security Context runAsNonRoot | `true` | +| `ui.containerSecurityContext.allowPrivilegeEscalation` | Set container's privilege escalation | `false` | +| `ui.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` | +| `ui.containerSecurityContext.capabilities.drop` | Set container's Security Context runAsNonRoot | `["ALL"]` | +| `ui.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `ui.public.api.client` | The endpoint for the client api. | `""` | +| `ui.public.api.server` | The endpoint for the server api. | `""` | +| `ui.public.title` | The user interface title. | `Database Repository` | +| `ui.public.logo` | The user interface logo. | `/logo.svg` | +| `ui.public.icon` | The user interface icon. | `/favicon.ico` | +| `ui.public.touch` | The user interface apple touch icon. | `/apple-touch-icon.png` | +| `ui.public.broker.host` | The displayed broker hostname. | `example.com` | +| `ui.public.broker.port.5671` | Enable display of the broker 5671 port and mark it as secure (SSL/TLS). | `true` | +| `ui.public.broker.port.5672` | Enable display of the broker 5672 port and mark it as insecure (no SSL/TLS). | `false` | +| `ui.public.broker.extra` | Extra metadata displayed. | `""` | +| `ui.public.database.extra` | Extra metadata displayed. | `128.130.0.0/15` | +| `ui.public.pid.default.publisher` | The default dataset publisher for persisted identifiers. | `Example University` | +| `ui.public.doi.enabled` | Enable the display that DOIs are minted. | `false` | +| `ui.public.doi.endpoint` | The DOI proxy. | `https://doi.org` | +| `ui.replicaCount` | The number of replicas. | `2` | ### Ingress diff --git a/helm/dbrepo/templates/_compatibility.tpl b/helm/dbrepo/templates/_compatibility.tpl new file mode 100644 index 0000000000000000000000000000000000000000..6fc2aa8fa45e3bf7a8cfdb5312515aa2c27a0491 --- /dev/null +++ b/helm/dbrepo/templates/_compatibility.tpl @@ -0,0 +1,42 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" "seLinuxOptions" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} \ No newline at end of file diff --git a/helm/dbrepo/templates/analyse-deployment.yaml b/helm/dbrepo/templates/analyse-deployment.yaml index 0cdb067ef7218710509f5febdb900b611e6d9f45..68d43e9cee8cab5e4f2073c3e23965e87f9197fe 100644 --- a/helm/dbrepo/templates/analyse-deployment.yaml +++ b/helm/dbrepo/templates/analyse-deployment.yaml @@ -22,25 +22,16 @@ spec: app: analyse-service service: analyse-service spec: - securityContext: - runAsNonRoot: true - fsGroup: 1001 - runAsUser: 1001 - runAsGroup: 1001 + {{- if .Values.analyseservice.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.analyseservice.podSecurityContext "context" $) | nindent 8 }} + {{- end }} containers: - name: analyse-service image: {{ .Values.analyseservice.image.name }} imagePullPolicy: {{ .Values.analyseservice.image.pullPolicy | default "IfNotPresent" }} - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 1001 - runAsGroup: 1001 - seccompProfile: - type: {{ .Values.analyseservice.profileType | default "RuntimeDefault" }} - capabilities: - drop: - - ALL + {{- if .Values.analyseservice.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.analyseservice.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} ports: - containerPort: 8080 protocol: TCP @@ -63,4 +54,7 @@ spec: - "curl -sSL localhost:8080/health | grep 'UP' || exit 1" initialDelaySeconds: 10 periodSeconds: 30 + {{- if .Values.analyseservice.resources }} + resources: {{- toYaml .Values.analyseservice.resources | nindent 12 }} + {{- end }} {{- end }} diff --git a/helm/dbrepo/templates/data-deployment.yaml b/helm/dbrepo/templates/data-deployment.yaml index cb8fda09915c05f9556717ea8de3e5e7f174fd70..1d9e2352bd080702d61f94cf32915cba841293ad 100644 --- a/helm/dbrepo/templates/data-deployment.yaml +++ b/helm/dbrepo/templates/data-deployment.yaml @@ -22,25 +22,16 @@ spec: app: data-service service: data-service spec: - securityContext: - runAsNonRoot: true - fsGroup: 65534 - runAsUser: 65534 - runAsGroup: 65534 + {{- if .Values.dataservice.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.dataservice.podSecurityContext "context" $) | nindent 8 }} + {{- end }} containers: - name: data-service image: {{ .Values.dataservice.image.name }} imagePullPolicy: {{ .Values.dataservice.image.pullPolicy | default "IfNotPresent" }} - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 - seccompProfile: - type: {{ .Values.dataservice.profileType | default "RuntimeDefault" }} - capabilities: - drop: - - ALL + {{- if .Values.dataservice.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.dataservice.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} ports: - containerPort: 80 protocol: TCP @@ -63,6 +54,9 @@ spec: - "curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1" initialDelaySeconds: 30 periodSeconds: 30 + {{- if .Values.dataservice.resources }} + resources: {{- toYaml .Values.dataservice.resources | nindent 12 }} + {{- end }} volumeMounts: [] volumes: [] {{- end }} diff --git a/helm/dbrepo/templates/metadata-deployment.yaml b/helm/dbrepo/templates/metadata-deployment.yaml index 7c78f853e68b9be83e704f06ccf8340a2b13fd03..4d16efb68bc6987c71b551311d83a2bffe819be5 100644 --- a/helm/dbrepo/templates/metadata-deployment.yaml +++ b/helm/dbrepo/templates/metadata-deployment.yaml @@ -22,25 +22,16 @@ spec: app: metadata-service service: metadata-service spec: - securityContext: - runAsNonRoot: true - fsGroup: 65534 - runAsUser: 65534 - runAsGroup: 65534 + {{- if .Values.metadataservice.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metadataservice.podSecurityContext "context" $) | nindent 8 }} + {{- end }} containers: - name: metadata-service image: {{ .Values.metadataservice.image.name }} imagePullPolicy: {{ .Values.metadataservice.image.pullPolicy | default "IfNotPresent" }} - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 65534 - runAsGroup: 65534 - seccompProfile: - type: {{ .Values.metadataservice.profileType | default "RuntimeDefault" }} - capabilities: - drop: - - ALL + {{- if .Values.metadataservice.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.metadataservice.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} ports: - containerPort: 80 protocol: TCP @@ -63,4 +54,7 @@ spec: - "curl -sSL localhost:8080/actuator/health/liveness | grep 'UP' || exit 1" initialDelaySeconds: 30 periodSeconds: 30 + {{- if .Values.metadataservice.resources }} + resources: {{- toYaml .Values.metadataservice.resources | nindent 12 }} + {{- end }} {{- end }} diff --git a/helm/dbrepo/templates/search-deployment.yaml b/helm/dbrepo/templates/search-deployment.yaml index bd937c6650a4b4ec1f2d8fb57c886b753d1a3468..6ba54abfcab317ab3d1a93ebf7589cdcbbcd81c4 100644 --- a/helm/dbrepo/templates/search-deployment.yaml +++ b/helm/dbrepo/templates/search-deployment.yaml @@ -22,25 +22,16 @@ spec: app: search-service service: search-service spec: - securityContext: - runAsNonRoot: true - fsGroup: 1001 - runAsUser: 1001 - runAsGroup: 1001 + {{- if .Values.searchservice.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.searchservice.podSecurityContext "context" $) | nindent 8 }} + {{- end }} initContainers: - name: init image: {{ .Values.searchservice.init.image.name }} imagePullPolicy: {{ .Values.searchservice.init.image.pullPolicy | default "IfNotPresent" }} - securityContext: - allowPrivilegeEscalation: false - runAsNonRoot: true - runAsUser: 1001 - runAsGroup: 1001 - seccompProfile: - type: {{ .Values.searchservice.profileType | default "RuntimeDefault" }} - capabilities: - drop: - - ALL + {{- if .Values.searchservice.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.searchservice.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} envFrom: - secretRef: name: search-service-secret @@ -80,6 +71,9 @@ spec: - "curl -sSL localhost:8080/health | grep 'UP' || exit 1" initialDelaySeconds: 10 periodSeconds: 30 + {{- if .Values.searchservice.resources }} + resources: {{- toYaml .Values.searchservice.resources | nindent 12 }} + {{- end }} volumeMounts: [ ] volumes: [ ] {{- end }} diff --git a/helm/dbrepo/templates/ui-deployment.yaml b/helm/dbrepo/templates/ui-deployment.yaml index 3f8c042579af608e2bae1b3586088b06e1bc1baa..64cea9bf103dd3c66446ba353528b9ddb96b42a7 100644 --- a/helm/dbrepo/templates/ui-deployment.yaml +++ b/helm/dbrepo/templates/ui-deployment.yaml @@ -22,22 +22,16 @@ spec: app: ui service: ui spec: - securityContext: - runAsNonRoot: true - fsGroup: 1000 - runAsUser: 1000 - runAsGroup: 1000 + {{- if .Values.ui.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.ui.podSecurityContext "context" $) | nindent 8 }} + {{- end }} containers: - name: ui image: {{ .Values.ui.image.name }} imagePullPolicy: {{ .Values.ui.image.pullPolicy | default "IfNotPresent" }} - securityContext: - allowPrivilegeEscalation: false - seccompProfile: - type: {{ .Values.ui.profileType | default "RuntimeDefault" }} - capabilities: - drop: - - ALL + {{- if .Values.ui.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.ui.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} ports: - containerPort: 3000 protocol: TCP @@ -143,6 +137,9 @@ spec: port: 3000 initialDelaySeconds: 30 periodSeconds: 30 + {{- if .Values.ui.resources }} + resources: {{- toYaml .Values.ui.resources | nindent 12 }} + {{- end }} volumes: {{- if .Values.ui.extraVolumes }} {{- .Values.ui.extraVolumes | toYaml | nindent 8 }} diff --git a/helm/dbrepo/values.schema.json b/helm/dbrepo/values.schema.json index 5872dd5e3a81b779cdf37c01cac04afa2d73e17a..0e1d72462caa8ecaa85d9eacd79822cb19f89dd1 100644 --- a/helm/dbrepo/values.schema.json +++ b/helm/dbrepo/values.schema.json @@ -3,6 +3,51 @@ "properties": { "analyseservice": { "properties": { + "containerSecurityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seLinuxOptions": { + "type": "string" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "enabled": { "type": "boolean" }, @@ -23,9 +68,56 @@ }, "type": "object" }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string" + }, + "supplementalGroups": { + "type": "array" + }, + "sysctls": { + "type": "array" + } + }, + "type": "object" + }, "replicaCount": { "type": "integer" }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "s3": { "properties": { "endpoint": { @@ -579,6 +671,51 @@ }, "dataservice": { "properties": { + "containerSecurityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seLinuxOptions": { + "type": "string" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "default": { "properties": { "date": { @@ -596,9 +733,6 @@ "enabled": { "type": "boolean" }, - "endpoint": { - "type": "string" - }, "grant": { "properties": { "read": { @@ -624,6 +758,26 @@ }, "type": "object" }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string" + }, + "supplementalGroups": { + "type": "array" + }, + "sysctls": { + "type": "array" + } + }, + "type": "object" + }, "rabbitmq": { "properties": { "consumer": { @@ -691,6 +845,27 @@ "gateway": { "type": "string" }, + "global": { + "properties": { + "compatibility": { + "properties": { + "openshift": { + "properties": { + "adaptSecurityContext": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "storageClass": { + "type": "string" + } + }, + "type": "object" + }, "hostname": { "type": "string" }, @@ -930,6 +1105,51 @@ }, "type": "object" }, + "containerSecurityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seLinuxOptions": { + "type": "string" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "datacite": { "properties": { "enabled": { @@ -976,12 +1196,59 @@ }, "type": "object" }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string" + }, + "supplementalGroups": { + "type": "array" + }, + "sysctls": { + "type": "array" + } + }, + "type": "object" + }, "replicaCount": { "type": "integer" }, "repositoryName": { "type": "string" }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "s3": { "properties": { "auth": { @@ -1065,12 +1332,54 @@ }, "searchservice": { "properties": { + "containerSecurityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seLinuxOptions": { + "type": "string" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "enabled": { "type": "boolean" }, - "endpoint": { - "type": "string" - }, "image": { "properties": { "debug": { @@ -1101,8 +1410,55 @@ }, "type": "object" }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string" + }, + "supplementalGroups": { + "type": "array" + }, + "sysctls": { + "type": "array" + } + }, + "type": "object" + }, "replicaCount": { "type": "integer" + }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" } }, "type": "object" @@ -1238,6 +1594,51 @@ }, "ui": { "properties": { + "containerSecurityContext": { + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "properties": { + "drop": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "seLinuxOptions": { + "type": "string" + }, + "seccompProfile": { + "properties": { + "type": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "enabled": { "type": "boolean" }, @@ -1261,6 +1662,26 @@ }, "type": "object" }, + "podSecurityContext": { + "properties": { + "enabled": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string" + }, + "supplementalGroups": { + "type": "array" + }, + "sysctls": { + "type": "array" + } + }, + "type": "object" + }, "public": { "properties": { "api": { @@ -1372,6 +1793,33 @@ }, "replicaCount": { "type": "integer" + }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" } }, "type": "object" diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index ba86f30cb74b8fa1acb4105b90ba66ff75559f1a..d910ff084fb38d08dde46d4f06c69c68450dc38d 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -1,23 +1,29 @@ # Copyright the DBRepo developers # SPDX-License-Identifier: APACHE-2.0 +## @section Global parameters + +global: + ## Compatibility adaptations for Kubernetes platforms + compatibility: + ## Compatibility adaptations for Openshift + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + adaptSecurityContext: auto + ## @param global.storageClass Global StorageClass for Persistent Volume(s) + storageClass: "" + ## @section Common parameters -## ## @param namespace The namespace to install the chart -## namespace: dbrepo ## @param hostname The hostname. -## hostname: example.com ## @param gateway The gateway endpoint. -## gateway: https://example.com ## @param strategyType The image pull -## strategyType: RollingUpdate ## @param clusterDomain The cluster domain. -## clusterDomain: cluster.local ## @section Metadata Database @@ -336,6 +342,48 @@ analyseservice: pullPolicy: Always ## @param analyseservice.image.debug Set the logging level to `trace`. Otherwise, set to `info`. debug: false + ## 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 + enabled: true + ## @param analyseservice.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + fsGroupChangePolicy: Always + ## @param analyseservice.podSecurityContext.sysctls Set kernel settings using the sysctl interface + sysctls: [ ] + ## @param analyseservice.podSecurityContext.supplementalGroups Set filesystem extra groups + supplementalGroups: [ ] + ## @param analyseservice.podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup + fsGroup: 1001 + containerSecurityContext: + ## @param analyseservice.containerSecurityContext.enabled Enabled containers' Security Context + enabled: true + ## @param analyseservice.containerSecurityContext.seLinuxOptions Set SELinux options in container + seLinuxOptions: "" + ## @param analyseservice.containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser + runAsUser: 1001 + ## @param analyseservice.containerSecurityContext.runAsGroup Set RabbitMQ containers' Security Context runAsGroup + runAsGroup: 1001 + ## @param analyseservice.containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot + runAsNonRoot: true + ## @param analyseservice.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + allowPrivilegeEscalation: false + ## @param analyseservice.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + readOnlyRootFilesystem: false + capabilities: + ## @param analyseservice.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + drop: [ "ALL" ] + seccompProfile: + ## @param analyseservice.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + type: "RuntimeDefault" + ## @skip analyseservice.resources + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 500m + memory: 2048Mi + ## @param analyseservice.endpoint The url of the endpoint. endpoint: http://analyse-service s3: @@ -347,7 +395,7 @@ analyseservice: ## @section Metadata Service metadataservice: - ## @param metadataservice.enabled Enable the Metadata Service. + ## @param metadataservice.enabled Enable the Broker Service. enabled: true image: ## @skip metadataservice.image.name @@ -356,6 +404,47 @@ metadataservice: pullPolicy: Always ## @param metadataservice.image.debug Set the logging level to `trace`. Otherwise, set to `info`. debug: false + ## 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 + enabled: true + ## @param metadataservice.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + fsGroupChangePolicy: Always + ## @param metadataservice.podSecurityContext.sysctls Set kernel settings using the sysctl interface + sysctls: [ ] + ## @param metadataservice.podSecurityContext.supplementalGroups Set filesystem extra groups + supplementalGroups: [ ] + ## @param metadataservice.podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup + fsGroup: 1001 + containerSecurityContext: + ## @param metadataservice.containerSecurityContext.enabled Enabled containers' Security Context + enabled: true + ## @param metadataservice.containerSecurityContext.seLinuxOptions Set SELinux options in container + seLinuxOptions: "" + ## @param metadataservice.containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser + runAsUser: 1001 + ## @param metadataservice.containerSecurityContext.runAsGroup Set RabbitMQ containers' Security Context runAsGroup + runAsGroup: 1001 + ## @param metadataservice.containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot + runAsNonRoot: true + ## @param metadataservice.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + allowPrivilegeEscalation: false + ## @param metadataservice.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + readOnlyRootFilesystem: false + capabilities: + ## @param metadataservice.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + drop: [ "ALL" ] + seccompProfile: + ## @param metadataservice.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + type: "RuntimeDefault" + ## @skip metadataservice.resources + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 2048Mi ## @param metadataservice.endpoint The Metadata Service endpoint. endpoint: http://metadata-service admin: @@ -399,10 +488,8 @@ metadataservice: ## @section Data Service dataservice: - ## @param dataservice.enabled Enable the Metadata Service. + ## @param dataservice.enabled Enable the Broker Service. enabled: true - ## @param dataservice.endpoint The endpoint for the microservices. - endpoint: http://data-service image: ## @skip dataservice.image.name name: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.4.4 @@ -410,6 +497,40 @@ dataservice: pullPolicy: Always ## @param dataservice.image.debug Set the logging level to `trace`. Otherwise, set to `info`. debug: false + ## 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 + enabled: true + ## @param dataservice.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + fsGroupChangePolicy: Always + ## @param dataservice.podSecurityContext.sysctls Set kernel settings using the sysctl interface + sysctls: [ ] + ## @param dataservice.podSecurityContext.supplementalGroups Set filesystem extra groups + supplementalGroups: [ ] + ## @param dataservice.podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup + fsGroup: 1001 + containerSecurityContext: + ## @param dataservice.containerSecurityContext.enabled Enabled containers' Security Context + enabled: true + ## @param dataservice.containerSecurityContext.seLinuxOptions Set SELinux options in container + seLinuxOptions: "" + ## @param dataservice.containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser + runAsUser: 1001 + ## @param dataservice.containerSecurityContext.runAsGroup Set RabbitMQ containers' Security Context runAsGroup + runAsGroup: 1001 + ## @param dataservice.containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot + runAsNonRoot: true + ## @param dataservice.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + allowPrivilegeEscalation: false + ## @param dataservice.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + readOnlyRootFilesystem: false + capabilities: + ## @param dataservice.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + drop: [ "ALL" ] + seccompProfile: + ## @param dataservice.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + type: "RuntimeDefault" + ## @skip dataservice.resources grant: ## @param dataservice.grant.read The default database permissions for users with read access. read: SELECT @@ -454,10 +575,8 @@ dataservice: ## @section Search Service searchservice: - ## @param searchservice.enabled Enable the Search Service. + ## @param searchservice.enabled Enable the Broker Service. enabled: true - ## @param searchservice.endpoint The endpoint for the microservices. - endpoint: http://search-service image: ## @skip searchservice.image.name name: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.4.4 @@ -465,6 +584,47 @@ searchservice: pullPolicy: Always ## @param searchservice.image.debug Set the logging level to `trace`. Otherwise, set to `info`. debug: false + ## 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 + enabled: true + ## @param searchservice.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + fsGroupChangePolicy: Always + ## @param searchservice.podSecurityContext.sysctls Set kernel settings using the sysctl interface + sysctls: [ ] + ## @param searchservice.podSecurityContext.supplementalGroups Set filesystem extra groups + supplementalGroups: [ ] + ## @param searchservice.podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup + fsGroup: 1001 + containerSecurityContext: + ## @param searchservice.containerSecurityContext.enabled Enabled containers' Security Context + enabled: true + ## @param searchservice.containerSecurityContext.seLinuxOptions Set SELinux options in container + seLinuxOptions: "" + ## @param searchservice.containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser + runAsUser: 1001 + ## @param searchservice.containerSecurityContext.runAsGroup Set RabbitMQ containers' Security Context runAsGroup + runAsGroup: 1001 + ## @param searchservice.containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot + runAsNonRoot: true + ## @param searchservice.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + allowPrivilegeEscalation: false + ## @param searchservice.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + readOnlyRootFilesystem: true + capabilities: + ## @param searchservice.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + drop: [ "ALL" ] + seccompProfile: + ## @param searchservice.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + type: "RuntimeDefault" + ## @skip searchservice.resources + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 2048Mi ## @skip searchservice.init init: image: @@ -574,7 +734,7 @@ identityservice: ## @section User Interface ui: - ## @param ui.enabled Enable the User Interface. + ## @param ui.enabled Enable the Broker Service. enabled: true image: ## @skip ui.image.name @@ -583,6 +743,47 @@ ui: pullPolicy: Always ## @param ui.image.debug Set the logging level to `trace`. Otherwise, set to `info`. debug: false + ## 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 + enabled: true + ## @param ui.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + fsGroupChangePolicy: Always + ## @param ui.podSecurityContext.sysctls Set kernel settings using the sysctl interface + sysctls: [ ] + ## @param ui.podSecurityContext.supplementalGroups Set filesystem extra groups + supplementalGroups: [ ] + ## @param ui.podSecurityContext.fsGroup Set RabbitMQ pod's Security Context fsGroup + fsGroup: 1001 + containerSecurityContext: + ## @param ui.containerSecurityContext.enabled Enabled containers' Security Context + enabled: true + ## @param ui.containerSecurityContext.seLinuxOptions Set SELinux options in container + seLinuxOptions: "" + ## @param ui.containerSecurityContext.runAsUser Set RabbitMQ containers' Security Context runAsUser + runAsUser: 1001 + ## @param ui.containerSecurityContext.runAsGroup Set RabbitMQ containers' Security Context runAsGroup + runAsGroup: 1001 + ## @param ui.containerSecurityContext.runAsNonRoot Set RabbitMQ container's Security Context runAsNonRoot + runAsNonRoot: true + ## @param ui.containerSecurityContext.allowPrivilegeEscalation Set container's privilege escalation + allowPrivilegeEscalation: false + ## @param ui.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + readOnlyRootFilesystem: false + capabilities: + ## @param ui.containerSecurityContext.capabilities.drop Set container's Security Context runAsNonRoot + drop: [ "ALL" ] + seccompProfile: + ## @param ui.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + type: "RuntimeDefault" + ## @skip ui.resources + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 2048Mi public: api: ## @param ui.public.api.client The endpoint for the client api. diff --git a/make/gen.mk b/make/gen.mk index 1f8e6fd45d1bc1b7451599bcd4722633038c17eb..b81d504213bdee6cae172d1edfc18db82f2ef65a 100644 --- a/make/gen.mk +++ b/make/gen.mk @@ -1,6 +1,6 @@ ##@ Generate -.PHONY: gen-swagger-doc-fe +.PHONY: gen-swagger-doc gen-swagger-doc: build-images ## Generate Swagger documentation and fetch. docker compose up -d bash .docs/.swagger/swagger-generate.sh diff --git a/make/test.mk b/make/test.mk index 5760075a2956bf282b7243ff78993b5022aebc7f..c3d2cd8804831f25d7450d0f34914c69c6f53477 100644 --- a/make/test.mk +++ b/make/test.mk @@ -15,30 +15,3 @@ test-analyse-service: ## Test the Analyse Service. .PHONY: test-lib test-lib: ## Test the Python Library. bash ./lib/python/test.sh - -.PHONY: scan-images -scan-images: ## Scan the docker images for vulnerabilities. - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-analyse-service-report.json dbrepo-analyse-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-analyse-service:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-authentication-service-report.json dbrepo-authentication-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-authentication-service:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-broker-service-report.json bitnami/rabbitmq:3.10 - trivy image --insecure --exit-code 1 --severity CRITICAL bitnami/rabbitmq:3.10 - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-gateway-service-report.json "nginx:1.25.0-alpine-slim" - trivy image --insecure --exit-code 1 --severity CRITICAL "nginx:1.25.0-alpine-slim" - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-metadata-db-report.json dbrepo-metadata-db:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-metadata-db:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-metadata-service-report.json dbrepo-metadata-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-metadata-service:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-data-service-report.json dbrepo-data-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-data-service:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-search-db-report.json "dbrepo-search-db" - trivy image --insecure --exit-code 1 --severity CRITICAL "dbrepo-search-db" - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-search-db-report.json "opensearchproject/opensearch-dashboards:2.10.0" - trivy image --insecure --exit-code 1 --severity CRITICAL "opensearchproject/opensearch-dashboards:2.10.0" - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-data-db-report.json "bitnami/mariadb:11.2.2-debian-11-r0" - trivy image --insecure --exit-code 1 --severity CRITICAL "bitnami/mariadb:11.2.2-debian-11-r0" - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-ui-report.json dbrepo-ui:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-ui:latest - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-search-service-report.json dbrepo-search-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-search-service:latest \ No newline at end of file