diff --git a/.dev/auth.keystore b/.dev/auth.keystore deleted file mode 100644 index e5fbb780a18153b3ccd70ed3e4a21c0203fbf86c..0000000000000000000000000000000000000000 Binary files a/.dev/auth.keystore and /dev/null differ diff --git a/.dev/chain.jks b/.dev/chain.jks deleted file mode 100644 index 924e97caff62e4d085110fef66edc6d4d1ca8ab5..0000000000000000000000000000000000000000 Binary files a/.dev/chain.jks and /dev/null differ diff --git a/.dev/generate-jks.sh b/.dev/generate-jks.sh deleted file mode 100644 index ea1bffbb4f6ce34f18a4639058b8b9cb36301db1..0000000000000000000000000000000000000000 --- a/.dev/generate-jks.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash -# ---------------- -# https://blogs.oracle.com/blogbypuneeth/post/create-an-internal-certification-authority-ca-using-keytool-and-sign-your-server-certificate -# ---------------- -STORE_PASS=password -KEY_PASS=password - -declare -A services -services[9091]=container -services[9092]=database -services[9093]=query -services[9094]=table -services[9095]=gateway -services[9096]=identifier -services[9097]=authentication -services[9098]=user -services[9099]=metadata - -function generate () { - if [ -z "$2" ]; then - CN="$1" - else - CN="$1-$2" - fi - echo "... generate $CN certificate" - keytool -genkeypair -storepass ${STORE_PASS} -keypass ${KEY_PASS} -storetype PKCS12 -keyalg RSA -keysize 2048 \ - -dname "CN=$CN, OU=DS-IFS, O=TU Wien, C=AT" -alias "$CN" -ext "SAN:c=DNS:localhost,IP:127.0.0.1" \ - -keystore ./server.keystore -} - -function sign () { - if [ -z "$2" ]; then - CN="$1" - else - CN="$1-$2" - fi - echo "... sign $CN certificate" - keytool -alias "$CN" -certreq -storepass ${STORE_PASS} -keyalg RSA \ - -keystore ./server.keystore | keytool -alias intermediate -gencert -storepass ${STORE_PASS} \ - -keyalg RSA | keytool -alias "$CN" -importcert -storepass ${STORE_PASS} -keyalg RSA \ - -keystore ./server.keystore -noprompt -trustcacerts -} - -function crt () { - echo "... export $1 certificate" - keytool -exportcert -alias "$1" -rfc -storepass ${STORE_PASS} -keystore "$2" > "./$1.crt" -} - -function move () { - if [ -z "$2" ]; then - CN="$1" - else - CN="$1-$2" - fi - echo "... move jks to the $CN" - cp ./server.keystore "../fda-$CN/server.keystore" - rm -f "../fda-$CN/root.crt" && cp ./root.crt "../fda-$CN/root.crt" -} - -echo "Remove old JKS(s)" -rm -f ./server.keystore ./auth.keystore ./chain.jks ./*.crt - -echo "Generate root certificate" -keytool -alias root -dname "CN=RootCA, OU=DS-IFS, O=TU Wien, C=AT" -genkeypair -ext KeyUsage="keyCertSign" \ - -ext BasicConstraints:"critical=ca:true" -validity 3600 -storepass ${STORE_PASS} -keyalg RSA - -echo "Generate intermediate certificate" -keytool -alias intermediate -dname "CN=IntermediateCA, OU=DS-IFS, O=TU Wien, C=AT" -genkeypair \ - -ext KeyUsage="keyCertSign" -ext BasicConstraints:"critical=ca:true" -validity 1800 -storepass ${STORE_PASS} \ - -keyalg RSA - -echo "Sign the intermediate certificate" -keytool -alias intermediate -certreq -storepass ${STORE_PASS} -keyalg RSA | keytool -alias root -gencert \ - -ext KeyUsage="keyCertSign" -ext BasicConstraints:"critical=ca:true" -storepass ${STORE_PASS} \ - -keyalg RSA | keytool -alias intermediate -importcert -storepass ${STORE_PASS} -keyalg RSA - -echo "Import the root certificate to the JKS" -keytool -export -alias root -storepass ${STORE_PASS} | keytool -import -alias root -keystore ./server.keystore \ - -storepass ${STORE_PASS} -noprompt -trustcacerts - -echo "Import the intermediate certificate to the JKS" -keytool -export -alias intermediate -storepass ${STORE_PASS} | keytool -import -alias intermediate -keystore ./server.keystore \ - -storepass ${STORE_PASS} -noprompt -trustcacerts - -echo "Generating the certificate key pairs" -for key in "${!services[@]}"; do - generate "${services[$key]}" "service" -done -generate "ui" - -echo "Sign the certificates with intermediate certificate" -for key in "${!services[@]}"; do - sign "${services[$key]}" "service" -done -sign "ui" - -echo "Export the trusted keystore" -keytool -export -alias intermediate -storepass ${STORE_PASS} | keytool -import -alias intermediate \ - -keystore ./chain.jks -storepass ${STORE_PASS} -trustcacerts -noprompt -keytool -export -alias root -storepass ${STORE_PASS} | keytool -import -alias root -keystore ./chain.jks \ - -storepass ${STORE_PASS} -trustcacerts -noprompt - -echo "Export CRTs" -crt root ./chain.jks -crt intermediate ./chain.jks - -echo "Copy the JKS(s)" -for key in "${!services[@]}"; do - move "${services[$key]}" "service" -done -move "ui" - -echo "Create the authentication service JKS" -echo "... import private key into the key store" -keytool -importkeystore -srckeystore ./server.keystore -srcstorepass ${STORE_PASS} -srcalias "authentication-service" \ - -destkeystore ./auth.keystore -deststorepass ${STORE_PASS} -deststoretype PKCS12 -destalias "server" -trustcacerts \ - -noprompt -rm -f ../fda-authentication-service/auth.keystore && cp ./auth.keystore ../fda-authentication-service/auth.keystore diff --git a/.dev/intermediate.crt b/.dev/intermediate.crt deleted file mode 100644 index e161ec3985815975bc897e1c3be854eff38afe39..0000000000000000000000000000000000000000 --- a/.dev/intermediate.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDaDCCAlCgAwIBAgIEMYJrXzANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDA0MDczMzU2WhcNMjMwNzAzMDczMzU2WjBJMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMRcwFQYDVQQD -Ew5JbnRlcm1lZGlhdGVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKPTnhNdSjVJvRT6jBQuNWOYAeukC1hVAAuiOtU6QqQANFLRHACFQGs/QJkh1LRt -HoNvN2W0EEljUQ5pgSym76xPXCg38OYmsV4w0gcSe34QyCCWkB82eBi48MEmsb6s -x7n3uM+SaSwaFqxZFTQszsEVOJcnfRDBhYkT3juiuW0HzmMCuDa/V1sl1HgxbKRc -zEXEk3PjDY12gsYNzF1jgB33Nwh692npdBca5MXJ+Gi0zvnM+1JgrfIYayC37+ZF -UG10LYTSV4rG4NS9UzF/cBK9naddMgCgqIMGHnU5Z5N+PNPiHZ4WkX4Xf4Zu1WTg -YGlsVjgNKTX6CYytrRwbWKUCAwEAAaNgMF4wHQYDVR0OBBYEFF5md9arqKs42p+W -jhWXGwgVMmDKMAsGA1UdDwQEAwICBDAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY -MBaAFJ0un4jfS4HiMAw/U+dkuiXFsX8DMA0GCSqGSIb3DQEBCwUAA4IBAQAJK/aw -CynaeSqWI85UAaHlW2IwG0JeEjsYmgjHq54zhN0Ye9W46ZkAS3KRemtDLrCIeoxA -GwF0c9Pw2IigxfD6ksopUok17YJroif3waSSee4CQfURHj1V4xUOIEeeStHciHmj -/HGs42vDfmh+uZ3hMy4Obxmag0CLg824WyATp5ShhVgzBBt/0MVQFubXuhCFtQCl -Ddyhrog2ThSwuSUxrZ//ia/xpFV2a91SopRAiFOWDCD0FnO+fHpxy+gK/HP2TFoL -yXE3aTr1p1TFQupxQFluqZLRyXoA/h7r5LPHmLCFLwCfcpJeF+6XtRY+GX+hp843 -yeYIIDqQs1RwUvCo ------END CERTIFICATE----- diff --git a/.dev/root.crt b/.dev/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/.dev/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/.dev/server.keystore b/.dev/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/.dev/server.keystore and /dev/null differ diff --git a/.env.unix.example b/.env.unix.example index 2d6d1d916cb39756ebda13c875a1680b89461dda..8577b8c00e0a6426aed10c7c2afeed0225730eba 100644 --- a/.env.unix.example +++ b/.env.unix.example @@ -14,5 +14,4 @@ BROKER_PASSWORD=fda KEYCLOAK_ADMIN=fda KEYCLOAK_ADMIN_PASSWORD=fda BROKER_CONSUMERS=2 -WEBSITE=http://example.com -spring_profiles_active=insecure \ No newline at end of file +WEBSITE=http://example.com \ No newline at end of file diff --git a/fda-authentication-service/dbrepo-realm.json b/fda-authentication-service/dbrepo-realm.json index bab85fd97b237704dde2ded4673f13b11b535e9e..c5005faeb27ad50b931795ee7ae5ab8e032939ea 100644 --- a/fda-authentication-service/dbrepo-realm.json +++ b/fda-authentication-service/dbrepo-realm.json @@ -50,7 +50,7 @@ "description" : "${default-user-handling}", "composite" : true, "composites" : { - "realm" : [ "modify-user-information" ] + "realm" : [ "modify-user-theme", "modify-user-information" ] }, "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", @@ -292,6 +292,14 @@ "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" : "8755da2b-d85a-4f40-a0bf-fe08cf8f9d75", "name" : "delete-table", @@ -1080,7 +1088,7 @@ } } ], "defaultClientScopes" : [ ], - "optionalClientScopes" : [ "rabbitmq.read:*/*", "web-origins", "acr", "rabbitmq.write:*/*", "address", "phone", "offline_access", "profile", "roles", "microprofile-jwt", "email", "rabbitmq.configure:*/*" ] + "optionalClientScopes" : [ "address", "profile", "roles", "web-origins", "rabbitmq.read:*/*", "acr", "rabbitmq.write:*/*", "phone", "offline_access", "attributes", "microprofile-jwt", "email", "rabbitmq.configure:*/*" ] }, { "id" : "25741f6b-4867-4138-8238-6345c6ba8702", "clientId" : "rabbitmq-client", @@ -1615,6 +1623,33 @@ "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:*/*", @@ -1720,7 +1755,7 @@ } ] } ], "defaultDefaultClientScopes" : [ ], - "defaultOptionalClientScopes" : [ "rabbitmq.write:*/*", "offline_access", "rabbitmq.configure:*/*", "roles", "role_list", "address", "phone", "acr", "microprofile-jwt", "email", "profile", "rabbitmq.read:*/*", "web-origins" ], + "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", @@ -1780,7 +1815,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "saml-role-list-mapper" ] } }, { "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1", @@ -1806,7 +1841,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper" ] } } ], "org.keycloak.userprofile.UserProfileProvider" : [ { @@ -1864,7 +1899,7 @@ "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "db0aeca3-8774-4c3d-a6b7-a29a7de63cf4", + "id" : "6230a38e-9a93-4ef4-a522-ebd0a0b5ba7a", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -1886,7 +1921,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "cfed2477-e59b-4b95-b76f-70d84e8c0876", + "id" : "f30c0cd5-9380-4297-87a9-2a3feee031ed", "alias" : "Authentication Options", "description" : "Authentication options.", "providerId" : "basic-flow", @@ -1915,7 +1950,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "0753142a-666c-4b86-8aed-e6930f4cfd9b", + "id" : "f7de5b0c-ebac-403b-acf1-3bb21ffeec22", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1937,7 +1972,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "f34f13eb-4053-452c-95d4-d11b2f38a679", + "id" : "8924d975-c78f-4798-9d81-2a40d7e5188a", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1959,7 +1994,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "899e0d91-28fa-4e3c-833b-fb21d3f59ef9", + "id" : "288e798c-84a3-4368-bb61-bb29c39d6d2c", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1981,7 +2016,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "57791f8b-44ec-4e33-a277-bc388e22770f", + "id" : "ced94ffb-3056-4582-82ef-06bff9ee166d", "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", @@ -2003,7 +2038,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "66f34e28-c468-42f0-a842-18e744d9774f", + "id" : "0cb56734-e325-4417-8aef-07237ecddd5a", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -2025,7 +2060,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "27738ff3-8b2c-498b-8303-eca7cd809f5a", + "id" : "d6fdc139-02e9-4799-beed-111a272b22e2", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -2048,7 +2083,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "272979c3-9993-42d3-a2e3-7fd8a5e872bb", + "id" : "b94cb3b9-40ba-45f8-9432-b40e45c94cd3", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -2070,7 +2105,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "537f7a1a-1c6a-444a-8c83-ed5401d4f00a", + "id" : "c2643757-cd92-4b82-b9f1-8d4769495484", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -2106,7 +2141,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "87638583-1629-4879-8705-ddb97e61c57e", + "id" : "07f49e9e-38cd-4d03-90b5-720aa77f5ae6", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -2142,7 +2177,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "de85f9a3-f505-4f4a-9f0f-23ad6a42c64b", + "id" : "381cd686-4fc3-47d2-8048-47f07dcb1a52", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -2171,7 +2206,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "74b10c28-424b-416c-9b09-1835418daafe", + "id" : "02bd79fb-4446-46e5-b881-d58b93ec8557", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -2186,7 +2221,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "bf8aedfb-8645-4130-bf30-e04a9f351eea", + "id" : "f0e72761-34a5-4ddc-9eda-a7b43b45ce4b", "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", @@ -2209,7 +2244,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "c3f6f1c8-2533-4e61-9e8f-89e5d4919923", + "id" : "752ea7e2-01f2-4cef-967e-e7678d245243", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -2231,7 +2266,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "ed4ab53a-4d51-4f0e-b2f6-e0ea7be307e7", + "id" : "89e9a682-6a84-4688-924e-e5582866d7fd", "alias" : "http challenge", "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", "providerId" : "basic-flow", @@ -2253,7 +2288,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "1e8dc301-de23-400f-af1c-0df80fcec9b7", + "id" : "02a165c7-53d5-4601-a342-de3e23a95054", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -2269,7 +2304,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "3359cf28-0d4b-407b-a291-65eec7879076", + "id" : "6a68e3c0-f1ed-4720-8bbe-458e1077e7eb", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -2305,7 +2340,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "76e815e3-344a-41dd-a593-a4c935218a61", + "id" : "7fff0117-d0b4-43ae-82e0-a93abc5dda87", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -2341,7 +2376,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "196d317e-c522-4058-b57c-2f527b3a139d", + "id" : "6d2ce2e0-f4d8-4e57-b77f-b681f2a9b99d", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -2357,13 +2392,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "ebd93af1-fecc-40d7-bc18-453d7367e183", + "id" : "9fdb8f42-4d69-495f-a97f-414480c7405f", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "da7de212-1212-48f7-8f75-d550888092b4", + "id" : "12c376db-bfdb-41fb-bdf9-45e5eda8d879", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/fda-container-service/Dockerfile b/fda-container-service/Dockerfile index a406bcb68f3fd0fcdc2f4fc6e58822b3f6975b36..b9da313606275edea16aea4dbc5fb08067d1386e 100644 --- a/fda-container-service/Dockerfile +++ b/fda-container-service/Dockerfile @@ -24,8 +24,6 @@ FROM openjdk:11-jre-slim as runtime ENV METADATA_DB=fda ENV METADATA_USERNAME=root ENV METADATA_PASSWORD=dbrepo -ENV BROKER_USERNAME=fda -ENV BROKER_PASSWORD=fda ENV SHARED_FILESYSTEM=/tmp ENV USER_NETWORK=userdb ENV LOG_LEVEL=debug @@ -33,18 +31,9 @@ ENV DBREPO_CLIENT_SECRET=client-secret ENV CLIENT_ID=dbrepo-client ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key -ENV KEY_ALIAS=container-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -54,4 +43,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./container-service.j EXPOSE 9091 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./container-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./container-service.jar"] diff --git a/fda-container-service/rest-service/src/main/resources/application-insecure.yml b/fda-container-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index bc752e1ad0832608ef3e42f9a88bfaaf7ca4402b..0000000000000000000000000000000000000000 --- a/fda-container-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,62 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: container-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -springdoc.swagger-ui.enabled: true -server: - port: 9091 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: container-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9091 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - network: userdb - mount.path: /tmp - ready.path: /ready - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" - client_secret: "${DBREPO_CLIENT_SECRET}" - client_id: "${CLIENT_ID}" - gateway.endpoint: https://gateway-service:9095 \ No newline at end of file diff --git a/fda-container-service/rest-service/src/main/resources/application-local.yml b/fda-container-service/rest-service/src/main/resources/application-local.yml index adb1000e110a7d831d4517306434a84f831a5d53..4131f45893204bb670d966e4245f268e4116d9da 100644 --- a/fda-container-service/rest-service/src/main/resources/application-local.yml +++ b/fda-container-service/rest-service/src/main/resources/application-local.yml @@ -22,21 +22,10 @@ spring: name: container-service cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true management.endpoints.web.exposure.include: health,info,prometheus springdoc.swagger-ui.enabled: true server: port: 9091 - ssl: - enabled: true - key-alias: container-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -46,16 +35,14 @@ logging: eureka: instance: hostname: container-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9091 + non-secure-port: 9091 client.serviceUrl.defaultZone: http://localhost:9090/eureka/ fda: network: userdb mount.path: /tmp ready.path: ./ready jwt: - issuer: https://localhost:8443/realms/dbrepo + issuer: http://localhost:8443/realms/dbrepo public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB client_secret: client-secret client_id: dbrepo-client diff --git a/fda-container-service/rest-service/src/main/resources/application.yml b/fda-container-service/rest-service/src/main/resources/application.yml index 135413295ca5d2c67dea3991f7b8561256765783..7017818a8f68bdd4366857c6ee3b7fc47fe44bb2 100644 --- a/fda-container-service/rest-service/src/main/resources/application.yml +++ b/fda-container-service/rest-service/src/main/resources/application.yml @@ -24,7 +24,8 @@ spring: loadbalancer.ribbon.enabled: false management.endpoints.web.exposure.include: health,info,prometheus springdoc.swagger-ui.enabled: true -server.port: 9091 +server: + port: 9091 logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -34,9 +35,7 @@ logging: eureka: instance: hostname: container-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9091 + non-secure-port: 9091 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: network: "${USER_NETWORK}" @@ -47,4 +46,4 @@ fda: public_key: "${JWT_PUBKEY}" client_secret: "${DBREPO_CLIENT_SECRET}" client_id: "${CLIENT_ID}" - gateway.endpoint: https://gateway-service:9095 \ No newline at end of file + gateway.endpoint: http://gateway-service:9095 \ No newline at end of file diff --git a/fda-container-service/root.crt b/fda-container-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-container-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-container-service/server.keystore b/fda-container-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-container-service/server.keystore and /dev/null differ diff --git a/fda-database-service/Dockerfile b/fda-database-service/Dockerfile index f798f537c212a2fdd97dbeb8020c132a4edb56ba..1cbbf1a0f5c7c42811fca132c14dfe9e7499eb12 100644 --- a/fda-database-service/Dockerfile +++ b/fda-database-service/Dockerfile @@ -29,24 +29,15 @@ ENV BROKER_PASSWORD=fda ENV SEARCH_ENDPOINT=search-service ENV SEARCH_USERNAME=elastic ENV SEARCH_PASSWORD=elastic -ENV GATEWAY_ENDPOINT=https://gateway-service:9095 +ENV GATEWAY_ENDPOINT=http://gateway-service:9095 ENV LOG_LEVEL=debug ENV DBREPO_CLIENT_SECRET=client-secret ENV CLIENT_ID=dbrepo-client ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key -ENV KEY_ALIAS=database-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -56,4 +47,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./database-service.ja EXPOSE 9092 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./database-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./database-service.jar"] diff --git a/fda-database-service/rest-service/src/main/resources/application-insecure.yml b/fda-database-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 5410f12b4ac605709c7b15766a48bfe7e3d9d119..0000000000000000000000000000000000000000 --- a/fda-database-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,67 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: database-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true - rabbitmq: - host: broker-service - username: fda - password: fda -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9092 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: database-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9092 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - elastic: - endpoint: search-service:9200 - username: elastic - password: "${ELASTIC_PASSWORD}" - ready.path: /ready - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" - client_secret: "${DBREPO_CLIENT_SECRET}" - client_id: "${CLIENT_ID}" - gateway.endpoint: "${GATEWAY_ENDPOINT}" \ No newline at end of file diff --git a/fda-database-service/rest-service/src/main/resources/application-local.yml b/fda-database-service/rest-service/src/main/resources/application-local.yml index 5c93752d641a4d037622954f0b5663180963fe08..93295575889343b2d9d3e4b10e70886ccb3dd1a1 100644 --- a/fda-database-service/rest-service/src/main/resources/application-local.yml +++ b/fda-database-service/rest-service/src/main/resources/application-local.yml @@ -22,10 +22,6 @@ spring: name: database-service cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true rabbitmq: host: localhost username: fda @@ -33,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9092 - ssl: - enabled: true - key-alias: database-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -49,9 +38,7 @@ logging: eureka: instance: hostname: database-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9092 + non-secure-port: 9092 client.serviceUrl.defaultZone: http://localhost:9090/eureka/ fda: elastic: @@ -60,7 +47,7 @@ fda: password: elastic ready.path: ./ready jwt: - issuer: https://localhost:8443/realms/dbrepo + issuer: http://localhost:8443/realms/dbrepo public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB client_secret: client-secret client_id: dbrepo-client diff --git a/fda-database-service/rest-service/src/main/resources/application.yml b/fda-database-service/rest-service/src/main/resources/application.yml index bc3a7d820fcd25325863aa26c7c7314ab2c85348..434d09b0be7696113f76f5b2b35f589f46a30b1d 100644 --- a/fda-database-service/rest-service/src/main/resources/application.yml +++ b/fda-database-service/rest-service/src/main/resources/application.yml @@ -29,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9092 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,9 +38,7 @@ logging: eureka: instance: hostname: database-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9092 + non-secure-port: 9092 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: elastic: @@ -60,4 +51,4 @@ fda: public_key: "${JWT_PUBKEY}" client_secret: "${DBREPO_CLIENT_SECRET}" client_id: "${CLIENT_ID}" - gateway.endpoint: https://gateway-service:9095 \ No newline at end of file + gateway.endpoint: "${GATEWAY_ENDPOINT}" \ No newline at end of file diff --git a/fda-database-service/root.crt b/fda-database-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-database-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-database-service/server.keystore b/fda-database-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-database-service/server.keystore and /dev/null differ diff --git a/fda-discovery-service/rest-service/src/main/resources/application-insecure.yml b/fda-discovery-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 9d94a3e040753966791aaa6694298bfac2134d1c..0000000000000000000000000000000000000000 --- a/fda-discovery-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,49 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: discovery-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9090 -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - client: - register-with-eureka: false - fetch-registry: false - serviceUrl.defaultZone: http://discovery-service:9090/eureka/ - instance: - hostname: discovery-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9090 -fda: - ready.path: /ready \ No newline at end of file diff --git a/fda-gateway-service/Dockerfile b/fda-gateway-service/Dockerfile index d1b28f09e6cf6c92d16e143af27f7d471603c8f7..125909033f3bf11b366d289cddfac7c21f57e315 100644 --- a/fda-gateway-service/Dockerfile +++ b/fda-gateway-service/Dockerfile @@ -21,10 +21,6 @@ ENV METADATA_USERNAME=postgres ENV METADATA_PASSWORD=postgres ENV GATEWAY_ENDPOINT=https://gateway-service:9095 ENV LOG_LEVEL=debug -ENV KEY_ALIAS=gateway-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app diff --git a/fda-gateway-service/rest-service/src/main/resources/application-insecure.yml b/fda-gateway-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 96eb965bdff44671e70d2bd0777513d8723f39e6..0000000000000000000000000000000000000000 --- a/fda-gateway-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,53 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:h2:mem:mydb - username: sa - password: password - driverClassName: org.h2.Driver - jpa: - show-sql: false - database-platform: org.hibernate.dialect.H2Dialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: gateway-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus,gateway -server: - port: 9095 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: discovery-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9095 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - ready.path: /ready \ No newline at end of file diff --git a/fda-gateway-service/rest-service/src/main/resources/application-local.yml b/fda-gateway-service/rest-service/src/main/resources/application-local.yml index 6ca893a90b0150b49522041bd169711015de9956..b53dbde5eee61dd749ccc089d7c9571656a62f56 100644 --- a/fda-gateway-service/rest-service/src/main/resources/application-local.yml +++ b/fda-gateway-service/rest-service/src/main/resources/application-local.yml @@ -29,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus,gateway server: port: 9095 - ssl: - enabled: true - key-alias: server - key-store: "./server.keystore" - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: diff --git a/fda-gateway-service/rest-service/src/main/resources/application.yml b/fda-gateway-service/rest-service/src/main/resources/application.yml index 63fcc36737fa2044224bb674aa8df23fba71cde0..61615339d0bfd8ff6aa7c3a539268b18f3f39bff 100644 --- a/fda-gateway-service/rest-service/src/main/resources/application.yml +++ b/fda-gateway-service/rest-service/src/main/resources/application.yml @@ -22,13 +22,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus,gateway server: port: 9095 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: diff --git a/fda-identifier-service/Dockerfile b/fda-identifier-service/Dockerfile index b1e7b2def2a6e6c810adb41c98729f19951b1f28..43768d4a7c6e293ed7e823df846c50e758e4e0d7 100644 --- a/fda-identifier-service/Dockerfile +++ b/fda-identifier-service/Dockerfile @@ -25,25 +25,16 @@ FROM openjdk:11-jre-slim as runtime ENV METADATA_DB=fda ENV METADATA_USERNAME=root ENV METADATA_PASSWORD=dbrepo -ENV GATEWAY_ENDPOINT=https://gateway-service:9095 +ENV GATEWAY_ENDPOINT=http://gateway-service:9095 ENV WEBSITE=http://localhost:3000 ENV LOG_LEVEL=debug ENV DBREPO_CLIENT_SECRET=client-secret ENV CLIENT_ID=dbrepo-client ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key -ENV KEY_ALIAS=identifier-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -53,4 +44,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./identifier-service. EXPOSE 9096 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./identifier-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./identifier-service.jar"] diff --git a/fda-identifier-service/intermediate.crt b/fda-identifier-service/intermediate.crt deleted file mode 100644 index 6b8e17c27ea8e5337a7c0aee7bc720dab08dac44..0000000000000000000000000000000000000000 --- a/fda-identifier-service/intermediate.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDaDCCAlCgAwIBAgIEH/QufDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTc1MDQ0WhcNMjMwNzAyMTc1MDQ0WjBJMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMRcwFQYDVQQD -Ew5JbnRlcm1lZGlhdGVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKPTnhNdSjVJvRT6jBQuNWOYAeukC1hVAAuiOtU6QqQANFLRHACFQGs/QJkh1LRt -HoNvN2W0EEljUQ5pgSym76xPXCg38OYmsV4w0gcSe34QyCCWkB82eBi48MEmsb6s -x7n3uM+SaSwaFqxZFTQszsEVOJcnfRDBhYkT3juiuW0HzmMCuDa/V1sl1HgxbKRc -zEXEk3PjDY12gsYNzF1jgB33Nwh692npdBca5MXJ+Gi0zvnM+1JgrfIYayC37+ZF -UG10LYTSV4rG4NS9UzF/cBK9naddMgCgqIMGHnU5Z5N+PNPiHZ4WkX4Xf4Zu1WTg -YGlsVjgNKTX6CYytrRwbWKUCAwEAAaNgMF4wHQYDVR0OBBYEFF5md9arqKs42p+W -jhWXGwgVMmDKMAsGA1UdDwQEAwICBDAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY -MBaAFJ0un4jfS4HiMAw/U+dkuiXFsX8DMA0GCSqGSIb3DQEBCwUAA4IBAQAviRt0 -PEHhiEOzEqI45XfnRNGntYdKHRKoftRIg2HM9drVKygZ85EBeiceyhX7U2O91X+i -zKionrqgpZrjO/rJc0R7QEVN2McCqFQEAu4AgZh4hcbhzjZVo74gQkCFnsTwQXwQ -/UB0exd5Qw1zcbgn4I+LcJaApvwZ5tTCvFDX20W7dSpxhqBPnU5dV92HoXqCX9H3 -8fgX8rK3PWoYKPuXHNcjhlG0d8FxNoxRKRJRUyUwT4UC/LJE5HZR8zTVcIPR/nlD -c2V539v4myGmZdWc8OYee09OPIDtjT2zejEmTpP3fPtvHdoTe59UGWMkYn830H4Z -U/v3rj9nHwAoTytU ------END CERTIFICATE----- diff --git a/fda-identifier-service/rest-service/src/main/resources/application-insecure.yml b/fda-identifier-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 3919219a351ffd523643d69a30385b2fb76afe15..0000000000000000000000000000000000000000 --- a/fda-identifier-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,64 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: identifier-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9096 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: identifier-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9096 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - ready.path: /ready - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" - client_secret: "${DBREPO_CLIENT_SECRET}" - client_id: "${CLIENT_ID}" - gateway.endpoint: "${GATEWAY_ENDPOINT}" - website: "${WEBSITE}" - elastic: - endpoint: search-service:9200 - username: elastic - password: "${ELASTIC_PASSWORD}" \ No newline at end of file diff --git a/fda-identifier-service/rest-service/src/main/resources/application-local.yml b/fda-identifier-service/rest-service/src/main/resources/application-local.yml index 7780e1bc497456b200542c7f462a19bbcdf79a88..bab1379f36617a8f7e9dc700f9737d476c896edb 100644 --- a/fda-identifier-service/rest-service/src/main/resources/application-local.yml +++ b/fda-identifier-service/rest-service/src/main/resources/application-local.yml @@ -22,19 +22,8 @@ spring: name: identifier-service cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true server: port: 9096 - ssl: - enabled: true - key-alias: identifier-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,14 +34,12 @@ logging: eureka: instance: hostname: identifier-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9096 + non-secure-port: 9096 client.serviceUrl.defaultZone: http://localhost:9090/eureka/ fda: ready.path: ./ready jwt: - issuer: https://localhost:8443/realms/dbrepo + issuer: http://localhost:8443/realms/dbrepo public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB client_secret: client-secret client_id: dbrepo-client diff --git a/fda-identifier-service/rest-service/src/main/resources/application.yml b/fda-identifier-service/rest-service/src/main/resources/application.yml index 8e4ddd84d849c99fbca68e923d76dab65b9896bd..4532a109dcc4fea02db6044987cea64e4af77add 100644 --- a/fda-identifier-service/rest-service/src/main/resources/application.yml +++ b/fda-identifier-service/rest-service/src/main/resources/application.yml @@ -25,13 +25,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9096 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -41,9 +34,7 @@ logging: eureka: instance: hostname: identifier-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9096 + non-secure-port: 9096 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: ready.path: /ready diff --git a/fda-identifier-service/root.crt b/fda-identifier-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-identifier-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-identifier-service/server.keystore b/fda-identifier-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-identifier-service/server.keystore and /dev/null differ diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserAttributeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserAttributeDto.java new file mode 100644 index 0000000000000000000000000000000000000000..ee3e1252788c06df6d94857eaf76bc84bc78c175 --- /dev/null +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserAttributeDto.java @@ -0,0 +1,34 @@ +package at.tuwien.api.user; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import javax.validation.constraints.NotNull; + +@Getter +@Setter +@ToString +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class UserAttributeDto { + + @NotNull + @JsonIgnore + private String id; + + @NotNull + @JsonIgnore + @JsonProperty("user_id") + @Schema(example = "1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4") + private String userId; + + @Schema(example = "theme_dark") + private String name; + + @Schema(example = "true") + private String value; + +} diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java index 43d341d894daa062c6881a55a36163ea44b5afce..6d198b70979e860dcec789a96706a479650bb5b4 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java @@ -19,7 +19,7 @@ import java.util.List; public class UserBriefDto { @NotNull - @JsonProperty("sub") + @Schema(example = "1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4") private String id; @NotNull @@ -37,7 +37,6 @@ public class UserBriefDto { @Schema(example = "Carberry") private String lastname; - @JsonIgnore @JsonProperty("email_verified") @Schema(example = "true") @org.springframework.data.annotation.Transient diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java index 793be6f7f6ae3f6a5c31c0b084b092d399560c34..3796e6c80f13f5d0b3cf6fcb9f15aa88178e61ee 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java @@ -18,7 +18,7 @@ import java.util.List; public class UserDto { @NotNull - @JsonProperty("sub") + @Schema(example = "1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4") private String id; @NotNull @@ -36,6 +36,10 @@ public class UserDto { @Schema(example = "Carberry") private String lastname; + @EqualsAndHashCode.Exclude + @org.springframework.data.annotation.Transient + private List<UserAttributeDto> attributes; + @EqualsAndHashCode.Exclude @org.springframework.data.annotation.Transient private List<ContainerDto> containers; diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java index 87d933a27d2a9bb2719ed5590c7679065a79df0c..75db0aa7076363314e89b5bbb522568464772c87 100644 --- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java @@ -32,13 +32,13 @@ public class User { @Column(unique = true, nullable = false) private String username; - @Column(name = "first_name") + @Column(name = "FIRST_NAME") private String firstname; - @Column(name = "last_name") + @Column(name = "LAST_NAME") private String lastname; - @Column(name = "realm_id") + @Column(name = "REALM_ID") private String realmId; @Column(unique = true, nullable = false) @@ -60,9 +60,14 @@ public class User { @Column(nullable = false) @ToString.Exclude - @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user") + @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user") private List<Role> roles; + @Column(nullable = false) + @ToString.Exclude + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user") + private List<UserAttribute> attributes; + @Column(nullable = false) @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user") private List<Credential> credentials; diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java new file mode 100644 index 0000000000000000000000000000000000000000..c0bf71be22e6c2ef7fd0b208a9a1ed5bb3e8aa4c --- /dev/null +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java @@ -0,0 +1,46 @@ +package at.tuwien.entities.user; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.*; +import org.hibernate.annotations.GenericGenerator; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; + +@Data +@Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ToString +@EntityListeners(AuditingEntityListener.class) +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@Table(name = "user_attribute") +public class UserAttribute { + + @Id + @JsonIgnore + @EqualsAndHashCode.Include + @GeneratedValue(generator = "attribute-uuid") + @GenericGenerator(name = "attribute-uuid", strategy = "org.hibernate.id.UUIDGenerator") + @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + private String id; + + @JsonIgnore + @Column(name = "USER_ID", nullable = false) + private String userId; + + @Column(name = "NAME", nullable = false) + private String name; + + @Column(name = "VALUE") + private String value; + + @ToString.Exclude + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumns({ + @JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false) + }) + private User user; + +} diff --git a/fda-metadata-db/setup-schema.sql b/fda-metadata-db/setup-schema.sql index d390aac4874431231bd4095e7abacedd30ba0c60..b78ca3ab39f8360b1fbac1399ae98c83e7c64bd0 100644 --- a/fda-metadata-db/setup-schema.sql +++ b/fda-metadata-db/setup-schema.sql @@ -469,6 +469,7 @@ VALUES ('ROOT', 'root', 'PRIVILEGED_USERNAME', 1), INSERT INTO `fda`.`mdb_images_date` (iid, database_format, unix_format, example, has_time) VALUES (1, '%Y-%c-%d %H:%i:%S.%f', 'yyyy-MM-dd HH:mm:ss.SSSSSS', '2022-01-30 13:44:25.499', true), - (1, '%Y-%c-%d %H:%i:%S', 'yyyy-MM-dd HH:mm:ss', '2022-01-30 13:44:25', true); + (1, '%Y-%c-%d %H:%i:%S', 'yyyy-MM-dd HH:mm:ss', '2022-01-30 13:44:25', true), + (1, '%Y-%c-%d', 'yyyy-MM-dd', '2022-01-30', false); COMMIT; diff --git a/fda-metadata-service/Dockerfile b/fda-metadata-service/Dockerfile index 8e945b6e1f8ce282b27b90787050b5256ef681c0..0eb916d2c91e161d2f19878e324375116f24ad84 100644 --- a/fda-metadata-service/Dockerfile +++ b/fda-metadata-service/Dockerfile @@ -25,26 +25,17 @@ ENV METADATA_DB=fda ENV METADATA_USERNAME=root ENV METADATA_PASSWORD=dbrepo ENV GATEWAY_ENDPOINT=https://gateway-service:9095 -ENV PID_BASE="https://example.com/pid/" +ENV PID_BASE="http://example.com/pid/" ENV REPOSITORY_NAME="Example Repository" -ENV BASE_URL="https://example.com" +ENV BASE_URL="http://example.com" ENV ADMIN_MAIL="noreply@example.com" ENV EARLIEST_DATESTAMP="2022-09-17T18:23:00Z" ENV DELETED_RECORD=persistent ENV GRANULARITY="YYYY-MM-DDThh:mm:ssZ" ENV LOG_LEVEL=debug -ENV KEY_ALIAS=metadata-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -54,4 +45,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./metadata-service.ja EXPOSE 9090 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./metadata-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./metadata-service.jar"] diff --git a/fda-metadata-service/rest-service/src/main/resources/application-insecure.yml b/fda-metadata-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index e2c8e24b3f7a9b75f086ab9752ff0ae0cdc4af05..0000000000000000000000000000000000000000 --- a/fda-metadata-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,62 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: metadata-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9099 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: metadata-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9099 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - ready.path: ./ready - pid.base: "${PID_BASE}" - gateway.endpoint: "${GATEWAY_ENDPOINT}" -dbrepo: - repository-name: "${REPOSITORY_NAME}" - base-url: "${BASE_URL}" - admin-email: "${ADMIN_MAIL}" - earliest-datestamp: "${EARLIEST_DATESTAMP}" - deleted-record: "${DELETED_RECORD}" - granularity: "${GRANULARITY}" diff --git a/fda-metadata-service/rest-service/src/main/resources/application-local.yml b/fda-metadata-service/rest-service/src/main/resources/application-local.yml index f50a1d555e2df503752e2fe6f2e347eceaa65539..fc3b8e3fb5df0de4a4f8e4d3959072ef598f5cbe 100644 --- a/fda-metadata-service/rest-service/src/main/resources/application-local.yml +++ b/fda-metadata-service/rest-service/src/main/resources/application-local.yml @@ -22,20 +22,9 @@ spring: name: metadata-service cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true management.endpoints.web.exposure.include: health,info,prometheus server: port: 9099 - ssl: - enabled: true - key-alias: metadata-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -51,11 +40,11 @@ eureka: client.serviceUrl.defaultZone: http://localhost:9090/eureka/ fda: ready.path: ./ready - pid.base: https://example.com/pid/ + pid.base: http://example.com/pid/ gateway.endpoint: http://localhost:9095 dbrepo: repository-name: TU Wien Database Repository - base-url: https://dbrepo.ossdip.at/api/oai + base-url: http://dbrepo.ossdip.at/api/oai admin-email: noreply@example.com earliest-datestamp: 2022-09-17T16:09:00Z deleted-record: persistent diff --git a/fda-metadata-service/rest-service/src/main/resources/application.yml b/fda-metadata-service/rest-service/src/main/resources/application.yml index c83d16237a1572dfc21ad30b55b8e4ecbf747921..1a81f97ef818aeeba391f917d907038ff8f1e556 100644 --- a/fda-metadata-service/rest-service/src/main/resources/application.yml +++ b/fda-metadata-service/rest-service/src/main/resources/application.yml @@ -29,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9099 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,9 +38,7 @@ logging: eureka: instance: hostname: metadata-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9099 + non-secure-port: 9099 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: ready.path: ./ready diff --git a/fda-metadata-service/root.crt b/fda-metadata-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-metadata-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-metadata-service/server.keystore b/fda-metadata-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-metadata-service/server.keystore and /dev/null differ diff --git a/fda-query-service/Dockerfile b/fda-query-service/Dockerfile index b1a49ccaee8dffff09052f6b8116a2b078a45cfc..a4d4c52a4b50dd84bfe21a77c175f51751275da4 100644 --- a/fda-query-service/Dockerfile +++ b/fda-query-service/Dockerfile @@ -27,7 +27,7 @@ ENV METADATA_USERNAME=root ENV METADATA_PASSWORD=dbrepo ENV BROKER_USERNAME=fda ENV BROKER_PASSWORD=fda -ENV GATEWAY_ENDPOINT=https://gateway-service:9095 +ENV GATEWAY_ENDPOINT=http://gateway-service:9095 ENV SHARED_FILESYSTEM=/tmp ENV BROKER_CONSUMERS=2 ENV LOG_LEVEL=debug @@ -36,18 +36,9 @@ ENV CLIENT_ID=dbrepo-client ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key ENV NOT_SUPPORTED_KEYWORDS=\\*,AVG,BIT_AND,BIT_OR,BIT_XOR,COUNT,COUNTDISTINCT,GROUP_CONCAT,JSON_ARRAYAGG,JSON_OBJECTAGG,MAX,MIN,STD,STDDEV,STDDEV_POP,STDDEV_SAMP,SUM,VARIANCE,VAR_POP,VAR_SAMP,-- -ENV KEY_ALIAS=query-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -57,4 +48,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./query-service.jar EXPOSE 9093 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./query-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./query-service.jar"] diff --git a/fda-query-service/intermediate.crt b/fda-query-service/intermediate.crt deleted file mode 100644 index 6b8e17c27ea8e5337a7c0aee7bc720dab08dac44..0000000000000000000000000000000000000000 --- a/fda-query-service/intermediate.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDaDCCAlCgAwIBAgIEH/QufDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTc1MDQ0WhcNMjMwNzAyMTc1MDQ0WjBJMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMRcwFQYDVQQD -Ew5JbnRlcm1lZGlhdGVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKPTnhNdSjVJvRT6jBQuNWOYAeukC1hVAAuiOtU6QqQANFLRHACFQGs/QJkh1LRt -HoNvN2W0EEljUQ5pgSym76xPXCg38OYmsV4w0gcSe34QyCCWkB82eBi48MEmsb6s -x7n3uM+SaSwaFqxZFTQszsEVOJcnfRDBhYkT3juiuW0HzmMCuDa/V1sl1HgxbKRc -zEXEk3PjDY12gsYNzF1jgB33Nwh692npdBca5MXJ+Gi0zvnM+1JgrfIYayC37+ZF -UG10LYTSV4rG4NS9UzF/cBK9naddMgCgqIMGHnU5Z5N+PNPiHZ4WkX4Xf4Zu1WTg -YGlsVjgNKTX6CYytrRwbWKUCAwEAAaNgMF4wHQYDVR0OBBYEFF5md9arqKs42p+W -jhWXGwgVMmDKMAsGA1UdDwQEAwICBDAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY -MBaAFJ0un4jfS4HiMAw/U+dkuiXFsX8DMA0GCSqGSIb3DQEBCwUAA4IBAQAviRt0 -PEHhiEOzEqI45XfnRNGntYdKHRKoftRIg2HM9drVKygZ85EBeiceyhX7U2O91X+i -zKionrqgpZrjO/rJc0R7QEVN2McCqFQEAu4AgZh4hcbhzjZVo74gQkCFnsTwQXwQ -/UB0exd5Qw1zcbgn4I+LcJaApvwZ5tTCvFDX20W7dSpxhqBPnU5dV92HoXqCX9H3 -8fgX8rK3PWoYKPuXHNcjhlG0d8FxNoxRKRJRUyUwT4UC/LJE5HZR8zTVcIPR/nlD -c2V539v4myGmZdWc8OYee09OPIDtjT2zejEmTpP3fPtvHdoTe59UGWMkYn830H4Z -U/v3rj9nHwAoTytU ------END CERTIFICATE----- diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java index 356a3fc77ae7d5d975277e1d17c95454585b95c2..cf5131b684e122b4b3adaccdfa685921a41d671d 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java @@ -35,7 +35,6 @@ public class ExportEndpoint { @GetMapping @Transactional(readOnly = true) - @PreAuthorize("hasAuthority('export-table')") @Timed(value = "table.export", description = "Time needed to export table data") @Operation(summary = "Export table", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<InputStreamResource> export(@NotNull @PathVariable("id") Long containerId, @@ -46,6 +45,7 @@ public class ExportEndpoint { throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, ContainerNotFoundException, FileStorageException, QueryMalformedException, UserNotFoundException { + // TODO: check if authority 'export-table' log.debug("endpoint export table, id={}, databaseId={}, tableId={}, timestamp={}, principal={}", containerId, databaseId, tableId, timestamp, principal); final HttpHeaders headers = new HttpHeaders(); diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java index af50ebc896b565413187f4484966f0757ced1a86..2446b606bba7f9a7369d2fec6c1d130961d5807f 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java @@ -109,9 +109,9 @@ public class QueryEndpoint { @Timed(value = "query.reexecute.count", description = "Time needed to re-execute a query") @Operation(summary = "Re-execute some query", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<Long> reExecuteCount(@NotNull @PathVariable("id") Long containerId, - @NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("queryId") Long queryId, - Principal principal) + @NotNull @PathVariable("databaseId") Long databaseId, + @NotNull @PathVariable("queryId") Long queryId, + Principal principal) throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, TableMalformedException, ColumnParseException, NotAllowedException, DatabaseConnectionException, UserNotFoundException { @@ -127,7 +127,6 @@ public class QueryEndpoint { @GetMapping("/{queryId}/export") @Transactional(readOnly = true) - @PreAuthorize("hasAuthority('export-query')") @Timed(value = "query.export", description = "Time needed to export query data") @Operation(summary = "Exports some query", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<?> export(@NotNull @PathVariable("id") Long containerId, @@ -136,11 +135,11 @@ public class QueryEndpoint { @RequestHeader(HttpHeaders.ACCEPT) String accept, Principal principal) throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, TableMalformedException, FileStorageException, NotAllowedException, - QueryMalformedException, DatabaseConnectionException, UserNotFoundException { + ContainerNotFoundException, TableMalformedException, FileStorageException, QueryMalformedException, + DatabaseConnectionException, UserNotFoundException { + // TODO: check if authority 'export-query-data' log.debug("endpoint export query, containerId={}, databaseId={}, queryId={}, accept={}, principal={}", containerId, databaseId, queryId, accept, principal); - log.trace("checking if query exists in the query store"); final Query query = storeService.findOne(containerId, databaseId, queryId, principal); log.trace("querystore returned query {}", query); final ExportResource resource = queryService.findOne(containerId, databaseId, queryId, principal); diff --git a/fda-query-service/rest-service/src/main/resources/application-insecure.yml b/fda-query-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 7aee796534edcd986653692bd66447e73e301a76..0000000000000000000000000000000000000000 --- a/fda-query-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,69 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: query-service - rabbitmq: - host: broker-service - username: fda - password: fda - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9093 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: query-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9093 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - gateway.endpoint: "${GATEWAY_ENDPOINT}" - ready.path: /ready - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" - client_secret: "${DBREPO_CLIENT_SECRET}" - client_id: "${CLIENT_ID}" - consumers: 2 - unsupported: "${NOT_SUPPORTED_KEYWORDS}" - elastic: - endpoint: search-service:9200 - username: elastic - password: "${ELASTIC_PASSWORD}" diff --git a/fda-query-service/rest-service/src/main/resources/application-local.yml b/fda-query-service/rest-service/src/main/resources/application-local.yml index 54d56d9838609ddbdb48772d92de993eed9118fd..c842574f67fcb19dd703fd5ee87861d0d84e3598 100644 --- a/fda-query-service/rest-service/src/main/resources/application-local.yml +++ b/fda-query-service/rest-service/src/main/resources/application-local.yml @@ -33,13 +33,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9093 - ssl: - enabled: true - key-alias: query-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -49,15 +42,13 @@ logging: eureka: instance: hostname: query-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9093 + non-secure-port: 9093 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: gateway.endpoint: http://localhost:9095 ready.path: ./ready jwt: - issuer: https://localhost:8443/realms/dbrepo + issuer: http://localhost:8443/realms/dbrepo public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB client_secret: client-secret client_id: dbrepo-client diff --git a/fda-query-service/rest-service/src/main/resources/application.yml b/fda-query-service/rest-service/src/main/resources/application.yml index 852aa812c533881a4a19132e8385e63986bde698..df6ca210fb0604969f43b73973b6c913cdf66f9e 100644 --- a/fda-query-service/rest-service/src/main/resources/application.yml +++ b/fda-query-service/rest-service/src/main/resources/application.yml @@ -29,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9093 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,9 +38,7 @@ logging: eureka: instance: hostname: query-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9093 + non-secure-port: 9093 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: gateway.endpoint: "${GATEWAY_ENDPOINT}" diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java index f0d75ef9991ad9fc5fae785956338b8792d6b66a..32e8364efbbf3900c25225d4c20e780e22217189 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java @@ -216,6 +216,36 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { }); } + @Test + public void insert_date_succeeds() throws InterruptedException, UserNotFoundException, TableNotFoundException, + TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException, ImageNotSupportedException, + ContainerNotFoundException, SQLException { + final TableCsvDto request = TableCsvDto.builder() + .data(new HashMap<>() {{ + put("id", 4L); + put("date", "2022-10-30"); + put("location", "Sydney"); + put("mintemp", 10L); + put("rainfall", 23.1); + }}).build(); + + /* mock */ + DockerConfig.createContainer(BIND_WEATHER, CONTAINER_1, CONTAINER_1_ENV); + DockerConfig.startContainer(CONTAINER_1); + when(databaseRepository.findByContainerIdAndDatabaseId(CONTAINER_1_ID, DATABASE_1_ID)) + .thenReturn(Optional.of(DATABASE_1)); + when(tableRepository.find(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID)) + .thenReturn(Optional.of(TABLE_1)); + + /* test */ + queryService.insert(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request, USER_1_PRINCIPAL); + final List<Map<String, String>> response = MariaDbConfig.selectQuery(CONTAINER_1_INTERNALNAME, DATABASE_1_INTERNALNAME, "SELECT `id`, `date`, `location` FROM `weather_aus` WHERE `id` = 4", "id", "date", "location"); + final Map<String, String> row1 = response.get(0); + assertEquals("4", row1.get("id")); + assertEquals("2022-10-30", row1.get("date")); + assertEquals("Sydney", row1.get("location")); + } + @Test public void insert_timestamp_succeeds() throws UserNotFoundException, TableNotFoundException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException, ImageNotSupportedException, diff --git a/fda-query-service/root.crt b/fda-query-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-query-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-query-service/server.keystore b/fda-query-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-query-service/server.keystore and /dev/null differ diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java index d85aaa7553b825ee12715bc4e8bb2a1176e865e1..0506192ecb16e1be14a9561614f214a10c0c8a5b 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java @@ -440,7 +440,7 @@ public interface QueryMapper { .findFirst(); if (tuple.isEmpty()) { log.error("Failed to map column name {}, known names: {}", column.getInternalName(), data.getData().keySet()); - throw new TableMalformedException("Failed to map column names"); + throw new TableMalformedException("Failed to map column names: not all columns are present in the tuple!"); } prepareStatementWithColumnTypeObject(pstmt, column.getColumnType(), idx[0]++, tuple.get().getValue()); } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java index a1dc0a91b336c9f1f8485ec7a167a6477487291e..1421c00dba97adf6817b32d46337eda1b39a881d 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java @@ -363,7 +363,6 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService throw new TableMalformedException("Failed to parse number: " + e.getMessage(), e); } catch (Exception e) { log.error("Database failed to accept tuple: {}", e.getMessage()); - log.throwing(e); throw new TableMalformedException("Database failed to accept tuple: " + e.getMessage(), e); } finally { dataSource.close(); diff --git a/fda-table-service/Dockerfile b/fda-table-service/Dockerfile index 42040d8660b3987e3ce270293c94c3c8d0c876ab..8d3ed94d45eda4eb97ff96c4b2bdebe16595cee4 100644 --- a/fda-table-service/Dockerfile +++ b/fda-table-service/Dockerfile @@ -33,25 +33,16 @@ ENV DBREPO_CLIENT_SECRET=client-secret ENV CLIENT_ID=dbrepo-client ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key -ENV KEY_ALIAS=table-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready HEALTHCHECK --interval=10s --timeout=5s --retries=12 CMD service_ready -COPY --from=build ./rest-service/target/rest-service-*.jar ./container-service.jar +COPY --from=build ./rest-service/target/rest-service-*.jar ./table-service.jar EXPOSE 9091 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./container-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./table-service.jar"] diff --git a/fda-table-service/rest-service/src/main/resources/application-docker.yml b/fda-table-service/rest-service/src/main/resources/application-docker.yml deleted file mode 100644 index 63633fa2b7bd36f096e28dd8bfbb51abcb58c3a1..0000000000000000000000000000000000000000 --- a/fda-table-service/rest-service/src/main/resources/application-docker.yml +++ /dev/null @@ -1,67 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: table-service - rabbitmq: - host: broker-service - username: fda - password: fda - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9094 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: table-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9094 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - ready.path: /ready - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" - client_secret: "${DBREPO_CLIENT_SECRET}" - client_id: "${CLIENT_ID}" - gateway.endpoint: "${GATEWAY_ENDPOINT}" - elastic: - endpoint: search-service:9200 - username: elastic - password: "${ELASTIC_PASSWORD}" \ No newline at end of file diff --git a/fda-table-service/rest-service/src/main/resources/application-local.yml b/fda-table-service/rest-service/src/main/resources/application-local.yml index 61ce9d5f263e2abbe1f7c2528eae3c9347b32322..87f46f3a0aa32935fdb312f4212bd6e10fa2e3ee 100644 --- a/fda-table-service/rest-service/src/main/resources/application-local.yml +++ b/fda-table-service/rest-service/src/main/resources/application-local.yml @@ -26,20 +26,9 @@ spring: password: fda cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true management.endpoints.web.exposure.include: health,info,prometheus server: port: 9094 - ssl: - enabled: true - key-alias: table-service - key-store: ./server.keystore - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -49,14 +38,12 @@ logging: eureka: instance: hostname: table-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9094 + non-secure-port: 9094 client.serviceUrl.defaultZone: http://localhost:9090/eureka/ fda: ready.path: ./ready jwt: - issuer: https://localhost:8443/realms/dbrepo + issuer: http://localhost:8443/realms/dbrepo public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB client_secret: client-secret client_id: dbrepo-client diff --git a/fda-table-service/rest-service/src/main/resources/application.yml b/fda-table-service/rest-service/src/main/resources/application.yml index 0d6a27d62ba39d15b53e619f2f6a8ace337aeb3d..65c0aed65a13be256b13dd2c0af3ca3020778ac4 100644 --- a/fda-table-service/rest-service/src/main/resources/application.yml +++ b/fda-table-service/rest-service/src/main/resources/application.yml @@ -29,13 +29,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9094 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,9 +38,7 @@ logging: eureka: instance: hostname: table-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9094 + non-secure-port: 9094 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: ready.path: /ready diff --git a/fda-table-service/root.crt b/fda-table-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-table-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-table-service/server.keystore b/fda-table-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-table-service/server.keystore and /dev/null differ diff --git a/fda-ui/Dockerfile b/fda-ui/Dockerfile index 14cb15e7bf5f7f08c781f05170f2170f45cb4874..2c2cd8c402e018c2986ad4c6e92e84cf8f821f0b 100644 --- a/fda-ui/Dockerfile +++ b/fda-ui/Dockerfile @@ -43,7 +43,6 @@ EXPOSE 3000 EXPOSE 9100 ENV API=https://gateway-service:9095 -ENV KEYCLOAK=https://authentication-service:8443 ENV BROKER_USERNAME=fda ENV BROKER_PASSWORD=fda ENV SANDBOX=false @@ -59,13 +58,6 @@ ENV DBREPO_CLIENT_SECRET=client-secret WORKDIR /app -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - -ENV NODE_OPTIONS=--use-openssl-ca -ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/DBRepo_Root_CA.crt - COPY --from=build /usr/local/bin/node_exporter/ /usr/local/bin/node_exporter/ COPY --from=build /app /app diff --git a/fda-ui/api/query/index.js b/fda-ui/api/query/index.js new file mode 100644 index 0000000000000000000000000000000000000000..e76cc2da4fb545a56bcf506e94018f2469a05315 --- /dev/null +++ b/fda-ui/api/query/index.js @@ -0,0 +1,17 @@ +const axios = require('axios/dist/browser/axios.cjs') + +export function findQuery (token, containerId, databaseId, queryId) { + return axios.get(`/api/container/${containerId}/database/${databaseId}/query/${queryId}`, { + headers: { + Authorization: `Bearer ${token}` + } + }) +} + +export function persistQuery (token, containerId, databaseId, queryId) { + return axios.put(`/api/container/${containerId}/database/${databaseId}/query/${queryId}`, {}, { + headers: { + Authorization: `Bearer ${token}` + } + }) +} diff --git a/fda-ui/api/user/index.js b/fda-ui/api/user/index.js index feb0b974e728e86401d28db318a4e1d5abe03770..3d8cc4f73825ce4e6c126c7cc4db1244644bb479 100644 --- a/fda-ui/api/user/index.js +++ b/fda-ui/api/user/index.js @@ -17,11 +17,41 @@ export function authenticate (clientSecret, username, password) { }) } -export function userinfo (clientSecret, token) { - return axios.get('/api/auth/realms/dbrepo/protocol/openid-connect/userinfo', { +export function updateUser (token, userId, data) { + return axios.put(`/api/user/${userId}`, data, { headers: { - Authorization: `Bearer ${token}`, - ContentType: 'application/form-data' + Authorization: `Bearer ${token}` + } + }) +} + +export function updateUserPassword (token, userId, password) { + const payload = { + password + } + return axios.put(`/api/user/${userId}/password`, payload, { + headers: { + Authorization: `Bearer ${token}` + } + }) +} + +export function toggleUserTheme (token, userId, themeDark) { + const payload = { + theme_dark: themeDark + } + return axios.put(`/api/user/${userId}/theme`, payload, { + headers: { + Authorization: `Bearer ${token}` + } + }) +} + +export function findUser (token) { + const user = tokenToUser(token) + return axios.get(`/api/user/${user.id}`, { + headers: { + Authorization: `Bearer ${token}` } }) } @@ -64,3 +94,10 @@ export function tokenToRoles (token) { } return data.realm_access.roles || [] } + +export function getThemeDark (user) { + if (!user || !user.attributes || user.attributes.filter(a => a.name === 'theme_dark').length === 0) { + return false + } + return user.attributes.filter(a => a.name === 'theme_dark')[0].value === 'true' +} diff --git a/fda-ui/components/DBToolbar.vue b/fda-ui/components/DBToolbar.vue index 3da290a9fa7b4fa5678c9962546df0ee3bf0eabe..026f7dce95417d0e4ba4a9d7addc3d4e5db350f3 100644 --- a/fda-ui/components/DBToolbar.vue +++ b/fda-ui/components/DBToolbar.vue @@ -85,29 +85,32 @@ export default { token () { return this.$store.state.token }, + roles () { + return this.$store.state.roles + }, canImportCsv () { if (!this.user) { return false } - return this.user.roles.includes('insert-table-data') + return this.roles.includes('insert-table-data') }, canCreateSubset () { if (!this.user) { return false } - return this.user.roles.includes('execute-query') + return this.roles.includes('execute-query') }, canCreateView () { if (!this.user) { return false } - return this.user.roles.includes('create-database-view') + return this.roles.includes('create-database-view') }, canCreateTable () { if (!this.user) { return false } - return this.user.roles.includes('create-table') + return this.roles.includes('create-table') }, isOwner () { if (!this.database || !this.user) { diff --git a/fda-ui/components/DatabaseList.vue b/fda-ui/components/DatabaseList.vue index 81e96814351acfe3f16a99e3a0a48cc0e84158d7..eed62c7875edd8b3551048ea6a62deb266240047 100644 --- a/fda-ui/components/DatabaseList.vue +++ b/fda-ui/components/DatabaseList.vue @@ -149,8 +149,8 @@ export default { } catch (error) { this.error = true console.error('Failed to retrieve containers', error) - const { message } = error.response.data - this.$toast.error(`Failed to retrieve containers: ${message}`) + const { statusText } = error.response + this.$toast.error(`Failed to retrieve containers: ${statusText}`) } this.loadingContainers = false }, diff --git a/fda-ui/components/TableSchema.vue b/fda-ui/components/TableSchema.vue index cdc1be5754142529ad10dac4e379ec35c50fe2c0..2042009818d6417217b0e2ef4b5ffe30857565ae 100644 --- a/fda-ui/components/TableSchema.vue +++ b/fda-ui/components/TableSchema.vue @@ -90,7 +90,7 @@ <v-btn v-if="back" class="mt-10 mr-2 mb-1" @click="stepBack()"> Back </v-btn> - <v-btn color="primary" :loading="finished && !error" :disabled="!valid" class="mt-10 mb-1" @click="submit()"> + <v-btn color="primary" :loading="loading" :disabled="!valid" class="mt-10 mb-1" @click="submit()"> Continue </v-btn> </div> @@ -219,11 +219,7 @@ export default { name, type, null_allowed, - primary_key, - check_expression: null, - foreign_key: null, - references: null, - unique + primary_key }) } } diff --git a/fda-ui/components/TableToolbar.vue b/fda-ui/components/TableToolbar.vue index 6784739e098ceff152b8202268208af7e0ecd658..1469c3c3fbe22ce3143f25b79e8ea3ef786c4788 100644 --- a/fda-ui/components/TableToolbar.vue +++ b/fda-ui/components/TableToolbar.vue @@ -93,50 +93,71 @@ export default { user () { return this.$store.state.user }, + roles () { + return this.$store.state.roles + }, token () { return this.$store.state.token }, canAddTuple () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('insert-table-data') + if (!this.isDataTab) { + return false + } + return this.roles.includes('insert-table-data') }, canEditTuple () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('insert-table-data') + if (!this.isDataTab) { + return false + } + return this.roles.includes('insert-table-data') }, canDeleteTuple () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('delete-table-data') + if (!this.isDataTab) { + return false + } + return this.roles.includes('delete-table-data') }, canExecuteQuery () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('execute-query') + return this.roles.includes('execute-query') }, canCreateView () { if (!this.user) { return false } - return this.user.roles.includes('create-database-view') + return this.roles.includes('create-database-view') }, canReadData () { - if (!this.user) { + if (!this.database) { + return false + } + if (this.database.is_public) { + return true + } + if (!this.roles) { return false } - return this.user.roles.includes('view-table-data') + return this.roles.includes('view-table-data') }, canImportCsv () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('insert-table-data') + return this.roles.includes('insert-table-data') + }, + isDataTab () { + return String(this.tab).endsWith('data') }, tuple () { return this.edit ? this.selection[0] : {} diff --git a/fda-ui/components/UserToolbar.vue b/fda-ui/components/UserToolbar.vue index 4fc6b82ee0064a4e93c62c73850ed67f08b736f1..5eb2113386e259091babc67dbfdfff9c2a1e08eb 100644 --- a/fda-ui/components/UserToolbar.vue +++ b/fda-ui/components/UserToolbar.vue @@ -12,7 +12,7 @@ <v-tab to="/user/authentication"> Authentication </v-tab> - <v-tab v-if="isDeveloper || isResearcher" to="/user/developer"> + <v-tab v-if="false" to="/user/developer"> Developer </v-tab> </v-tabs> diff --git a/fda-ui/config.js b/fda-ui/config.js index e2bc44ee35ecae1e00629b55538f13239466bb1e..9cce6f7341a6fd088bec683edfa7053fe92e4507 100644 --- a/fda-ui/config.js +++ b/fda-ui/config.js @@ -1,6 +1,6 @@ const config = {} -config.api = process.env.API || 'https://gateway-service:9095' +config.api = process.env.API || 'http://gateway-service:9095' config.search = process.env.SEARCH || 'http://localhost:9200' config.sandbox = process.env.SANDBOX || false config.title = process.env.TITLE || 'Database Repository' diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue index 064a8436d0588c230a041f253fc5c40c68d6a707..0a00d0939634f08dd911b7f072aab09e5f23a572 100644 --- a/fda-ui/layouts/default.vue +++ b/fda-ui/layouts/default.vue @@ -130,7 +130,7 @@ <script> import { isDeveloper } from '@/utils' -import { tokenToUser, tokenToExp, refresh } from '@/api/user' +import { findUser, getThemeDark, tokenToRoles } from '@/api/user' export default { name: 'DefaultLayout', data () { @@ -241,7 +241,6 @@ export default { if (this.$route.query && this.$route.query.q) { this.search = this.$route.query.q } - this.refreshTokenIfNecessary() }, methods: { submit () { @@ -256,69 +255,41 @@ export default { this.$toast.warning(message) } this.$store.commit('SET_TOKEN', null) - this.$store.commit('SET_REFRESH_TOKEN', null) + this.$store.commit('SET_ROLES', []) this.$store.commit('SET_USER', null) this.$store.commit('SET_ACCESS', null) this.$vuetify.theme.dark = false this.$router.push('/container') }, - loadUser () { + async loadUser () { if (!this.token) { return } try { this.loadingUser = true - const user = tokenToUser(this.token) + const res = await findUser(this.token) + const user = res.data console.debug('user', user) this.$store.commit('SET_USER', user) - this.$vuetify.theme.dark = user.theme_dark + const roles = tokenToRoles(this.token) + this.$store.commit('SET_ROLES', roles) + this.$vuetify.theme.dark = getThemeDark(user) this.loading = false - } catch (err) { - console.error('Failed to load user', err) - const { status } = err.response + } catch (error) { + console.error('Failed to load user', error) + const { status } = error.response if (status === 401) { - console.error('Token expired', err) + console.error('Token expired', error) this.$toast.warning('Login has expired') this.logout() } else { - console.error('user data', err) + console.error('user data', error) this.$toast.error('Failed to load user') this.error = true } } this.loadingUser = false }, - async refreshTokenIfNecessary () { - if (!this.token) { - return - } - const exp = tokenToExp(this.token) - if (exp > new Date()) { - const timeout = (exp - new Date()) > 0 ? exp - new Date() : 0 - console.debug('token will be refreshed', exp, 'timeout is', timeout) - setTimeout(() => this.refreshTokenIfNecessary(), timeout) - return - } - const refreshExp = tokenToExp(this.refreshToken) - if (refreshExp > new Date()) { - try { - const res = await refresh(this.clientSecret, this.refreshToken) - // eslint-disable-next-line camelcase - const { access_token, refresh_token } = res.data - this.$store.commit('SET_TOKEN', access_token) - this.$store.commit('SET_REFRESH_TOKEN', refresh_token) - console.info('refreshed tokens') - const user = tokenToUser(this.token) - console.debug('user', user) - this.$store.commit('SET_USER', user) - return - } catch (error) { - console.error('Failed to login', error) - this.$toast.error('Failed to refresh tokens') - } - } - this.logout('Your session has expired') - }, async loadDatabase () { if (!this.$route.params.container_id || !this.$route.params.database_id) { return diff --git a/fda-ui/package.json b/fda-ui/package.json index 2548fe968b7e116e56a99218d5e85e775b56055c..ff23e62ae94a9fff5f6ad2d24cc4092fa5e861d5 100644 --- a/fda-ui/package.json +++ b/fda-ui/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "dev": "NODE_OPTIONS=--use-openssl-ca NODE_EXTRA_CA_CERTS=./root.crt nuxt --port 3001", + "dev": "nuxt --port 3001", "docker": "nuxt > /dev/null", "build": "nuxt build", "start": "nuxt start", diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue index 0eebace71286ad4c51a7ce7e9173dc11f6fd83e0..8db247d37184d1b2393fa617e09da947cb2fbdd6 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue @@ -266,6 +266,9 @@ export default { user () { return this.$store.state.user }, + roles () { + return this.$store.state.roles + }, identifier () { if (!this.database) { return null @@ -313,22 +316,22 @@ export default { if (!this.user) { return false } - return this.canCreateIdentifier || this.canDeleteIdentifier || this.user.roles.includes('modify-identifier-metadata') + return this.canCreateIdentifier || this.canDeleteIdentifier || this.roles.includes('modify-identifier-metadata') }, canCreateIdentifier () { - if (!this.user) { + if (!this.roles) { return false } if (this.hasIdentifier) { return false } - return this.user.roles.includes('create-identifier') + return this.roles.includes('create-identifier') }, canDeleteIdentifier () { if (!this.user) { return false } - return this.user.roles.includes('delete-identifier') + return this.roles.includes('delete-identifier') }, contact () { if (this.database.contact === null || this.database.contact === undefined) { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue index 4ca589d1527db7c2bd3eea1a845348c3f3d2d9c9..264b049ac42b4b1eff211caed58e932394950d1d 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue @@ -14,7 +14,7 @@ <v-btn v-if="!query.is_persisted && canWrite" :loading="loadingSave" class="mb-1 mr-2" @click.stop="save"> <v-icon left>mdi-content-save-outline</v-icon> Save </v-btn> - <v-btn v-if="query.is_persisted && !query.identifier && canWrite" class="mb-1 mr-2" color="primary" :disabled="error || !executionUTC" @click.stop="openDialog()"> + <v-btn v-if="query.is_persisted && !query.identifier && canWrite" class="mb-1 mr-2" color="primary" :disabled="!executionUTC" @click.stop="openDialog()"> <v-icon left>mdi-content-save-outline</v-icon> Get PID </v-btn> <v-btn v-if="result_visibility && !query.identifier && query.result_number" class="mb-1" :loading="downloadLoading" @click.stop="downloadData"> @@ -221,6 +221,7 @@ import Persist from '@/components/dialogs/Persist' import Citation from '@/components/identifier/Citation' import { formatTimestampUTCLabel, formatDateUTC } from '@/utils' +import { findQuery, persistQuery } from '@/api/query' export default { name: 'QueryShow', @@ -424,7 +425,7 @@ export default { async loadQuery () { this.loadingQuery = true try { - const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/query/${this.$route.params.query_id}`, this.config) + const res = await findQuery(this.token, this.$route.params.container_id, this.$route.params.database_id, this.$route.params.query_id) console.info('load query', res.data) this.query = res.data } catch (err) { @@ -440,12 +441,12 @@ export default { async save () { this.loadingSave = true try { - const res = await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/query/${this.$route.params.query_id}`, {}, this.config) - console.info('save query', res.data) + const res = await persistQuery(this.token, this.$route.params.container_id, this.$route.params.database_id, this.$route.params.query_id) + console.info('persisted query', res.data) this.query = res.data - } catch (err) { - console.error('Failed to save query', err) - this.$toast.error('Failed to save query') + } catch (error) { + console.error('Failed to persisted query', error) + this.$toast.error('Failed to persisted query') this.error = true } this.loadingSave = false diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue index 52ca422a0a3dfd592e10acd9eb67c442f33a3692..dd5c10a9e73cd3154a62dd00304457c9e333d5d9 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue @@ -28,11 +28,14 @@ export default { user () { return this.$store.state.user }, + roles () { + return this.$store.state.roles + }, canExecuteQuery () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('execute-query') + return this.roles.includes('execute-query') } } } diff --git a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue index 2c4fc09eeb7e447015d0822ee0b6ecef9e406fb4..7a69a85091e52b6c460be216522c3064b0c29976 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue @@ -149,6 +149,9 @@ export default { token () { return this.$store.state.token }, + roles () { + return this.$store.state.roles + }, config () { if (this.token === null) { return {} @@ -173,13 +176,13 @@ export default { if (!this.isOwner) { return false } - return this.user.roles.includes('modify-database-visibility') + return this.roles.includes('modify-database-visibility') }, canModifyOwnership () { if (!this.isOwner) { return false } - return this.user.roles.includes('modify-database-owner') + return this.roles.includes('modify-database-owner') } }, watch: { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue index 98fe74a3f40389437b93d9aa6642e0eccc6b8865..fdcfac698ec021c6232ba814f4d26bc0e57f0d43 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue @@ -42,7 +42,7 @@ </v-list-item-content> </v-list-item-content> </v-list-item> - <v-list-item v-if="canModify"> + <v-list-item v-if="canWriteQueues"> <v-list-item-icon> <v-icon>mdi-rabbit</v-icon> </v-list-item-icon> @@ -81,14 +81,12 @@ <v-list-item-title v-if="canRead" class="mt-2"> Consumer Count </v-list-item-title> - <v-list-item-content v-if="canRead" class="amqp-consumer"> - <span v-if="attemptedLoadingConsumers" v-text="`${consumersUp}/${consumersTotal}`" /> + <v-list-item-content v-if="canWriteQueues" class="amqp-consumer"> + <span v-text="`${consumersUp}/${consumersTotal}`" /> <v-badge - v-if="attemptedLoadingConsumers" class="ml-1" :color="consumersState.color" :content="consumersState.text" /> - <v-skeleton-loader v-else type="text" class="skeleton-xsmall" /> </v-list-item-content> </v-list-item-content> </v-list-item> @@ -108,8 +106,6 @@ export default { }, data () { return { - loadingConsumers: false, - attemptedLoadingConsumers: false, selection: [], consumers: [], items: [ @@ -146,6 +142,9 @@ export default { table () { return this.$store.state.table }, + roles () { + return this.$store.state.roles + }, canRead () { if (this.database?.is_public) { return true @@ -174,23 +173,16 @@ export default { return { color: 'success', text: 'up' } }, consumersTotal () { - if (this.loadingConsumers) { - return 0 - } return this.consumers.length }, consumersUp () { - if (this.loadingConsumers) { - return 0 - } return this.consumers.filter(c => c.active).length }, - canModify () { - if (!this.token || !this.user.username || !this.table || !('creator' in this.table) || !this.table.creator || !('username' in this.table.creator) || !this.table.creator.username) { - /* not yet loaded */ + canWriteQueues () { + if (!this.roles) { return false } - return this.table.creator.username === this.user.username + return this.roles.includes('insert-table-data') }, versionColor () { if (this.version === null) { @@ -218,11 +210,13 @@ export default { } }, watch: { - table (val) { - this.pollConsumerStatus(true) - setInterval(() => this.pollConsumerStatus(false), 5 * 1000) + table () { + this.pollConsumerStatus() } }, + mounted () { + this.pollConsumerStatus() + }, methods: { formatCreator (creator) { return formatUser(creator) @@ -233,12 +227,11 @@ export default { } return table.creator.username === this.user.username }, - async pollConsumerStatus (first) { + async pollConsumerStatus () { if (this.table === null || this.table.queue_name === null) { return } try { - this.loadingConsumers = first const res = await this.$axios.get('/api/broker/consumers/%2F', this.brokerConfig) const consumers = res.data.filter(c => c.queue.name === this.table.queue_name) console.debug('filtered', consumers) @@ -248,8 +241,6 @@ export default { console.error('Failed to find consumers', error) this.$toast.error(`Failed to find consumers: ${message}`) } - this.loadingConsumers = false - this.attemptedLoadingConsumers = true } } } diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue index 7a405ae2ed56946cd2d2fed6b936d0991ce344ea..49fd24d9d8cc26ede48cfe6b1277d38b93465c93 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue @@ -103,6 +103,9 @@ export default { token () { return this.$store.state.token }, + roles () { + return this.$store.state.roles + }, user () { return this.$store.state.user }, @@ -110,10 +113,10 @@ export default { return this.$store.state.database }, canCreateTable () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('create-table') + return this.roles.includes('create-table') }, config () { if (this.token === null) { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue index f94d97345ffaf8d03f5e829fb6a0f97cc32b1c5c..9a97285bd69bcbaa431980add330782916521c19 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue @@ -267,6 +267,9 @@ export default { user () { return this.$store.state.user }, + roles () { + return this.$store.state.roles + }, isResearcher () { return isResearcher(this.user) }, @@ -289,10 +292,10 @@ export default { .replace(/--+/g, '_')) }, canInsertTableData () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('insert-table-data') + return this.roles.includes('insert-table-data') } }, mounted () { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue index a78526e1bcf9b763334632ad8a51cb69f4b3ce98..7c06ccead7615ab69747ccfed5d5c9def86514b0 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue @@ -28,11 +28,14 @@ export default { user () { return this.$store.state.user }, + roles () { + return this.$store.state.roles + }, canCreateView () { - if (!this.user) { + if (!this.roles) { return false } - return this.user.roles.includes('create-database-view') + return this.roles.includes('create-database-view') } } } diff --git a/fda-ui/pages/forgot.vue b/fda-ui/pages/forgot.vue deleted file mode 100644 index 809139658b9b5bb04f1bb430a62b69ef4a03de14..0000000000000000000000000000000000000000 --- a/fda-ui/pages/forgot.vue +++ /dev/null @@ -1,110 +0,0 @@ -<template> - <div> - <v-form ref="form" v-model="valid" @submit.prevent="submit"> - <v-card v-if="!token" flat tile> - <v-progress-linear v-if="loading" color="primary" :indeterminate="!error" /> - <v-card-title> - Forgot Login - </v-card-title> - <v-card-text> - <v-alert - border="left" - color="info"> - Please provide either your username or e-mail address, or both. - </v-alert> - <v-row> - <v-col cols="6"> - <v-text-field - v-model="data.username" - autocomplete="off" - autofocus - name="username" - label="Username" /> - </v-col> - </v-row> - <v-row> - <v-col cols="6"> - <v-text-field - v-model="data.email" - autocomplete="off" - type="email" - name="email" - label="E-Mail Address" /> - </v-col> - </v-row> - </v-card-text> - <v-card-actions> - <v-btn - id="login" - class="mb-2 ml-2" - :disabled="!valid || !formValid" - color="primary" - type="submit" - name="submit" - @click="forgot"> - Reset password - </v-btn> - </v-card-actions> - </v-card> - </v-form> - <p v-if="token">Already logged-in</p> - </div> -</template> - -<script> -export default { - data () { - return { - loading: false, - valid: false, - error: false, - data: { - username: null, - email: null - } - } - }, - computed: { - token () { - return this.$store.state.token - }, - formValid () { - if (this.data.username === null && this.data.email === null) { - return false - } - if (this.data.username === null && this.data.email !== null) { - return this.data.email.length > 0 - } - if (this.data.username !== null && this.data.email === null) { - return this.data.username.length > 0 - } - if (this.data.username !== null && this.data.email !== null) { - return this.data.username.length > 0 || this.data.email.length > 0 - } - return false - } - }, - methods: { - submit () { - this.$refs.form.validate() - }, - login () { - this.$router.push('/login') - }, - signup () { - this.$router.push('/signup') - }, - async forgot () { - try { - this.loading = true - const res = await this.$axios.put('/api/user', this.data) - console.debug('reset user', res.data) - this.$toast.success('If a user with this information exists, we sent you a mail!') - } catch (err) { - console.error('login reset failed', err) - } - this.loading = false - } - } -} -</script> diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue index be8fbb1ed68323c63864093d25c0747945c31fe6..3cd0247d196ca6d0f35227ce8c41d9ae697c2899 100644 --- a/fda-ui/pages/login.vue +++ b/fda-ui/pages/login.vue @@ -1,15 +1,17 @@ <template> <div> + <v-toolbar flat> + <v-toolbar-title> + Login + </v-toolbar-title> + </v-toolbar> <v-form ref="form" v-model="valid" @submit.prevent="submit"> <v-card v-if="!token" flat tile> - <v-card-title> - Login - </v-card-title> <v-card-text> <v-alert border="left" color="info"> - If you need an account, <a @click="signup">create one</a> or if you cannot login, <a @click="forgot">reset</a> your information. + If you need an account, <a @click="signup">create one</a>. </v-alert> <v-row dense> <v-col sm="6"> @@ -56,7 +58,7 @@ </template> <script> -import { authenticate, refresh, tokenToExp, tokenToUser } from '@/api/user' +import { authenticate, getThemeDark, findUser, tokenToRoles } from '@/api/user' export default { data () { return { @@ -109,62 +111,30 @@ export default { try { this.loading = true const res = await authenticate(this.clientSecret, this.username, this.password) - console.debug('login user', res.data) // eslint-disable-next-line camelcase - const { access_token, refresh_token } = res.data + const { access_token } = res.data this.$store.commit('SET_TOKEN', access_token) - this.$store.commit('SET_REFRESH_TOKEN', refresh_token) - const user = tokenToUser(this.token) - console.debug('user', user) - this.$store.commit('SET_USER', user) - this.$vuetify.theme.dark = user?.theme_dark || false - await this.refreshTokenIfNecessary() + const roles = tokenToRoles(access_token) + this.$store.commit('SET_ROLES', roles) + await this.setTheme() await this.$router.push({ path: this.$route.query.redirect ? this.$route.query.redirect : '/container' }) } catch (error) { console.error('Failed to login', error) - const { status } = error.response - if (status === 418) { - this.$toast.error('Check your inbox and confirm your e-mail address') - console.error('user has not confirmed e-mail', error) - } else if (status === 404) { - this.$toast.error('Username not found') - console.error('user has not confirmed e-mail', error) - } else { - this.$toast.error('Login not successful') - console.error('login user failed', error) - } + const { statusText } = error.response + this.$toast.error(`Failed to login: ${statusText}`) this.loading = false } }, - async refreshTokenIfNecessary () { - if (!this.token) { - return - } - const exp = tokenToExp(this.token) - if (exp > new Date()) { - console.debug('token will be refreshed', exp, 'timeout is', exp - new Date()) - setTimeout(() => this.refreshTokenIfNecessary(), exp - new Date()) - return - } - const refreshExp = tokenToExp(this.refreshToken) - if (refreshExp > new Date()) { - try { - const res = await refresh(this.clientSecret, this.refreshToken) - // eslint-disable-next-line camelcase - const { access_token, refresh_token } = res.data - this.$store.commit('SET_TOKEN', access_token) - this.$store.commit('SET_REFRESH_TOKEN', refresh_token) - console.info('refreshed tokens') - const user = tokenToUser(this.token) - console.debug('user', user) - this.$store.commit('SET_USER', user) - return - } catch (error) { - console.error('Failed to login', error) - this.$toast.error('Failed to refresh tokens') - } + async setTheme () { + try { + const res = await findUser(this.token) + const user = res.data + console.debug('user', user) + this.$store.commit('SET_USER', user) + this.$vuetify.theme.dark = getThemeDark(user) + } catch (error) { + console.error('Failed to set theme', error) } - this.logout('Your session has expired') }, signup () { this.$router.push('/signup') diff --git a/fda-ui/pages/reset.vue b/fda-ui/pages/reset.vue deleted file mode 100644 index 91a12106e2de0bff5d7a2db41a300bff62af4fa2..0000000000000000000000000000000000000000 --- a/fda-ui/pages/reset.vue +++ /dev/null @@ -1,114 +0,0 @@ -<template> - <div> - <v-form ref="form" v-model="valid" @submit.prevent="submit"> - <v-card v-if="!error && !token" flat tile> - <v-card-title> - Reset Password - </v-card-title> - <v-card-text> - <v-row dense> - <v-col sm="6"> - <v-text-field - v-model="password" - autocomplete="off" - type="password" - required - :rules="[v => !!v || $t('Required')]" - label="Password *" /> - </v-col> - </v-row> - <v-row dense> - <v-col sm="6"> - <v-text-field - v-model="data.password" - autocomplete="off" - type="password" - required - :rules="[v => !!v || $t('Required'), _ => formValid || $t('Passwords not matching')]" - label="Repeat Password *" /> - </v-col> - </v-row> - </v-card-text> - <v-card-actions> - <v-btn - id="login" - class="mb-2 ml-2" - :disabled="!formValid" - color="primary" - type="submit" - @click="reset"> - Reset Password - </v-btn> - </v-card-actions> - </v-card> - </v-form> - </div> -</template> - -<script> -export default { - data () { - return { - loading: false, - valid: false, - error: false, - password: null, - data: { - password: null, - token: this.$route.query.token - } - } - }, - computed: { - token () { - return this.$store.state.token - }, - formValid () { - if (this.password === null || this.data.password === null) { - return false - } - return this.password === this.data.password - } - }, - mounted () { - if (!this.$route.query.token) { - console.error('missing token!') - this.$toast.error('Missing token!') - this.error = true - } - }, - methods: { - submit () { - this.$refs.form.validate() - }, - login () { - this.$router.push('/login') - }, - signup () { - this.$router.push('/signup') - }, - async reset () { - try { - this.loading = true - const res = await this.$axios.put('/api/user/reset', this.data) - this.loading = false - console.debug('reset user', res.data) - this.$router.push('/login?password_reset') - } catch (err) { - this.loading = false - if (err.response !== undefined && err.response.status !== undefined) { - if (err.response.status === 302) { - this.$toast.success('Password successfully reset!') - this.$router.push('/login?password_reset') - return - } else if (err.response.status === 417) { - this.$toast.error('Token is invalid!') - } - } - console.error('login reset failed', err) - } - this.loading = false - } - } -} -</script> diff --git a/fda-ui/pages/signup.vue b/fda-ui/pages/signup.vue index 2b88602a4e7b006558a5f5759771a9c2dcbde622..cb243ee531ebe1f189c119985a002eb5d27089c1 100644 --- a/fda-ui/pages/signup.vue +++ b/fda-ui/pages/signup.vue @@ -1,10 +1,12 @@ <template> <div> + <v-toolbar flat> + <v-toolbar-title> + Signup + </v-toolbar-title> + </v-toolbar> <v-form ref="form" v-model="valid" @submit.prevent="submit"> <v-card flat tile> - <v-card-title> - Create Account - </v-card-title> <v-card-text> <v-alert v-if="mailVerify" @@ -139,7 +141,7 @@ export default { this.loading = true const res = await this.$axios.post(url, this.createAccount) console.debug('create user', res.data) - this.$toast.success('Success. Check your inbox!') + this.$toast.success(`Success! ${this.mailVerify ? 'Check your inbox!' : ''}`) this.$router.push('/login') } catch (err) { if (err.response !== undefined && err.response.status !== undefined) { diff --git a/fda-ui/pages/user/authentication.vue b/fda-ui/pages/user/authentication.vue index 000ccc80ba5c66e80308bca816c14d973ac5150a..0843233abfe277a94703ec14830f79f8a867109b 100644 --- a/fda-ui/pages/user/authentication.vue +++ b/fda-ui/pages/user/authentication.vue @@ -4,47 +4,27 @@ <v-tabs-items v-model="tab"> <v-tab-item> <v-card flat tile> - <v-card-title>Verify E-Mail-Address</v-card-title> + <v-card-title>Password Change</v-card-title> <v-card-text> - <v-form v-model="valid1" @submit.prevent="submit"> + <v-form v-model="valid2" @submit.prevent="submit"> <v-row dense> <v-col md="6"> <v-text-field - v-model="email" - :disabled="user.email_verified || error" + v-model="password" + type="password" :rules="[v => !!v || $t('Required')]" required - label="E-Mail Address *" /> + label="Password *" /> </v-col> </v-row> - <v-row dense> - <v-col md="6"> - <v-btn - v-model="user.email" - small - :disabled="user.email_verified || error" - color="secondary" - type="submit" - @click="resend"> - Resend E-Mail - </v-btn> - </v-col> - </v-row> - </v-form> - </v-card-text> - <v-divider /> - <v-card-title>Password Change</v-card-title> - <v-card-text> - <v-form v-model="valid2" @submit.prevent="submit"> <v-row dense> <v-col md="6"> <v-text-field - v-model="reset.password" - :disabled="error" + v-model="password2" type="password" - :rules="[v => !!v || $t('Required')]" + :rules="[v => !!v || $t('Required'), v => (!!v && v) === password || $t('Not matching!')]" required - label="Password *" /> + label="Repeat Password *" /> </v-col> </v-row> <v-row dense> @@ -52,7 +32,8 @@ <v-btn small color="primary" - :disabled="!valid2 || error" + :loading="loadingUpdate" + :disabled="!valid2" type="submit" @click="changePassword"> Change @@ -70,6 +51,7 @@ <script> import UserToolbar from '@/components/UserToolbar' +import { updateUserPassword } from '@/api/user' export default { components: { @@ -80,24 +62,9 @@ export default { tab: 0, valid1: false, valid2: false, - error: false, + loadingUpdate: false, email: null, - user: { - id: null, - email: null, - username: null, - lastname: null, - firstname: null, - titles_after: null, - titles_before: null, - email_verified: false, - affiliation: null, - orcid: null, - theme_dark: null - }, - reset: { - password: null - }, + password: null, password2: null } }, @@ -105,6 +72,9 @@ export default { token () { return this.$store.state.token }, + user () { + return this.$store.state.user + }, config () { if (this.token === null) { return {} @@ -119,33 +89,17 @@ export default { methods: { submit () { }, - async resend () { - try { - this.loading = true - const res = await this.$axios.post('/api/user/token/resend', { - email: this.email - }, this.config) - console.debug('resend', res.data) - this.error = false - this.$toast.success('Successfully sent a verification e-mail') - } catch (err) { - console.error('resend', err) - this.error = true - } - this.loading = false - }, async changePassword () { try { - this.loading = true - const res = await this.$axios.put(`/api/user/${this.user.id}/password`, this.reset, this.config) + this.loadingUpdate = true + const res = await updateUserPassword(this.token, this.user.id, this.password) console.debug('password', res.data) - this.error = false this.$toast.success('Successfully changed the password') - } catch (err) { - console.error('password', err) - this.error = true + } catch (error) { + console.error('Failed to update password', error) + this.$toast.error('Failed to update password') } - this.loading = false + this.loadingUpdate = false } } } diff --git a/fda-ui/pages/user/developer.vue b/fda-ui/pages/user/developer.vue index e71b8b5948035c217e3895bb2ef5500de5970e9c..7199d562b745dc63ef6aff2f6d926a2170eca0c7 100644 --- a/fda-ui/pages/user/developer.vue +++ b/fda-ui/pages/user/developer.vue @@ -5,7 +5,6 @@ <v-tab-item> <v-card flat tile> <v-card-title>Personal Access Tokens</v-card-title> - <v-card-subtitle>Authentication tokens to access the HTTP API</v-card-subtitle> <v-card-text> <v-list-item v-for="(item, i) in tokens" :key="i" three-line> <v-list-item-content> diff --git a/fda-ui/pages/user/info.vue b/fda-ui/pages/user/info.vue index f1b8de891e7fcb82dbaa35b8fa07b1efbfb82629..986e1f0cd51827eefcabef55370d9871cdbe91ba 100644 --- a/fda-ui/pages/user/info.vue +++ b/fda-ui/pages/user/info.vue @@ -3,76 +3,95 @@ <UserToolbar /> <v-tabs-items v-model="tab"> <v-tab-item> - <v-card flat> - <v-card-title>User Information</v-card-title> - <v-card-subtitle>Your identity is externally managed</v-card-subtitle> - <v-card-text> - <v-form v-model="valid1" @submit.prevent="submit"> - <v-row dense> - <v-col md="3"> - <v-text-field - v-model="model.id" - disabled - label="ID" /> - </v-col> - <v-col md="3"> - <v-text-field - v-model="model.username" - disabled - label="Username" /> - </v-col> - </v-row> - <v-row dense> - <v-col md="6"> - <v-text-field - v-model="model.firstname" - disabled - :rules="[v => !!v || $t('Required')]" - required - label="Firstname *" /> - </v-col> - </v-row> - <v-row dense> - <v-col md="6"> - <v-text-field - v-model="model.lastname" - disabled - :rules="[v => !!v || $t('Required')]" - required - label="Lastname *" /> - </v-col> - </v-row> - <v-row dense> - <v-col md="6"> - <v-text-field - v-model="model.affiliation" - disabled - hint="e.g. University of xyz" - label="Affiliation" /> - </v-col> - </v-row> + <div v-if="canModifyInformation"> + <v-card flat> + <v-card-title>User Information</v-card-title> + <v-card-text> + <v-form v-model="valid1" @submit.prevent="submit"> + <v-row dense> + <v-col md="3"> + <v-text-field + v-model="model.id" + disabled + label="ID" /> + </v-col> + <v-col md="3"> + <v-text-field + v-model="model.username" + disabled + label="Username" /> + </v-col> + </v-row> + <v-row dense> + <v-col md="6"> + <v-text-field + v-model="model.firstname" + :rules="[v => !!v || $t('Required')]" + required + label="Firstname *" /> + </v-col> + </v-row> + <v-row dense> + <v-col md="6"> + <v-text-field + v-model="model.lastname" + :rules="[v => !!v || $t('Required')]" + required + label="Lastname *" /> + </v-col> + </v-row> + <v-row> + <v-col> + <v-btn + small + color="primary" + :loading="loading" + @click="updateInfo"> + Update + </v-btn> + </v-col> + </v-row> + <!-- <v-row dense>--> + <!-- <v-col md="6">--> + <!-- <v-text-field--> + <!-- v-model="model.affiliation"--> + <!-- disabled--> + <!-- hint="e.g. University of xyz"--> + <!-- label="Affiliation" />--> + <!-- </v-col>--> + <!-- </v-row>--> + <!-- <v-row dense>--> + <!-- <v-col md="6">--> + <!-- <v-text-field--> + <!-- v-model="model.orcid"--> + <!-- disabled--> + <!-- maxlength="19"--> + <!-- hint="e.g. 0000-0002-1825-0097"--> + <!-- label="ORCID" />--> + <!-- </v-col>--> + <!-- </v-row>--> + </v-form> + </v-card-text> + </v-card> + </div> + <div v-if="canModifyTheme"> + <v-divider /> + <v-card flat> + <v-card-title>Theme</v-card-title> + <v-card-text> <v-row dense> - <v-col md="6"> - <v-text-field - v-model="model.orcid" - disabled - maxlength="19" - hint="e.g. 0000-0002-1825-0097" - label="ORCID" /> + <v-col> + <v-switch + v-model="theme_dark" + :loading="loadingUpdate" + inset + :label="themeLabel" + @click="toggleTheme" /> </v-col> </v-row> - </v-form> - </v-card-text> - <v-divider /> - <v-card-title>Roles</v-card-title> - <v-card-text> - <v-row dense> - <v-col> - <pre>{{ roles.join(', ') }}</pre> - </v-col> - </v-row> - </v-card-text> - </v-card> + </v-card-text> + </v-card> + </div> </v-tab-item> </v-tabs-items> </div> @@ -80,7 +99,7 @@ <script> import UserToolbar from '@/components/UserToolbar' -import { tokenToRoles } from '@/api/user' +import { tokenToRoles, updateUser, toggleUserTheme, getThemeDark } from '@/api/user' export default { components: { @@ -93,17 +112,14 @@ export default { valid2: false, error: false, loading: false, + loadingUpdate: false, model: { id: null, username: null, firstname: null, - lastname: null, - titles_before: null, - titles_after: null, - affiliation: null, - orcid: null, - theme_dark: null - } + lastname: null + }, + theme_dark: null } }, computed: { @@ -125,49 +141,69 @@ export default { return { headers: { Authorization: `Bearer ${this.token}` } } + }, + themeLabel () { + return `${this.theme_dark ? 'Dark' : 'Light'} Theme` + }, + canModifyTheme () { + return this.roles.includes('modify-user-theme') + }, + canModifyInformation () { + return this.roles.includes('modify-user-information') + } + }, + watch: { + user () { + this.init() } }, mounted () { - this.model = Object.assign({}, this.user) + this.init() }, methods: { submit () { }, async updateInfo () { try { - this.loading = true - const res = await this.$axios.put(`/api/user/${this.user.id}`, { - titles_before: this.model.titles_before, - titles_after: this.model.titles_after, + this.loadingUpdate = true + const payload = { firstname: this.model.firstname, - lastname: this.model.lastname, - affiliation: this.model.affiliation, - orcid: this.model.orcid - }, this.config) + lastname: this.model.lastname + } + const res = await updateUser(this.token, this.user.id, payload) console.info('Updated user information') - console.debug('user information', res.data) + const user = res.data + console.debug('user', user) + this.$store.commit('SET_USER', user) this.error = false this.$toast.success('Successfully updated user information') - } catch (err) { - console.error('update', err) + } catch (error) { + console.error('update', error) this.$toast.error('Failed to update user info') this.error = true } - this.loading = false + this.loadingUpdate = false }, async toggleTheme () { try { - await this.$axios.put(`/api/user/${this.user.id}/theme`, { - theme_dark: this.model.theme_dark - }, this.config) - this.$vuetify.theme.dark = this.model.theme_dark - console.info('Set theme to', this.model.theme_dark ? 'dark' : 'light') + await toggleUserTheme(this.token, this.user.id, this.theme_dark) + this.$vuetify.theme.dark = this.theme_dark } catch (error) { const { message } = error.response console.error('Failed to update theme', error) this.$toast.error('Failed to update theme: ' + message) this.error = true } + }, + init () { + if (!this.user) { + return + } + this.theme_dark = getThemeDark(this.user) + this.model.id = this.user.id + this.model.username = this.user.username + this.model.firstname = this.user.given_name + this.model.lastname = this.user.family_name } } } diff --git a/fda-ui/root.crt b/fda-ui/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-ui/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-ui/store/index.js b/fda-ui/store/index.js index d7cd95a022d8731e46b4287d1f36ab461ddbbadb..e98dbe5ffa4f24cf44001b68363d0b3999ce8b17 100644 --- a/fda-ui/store/index.js +++ b/fda-ui/store/index.js @@ -1,6 +1,6 @@ export const state = () => ({ token: null, - refreshToken: null, + roles: [], user: null, database: null, table: null, @@ -14,15 +14,15 @@ export const mutations = { SET_TOKEN (state, token) { state.token = token }, - SET_REFRESH_TOKEN (state, refreshToken) { - state.refreshToken = refreshToken - }, SET_USER (state, user) { if (user != null && user.token) { delete user.token } state.user = user }, + SET_ROLES (state, roles) { + state.roles = roles + }, SET_ACCESS (state, access) { state.access = access }, diff --git a/fda-user-service/Dockerfile b/fda-user-service/Dockerfile index 61cb2ed65f4dbf04260fe535c1d7f6cc617beef6..151ebf831c27ef09acead44bd00624c5e4edcefb 100644 --- a/fda-user-service/Dockerfile +++ b/fda-user-service/Dockerfile @@ -24,23 +24,15 @@ FROM openjdk:11-jre-slim as runtime ENV METADATA_DB=fda ENV METADATA_USERNAME=root ENV METADATA_PASSWORD=dbrepo -ENV GATEWAY_ENDPOINT=https://gateway-service:9095 +ENV GATEWAY_ENDPOINT=http://gateway-service:9095 ENV JWT_ISSUER=http://localhost:8080/realms/dbrepo ENV JWT_PUBKEY=public-key ENV LOG_LEVEL=debug -ENV KEY_ALIAS=user-service -ENV KEY_PASS=password -ENV KEY_STORE=./server.keystore -ENV KEY_STORE_PASS=password ENV DEFAULT_ROLE=default-researcher-roles +ENV ELASTIC_PASSWORD=elastic WORKDIR /app -COPY ./server.keystore ./server.keystore -COPY ./root.crt /etc/ssl/certs/DBRepo_Root_CA.crt - -RUN cat /etc/ssl/certs/DBRepo_Root_CA.crt >> /etc/ssl/certs/ca-certificates.crt - COPY ./service_ready /usr/bin RUN chmod +x /usr/bin/service_ready @@ -50,4 +42,4 @@ COPY --from=build ./rest-service/target/rest-service-*.jar ./user-service.jar EXPOSE 9093 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-Djavax.net.ssl.trustStore=/app/server.keystore", "-Djavax.net.ssl.trustStorePassword=password", "-jar", "./user-service.jar"] +ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./user-service.jar"] diff --git a/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java b/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java index 0ff21554ca2b14c49e50550456f9e14eb501f8ea..2340c468874e170ba3edd68e0ae824751d20157e 100644 --- a/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java +++ b/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java @@ -1,12 +1,11 @@ package at.tuwien.endpoint; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.UserBriefDto; -import at.tuwien.api.user.UserDto; -import at.tuwien.api.user.UserUpdateDto; +import at.tuwien.api.user.*; import at.tuwien.config.AuthenticationConfig; import at.tuwien.entities.auth.Realm; import at.tuwien.entities.user.Role; +import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.UserMapper; import at.tuwien.service.RealmService; @@ -14,7 +13,9 @@ import at.tuwien.service.RoleService; import at.tuwien.service.UserService; import io.micrometer.core.annotation.Timed; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.extern.log4j.Log4j2; +import org.elasticsearch.client.security.ChangePasswordRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -67,7 +68,7 @@ public class UserEndpoint { @PostMapping @Transactional @Timed(value = "user.create", description = "Time needed to create a user in the metadata database") - @Operation(summary = "Create a user") + @Operation(summary = "Create user") public ResponseEntity<UserBriefDto> create(@NotNull @Valid @RequestBody SignupRequestDto data) throws UserNotFoundException, RemoteUnavailableException, RealmNotFoundException, UserAlreadyExistsException, RoleNotFoundException { @@ -80,19 +81,69 @@ public class UserEndpoint { .body(dto); } - @PutMapping + @GetMapping("/{id}") + @Transactional + @PreAuthorize("isAuthenticated()") + @Timed(value = "user.info", description = "Time needed to get information of a user in the metadata database") + @Operation(summary = "Get a user info", security = @SecurityRequirement(name = "bearerAuth")) + public ResponseEntity<UserDto> find(@NotNull @PathVariable("id") String id, + @NotNull Principal principal) + throws UserNotFoundException { + log.debug("endpoint find a user, id={}, principal={}", id, principal); + final UserDto dto = userMapper.userToUserDto(userService.find(id)); + log.trace("find user resulted in dto {}", dto); + return ResponseEntity.ok() + .body(dto); + } + + @PutMapping("/{id}") @Transactional @PreAuthorize("hasAuthority('modify-user-information')") @Timed(value = "user.modify", description = "Time needed to modify a user in the metadata database") - @Operation(summary = "Modify a user") - public ResponseEntity<UserDto> modify(@NotNull @Valid @RequestBody UserUpdateDto data, + @Operation(summary = "Modify user information", security = @SecurityRequirement(name = "bearerAuth")) + public ResponseEntity<UserDto> modify(@NotNull @PathVariable("id") String id, + @NotNull @Valid @RequestBody UserUpdateDto data, @NotNull Principal principal) - throws UserNotFoundException { - log.debug("endpoint modify a user, data={}", data); - final UserDto dto = userMapper.userToUserDto(userService.modify(data, principal)); + throws UserNotFoundException, ForeignUserException { + log.debug("endpoint modify a user, id={}, data={}, principal={}", id, data, principal); + final UserDto dto = userMapper.userToUserDto(userService.modify(id, data, principal)); log.trace("modify user resulted in dto {}", dto); return ResponseEntity.status(HttpStatus.ACCEPTED) .body(dto); } + @PutMapping("/{id}/theme") + @Transactional + @PreAuthorize("hasAuthority('modify-user-theme')") + @Timed(value = "user.theme", description = "Time needed to modify a user theme in the metadata database") + @Operation(summary = "Modify user theme", security = @SecurityRequirement(name = "bearerAuth")) + public ResponseEntity<UserDto> theme(@NotNull @PathVariable("id") String id, + @NotNull @Valid @RequestBody UserThemeSetDto data, + @NotNull Principal principal) + throws UserNotFoundException, ForeignUserException { + log.debug("endpoint modify a user theme, id={}, data={}, principal={}", id, data, principal); + final User user = userService.toggleTheme(id, data, principal); + final UserDto dto = userMapper.userToUserDto(user); + log.trace("modify user theme resulted in dto {}", dto); + return ResponseEntity.accepted() + .body(dto); + } + + @PutMapping("/{id}/password") + @Transactional + @PreAuthorize("isAuthenticated()") + @Timed(value = "user.password", description = "Time needed to modify a user password in the metadata database") + @Operation(summary = "Modify user password", security = @SecurityRequirement(name = "bearerAuth")) + public ResponseEntity<UserDto> password(@NotNull @PathVariable("id") String id, + @NotNull @Valid @RequestBody UserPasswordDto data, + @NotNull Principal principal) + throws UserNotFoundException, ForeignUserException { + log.debug("endpoint modify a user password, id={}, data={}, principal={}", id, data, principal); + final User user = userService.updatePassword(id, data, principal); + final UserDto dto = userMapper.userToUserDto(user); + log.trace("updated user password resulted in dto {}", dto); + return ResponseEntity.accepted() + .body(dto); + } + } diff --git a/fda-user-service/rest-service/src/main/resources/application-insecure.yml b/fda-user-service/rest-service/src/main/resources/application-insecure.yml deleted file mode 100644 index 613bde85073fc605cde77cc18fad6f3c4be732dc..0000000000000000000000000000000000000000 --- a/fda-user-service/rest-service/src/main/resources/application-insecure.yml +++ /dev/null @@ -1,58 +0,0 @@ -app.version: '@project.version@' -spring: - main.banner-mode: off - datasource: - url: jdbc:mariadb://metadata-db:3306/fda - driver-class-name: org.mariadb.jdbc.Driver - username: "${METADATA_USERNAME}" - password: "${METADATA_PASSWORD}" - jpa: - show-sql: false - database-platform: org.hibernate.dialect.MariaDBDialect - hibernate: - ddl-auto: validate - use-new-id-generator-mappings: false - open-in-view: false - properties: - hibernate: - default_schema: fda - jdbc: - time_zone: UTC - application: - name: user-service - cloud: - loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true -management.endpoints.web.exposure.include: health,info,prometheus -server: - port: 9098 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" -logging: - pattern.console: "%d %highlight(%-5level) %msg%n" - level: - root: warn - at.tuwien.: "${LOG_LEVEL}" - org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug -eureka: - instance: - hostname: user-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9098 - client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ -fda: - ready.path: /ready - gateway.endpoint: "${GATEWAY_ENDPOINT}" - default_role: "${DEFAULT_ROLE}" - jwt: - issuer: "${JWT_ISSUER}" - public_key: "${JWT_PUBKEY}" \ No newline at end of file diff --git a/fda-user-service/rest-service/src/main/resources/application-local.yml b/fda-user-service/rest-service/src/main/resources/application-local.yml index bb1d896827b99a1b8f24d93fa99b90eaceab472b..77662670bf1b7cc3924dfac97fb15801642794e1 100644 --- a/fda-user-service/rest-service/src/main/resources/application-local.yml +++ b/fda-user-service/rest-service/src/main/resources/application-local.yml @@ -22,20 +22,9 @@ spring: name: user-service cloud: loadbalancer.ribbon.enabled: false - gateway: - httpclient: - ssl: - useInsecureTrustManager: true management.endpoints.web.exposure.include: health,info,prometheus server: port: 9098 - ssl: - enabled: true - key-alias: user-service - key-store: "./server.keystore" - key-store-type: jks - key-store-password: password - key-password: password logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -45,13 +34,15 @@ logging: eureka: instance: hostname: user-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9098 + non-secure-port: 9098 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: + elastic: + endpoint: localhost:9200 + username: elastic + password: elastic ready.path: ./ready - gateway.endpoint: https://gateway-service:9095 + gateway.endpoint: http://gateway-service:9095 default_role: default-researcher-roles jwt: issuer: https://localhost:8443/realms/dbrepo diff --git a/fda-user-service/rest-service/src/main/resources/application.yml b/fda-user-service/rest-service/src/main/resources/application.yml index a9f7bbd141d3ff399ad2c0c138e0c03f03ebb8cd..7acd005839042d01e3a5a3241b46713fc92f2596 100644 --- a/fda-user-service/rest-service/src/main/resources/application.yml +++ b/fda-user-service/rest-service/src/main/resources/application.yml @@ -25,13 +25,6 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus server: port: 9098 - ssl: - enabled: true - key-alias: "${KEY_ALIAS}" - key-store: "${KEY_STORE}" - key-store-type: jks - key-store-password: "${KEY_STORE_PASS}" - key-password: "${KEY_PASS}" logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: @@ -41,11 +34,13 @@ logging: eureka: instance: hostname: user-service - non-secure-port-enabled: false - secure-port-enabled: true - secure-port: 9098 + non-secure-port: 9098 client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/ fda: + elastic: + endpoint: search-service:9200 + username: elastic + password: "${ELASTIC_PASSWORD}" ready.path: /ready gateway.endpoint: "${GATEWAY_ENDPOINT}" default_role: "${DEFAULT_ROLE}" diff --git a/fda-user-service/root.crt b/fda-user-service/root.crt deleted file mode 100644 index 798a1f673479c075782eeed6458beb2d7d693e07..0000000000000000000000000000000000000000 --- a/fda-user-service/root.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPzCCAiegAwIBAgIEHaMDRDANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJB -VDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQDEwZS -b290Q0EwHhcNMjMwNDAzMTczOTU5WhcNMzMwMjA5MTczOTU5WjBBMQswCQYDVQQG -EwJBVDEQMA4GA1UEChMHVFUgV2llbjEPMA0GA1UECxMGRFMtSUZTMQ8wDQYDVQQD -EwZSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCK8FuP0bGt -QAvhZEjRWTQuCdE6vXpDWjvSoevZaSclgJ9SncDHtRzkH0x0ArVfIRZFtjSUEcHb -2r8mnOvqQ+9vs2azjTlacdPvezbhfgFFGIdrnHSm3RTB7smeOFceFkIvwiXT49+y -ZGkB/p0QCDoVYhgRxFNtZKBTYa0uJLQ7cM8LK2g66/yugJsB4zOlre1zPiWGY/5k -sWu780XVKpl9j6CR/xp3012bKlT/t7j7fKRamJYVYtW2guRQnl5J5AKRzlRGh84G -onNI5qiwS0gAZUajpL00lb2XxSkv11DY0743EOSsqOvUDr+5h4v7pXEt+O5aFvFN -ewRTHON1624fAgMBAAGjPzA9MB0GA1UdDgQWBBSdLp+I30uB4jAMP1PnZLolxbF/ -AzALBgNVHQ8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AQEAIqrbs8mXC07a8VURnu3EFxO3dliDgxY1yQfB0VqMFL1yxGKXrVAJFLP/1MVr -HVx53vZd/KBNGUjhLfnj3vF+TpqnOoJ/QEDSJPuEnpfFPtx0tE3e3lQQlebIA8aM -m1iP2SJuKAYQUYOg1N9XXa+UPs9tWWrllY5dcYdHOK168eUwo1h6v0OOnaP7RvSn -457jewK6fJ3tUhox2Hu1JEowupYE5QhMiLwG30MGkf2pWkTNfz005LTzmgvfMSz7 -k1rfO9oKdVbxNYxZPdzKZRsnCfOka/MmYcXstjp5KKXLo4Z3LLs8N0GDWlKRvX9p -z2CJQ6CG+Aws4+J3mFOm2G9rIw== ------END CERTIFICATE----- diff --git a/fda-user-service/server.keystore b/fda-user-service/server.keystore deleted file mode 100644 index 1acf1f68ca7c367468fe2a81179d5fc9f295cfc9..0000000000000000000000000000000000000000 Binary files a/fda-user-service/server.keystore and /dev/null differ diff --git a/fda-user-service/services/src/main/java/at/tuwien/config/ElasticsearchConfig.java b/fda-user-service/services/src/main/java/at/tuwien/config/ElasticsearchConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..dd42aa517fb5bda732d39a5660918bbe61cfc6ce --- /dev/null +++ b/fda-user-service/services/src/main/java/at/tuwien/config/ElasticsearchConfig.java @@ -0,0 +1,42 @@ +package at.tuwien.config; + +import lombok.extern.log4j.Log4j2; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.client.RestClients; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; + +@Log4j2 +@Configuration +public class ElasticsearchConfig { + + @Value("${fda.elastic.endpoint}") + private String elasticEndpoint; + + @Value("${fda.elastic.username}") + private String elasticUsername; + + @Value("${fda.elastic.password}") + private String elasticPassword; + + @Bean + public RestHighLevelClient client() { + log.debug("elastic endpoint={}", elasticEndpoint); + final ClientConfiguration clientConfiguration = ClientConfiguration.builder() + .connectedTo(elasticEndpoint) + .withBasicAuth(elasticUsername, elasticPassword) + .build(); + return RestClients.create(clientConfiguration) + .rest(); + } + + @Bean + public ElasticsearchOperations elasticsearchTemplate() { + return new ElasticsearchRestTemplate(client()); + } + +} \ No newline at end of file diff --git a/fda-user-service/services/src/main/java/at/tuwien/exception/ForeignUserException.java b/fda-user-service/services/src/main/java/at/tuwien/exception/ForeignUserException.java new file mode 100644 index 0000000000000000000000000000000000000000..921a99180d914e36f0898402720afbd493c6a6a6 --- /dev/null +++ b/fda-user-service/services/src/main/java/at/tuwien/exception/ForeignUserException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED) +public class ForeignUserException extends Exception { + + public ForeignUserException(String message) { + super(message); + } + + public ForeignUserException(String message, Throwable thr) { + super(message, thr); + } + + public ForeignUserException(Throwable thr) { + super(thr); + } + +} diff --git a/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/UserAttributeRepository.java b/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/UserAttributeRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..b3cf3ecedceee547dc556209959dad5cd6c4627f --- /dev/null +++ b/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/UserAttributeRepository.java @@ -0,0 +1,14 @@ +package at.tuwien.repository.jpa; + +import at.tuwien.entities.user.UserAttribute; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface UserAttributeRepository extends JpaRepository<UserAttribute, String> { + + Optional<UserAttribute> findByUserIdAndName(String userId, String name); + +} diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java b/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java index 713fbabca61dff710453ac31af1200ef0aa74216..fc4367b76898d55f332020fd19c75655913c0085 100644 --- a/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java +++ b/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java @@ -1,10 +1,13 @@ package at.tuwien.service; import at.tuwien.api.auth.SignupRequestDto; +import at.tuwien.api.user.UserPasswordDto; +import at.tuwien.api.user.UserThemeSetDto; import at.tuwien.api.user.UserUpdateDto; import at.tuwien.entities.auth.Realm; import at.tuwien.entities.user.Role; import at.tuwien.entities.user.User; +import at.tuwien.exception.ForeignUserException; import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.UserAlreadyExistsException; import at.tuwien.exception.UserNotFoundException; @@ -30,10 +33,17 @@ public interface UserService { */ User findByUsername(String username) throws UserNotFoundException; + User findById(String id) throws UserNotFoundException; + User create(SignupRequestDto data, Realm realm, Role role) throws RemoteUnavailableException, UserNotFoundException, UserAlreadyExistsException; - User modify(UserUpdateDto data, Principal principal) throws UserNotFoundException; + User modify(String id, UserUpdateDto data, Principal principal) throws UserNotFoundException, ForeignUserException; + + User updatePassword(String id, UserPasswordDto data, Principal principal) throws UserNotFoundException, + ForeignUserException; + + User toggleTheme(String id, UserThemeSetDto data, Principal principal) throws UserNotFoundException, ForeignUserException; User find(String id) throws UserNotFoundException; } diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java index e1722327d938915fa17e9c179606c0f8e349bb06..c3616f99e6814e1fc2b9160f53c1dfd280794cf9 100644 --- a/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java @@ -1,18 +1,19 @@ package at.tuwien.service.impl; import at.tuwien.api.auth.SignupRequestDto; +import at.tuwien.api.user.UserPasswordDto; +import at.tuwien.api.user.UserThemeSetDto; import at.tuwien.api.user.UserUpdateDto; import at.tuwien.entities.auth.Realm; -import at.tuwien.entities.user.Credential; -import at.tuwien.entities.user.Role; -import at.tuwien.entities.user.RoleMapping; -import at.tuwien.entities.user.User; +import at.tuwien.entities.user.*; +import at.tuwien.exception.ForeignUserException; import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.UserAlreadyExistsException; import at.tuwien.exception.UserNotFoundException; import at.tuwien.mapper.UserMapper; import at.tuwien.repository.jpa.CredentialRepository; import at.tuwien.repository.jpa.RoleMappingRepository; +import at.tuwien.repository.jpa.UserAttributeRepository; import at.tuwien.repository.jpa.UserRepository; import at.tuwien.service.UserService; import lombok.extern.log4j.Log4j2; @@ -47,14 +48,17 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final CredentialRepository credentialRepository; private final RoleMappingRepository roleMappingRepository; + private final UserAttributeRepository userAttributeRepository; @Autowired public UserServiceImpl(UserMapper userMapper, UserRepository userRepository, - CredentialRepository credentialRepository, RoleMappingRepository roleMappingRepository) { + CredentialRepository credentialRepository, RoleMappingRepository roleMappingRepository, + UserAttributeRepository userAttributeRepository) { this.userMapper = userMapper; this.userRepository = userRepository; this.credentialRepository = credentialRepository; this.roleMappingRepository = roleMappingRepository; + this.userAttributeRepository = userAttributeRepository; } @Override @@ -72,6 +76,16 @@ public class UserServiceImpl implements UserService { return optional.get(); } + @Override + public User findById(String id) throws UserNotFoundException { + final Optional<User> optional = userRepository.findById(id); + if (optional.isEmpty()) { + log.error("Failed to retrieve user with id {}", id); + throw new UserNotFoundException("Failed to retrieve user"); + } + return optional.get(); + } + @Override public User create(SignupRequestDto data, Realm realm, Role role) throws RemoteUnavailableException, UserNotFoundException, UserAlreadyExistsException { @@ -93,7 +107,7 @@ public class UserServiceImpl implements UserService { .append("\",\"salt\":\"") .append(Base64.encodeBytes(salt)) .append("\",\"additionalParameters\":{}}"); - final Credential entity = Credential.builder() + Credential credential = Credential.builder() .createdDate(Instant.now().toEpochMilli()) .secretData(secretData.toString()) .type("password") @@ -101,15 +115,22 @@ public class UserServiceImpl implements UserService { .credentialData("{\"hashIterations\":" + DEFAULT_ITERATIONS + ",\"algorithm\":\"" + ID + "\",\"additionalParameters\":{}}") .build(); /* save */ - final User tmp = userMapper.signupRequestDtoToUser(data); - tmp.setEmailVerified(false); - tmp.setEnabled(true); - tmp.setRealmId(realm.getId()); - tmp.setCreatedTimestamp(Instant.now().toEpochMilli()); - final User user = userRepository.save(tmp); - entity.setUserId(user.getId()); - final Credential credential = credentialRepository.save(entity); + User user = userMapper.signupRequestDtoToUser(data); + user.setEmailVerified(false); + user.setEnabled(true); + user.setRealmId(realm.getId()); + user.setCreatedTimestamp(Instant.now().toEpochMilli()); + user = userRepository.save(user); + UserAttribute userAttribute = UserAttribute.builder() + .userId(user.getId()) + .name("theme_dark") + .value("false") + .build(); + userAttribute = userAttributeRepository.save(userAttribute); + credential.setUserId(user.getId()); + credential = credentialRepository.save(credential); user.setCredentials(List.of(credential)); + user.setAttributes(List.of(userAttribute)); final RoleMapping tmp2 = RoleMapping.builder() .userId(user.getId()) .roleId(role.getId()) @@ -122,17 +143,79 @@ public class UserServiceImpl implements UserService { } @Override - public User modify(UserUpdateDto data, Principal principal) throws UserNotFoundException { + public User modify(String id, UserUpdateDto data, Principal principal) throws UserNotFoundException, + ForeignUserException { /* check */ - final User entity = findByUsername(principal.getName()); - entity.setFirstname(data.getFirstname()); - entity.setLastname(data.getLastname()); + User user = findById(id); + if (!user.getUsername().equals(principal.getName())) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + user.setFirstname(data.getFirstname()); + user.setLastname(data.getLastname()); /* save */ - final User user = userRepository.save(entity); + user = userRepository.save(user); log.info("Modified user with id {}", user.getId()); return user; } + @Override + public User updatePassword(String id, UserPasswordDto data, Principal principal) throws UserNotFoundException, + ForeignUserException { + /* check */ + final User user = findById(id); + if (!user.getUsername().equals(principal.getName())) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + /* create secret */ + final byte[] salt = getSalt(); + final StringBuilder secretData = new StringBuilder("{\"value\":\"") + .append(encodedCredential(data.getPassword(), DEFAULT_ITERATIONS, salt, DERIVED_KEY_SIZE)) + .append("\",\"salt\":\"") + .append(Base64.encodeBytes(salt)) + .append("\",\"additionalParameters\":{}}"); + Credential credential = Credential.builder() + .createdDate(Instant.now().toEpochMilli()) + .secretData(secretData.toString()) + .type("password") + .priority(10) + .credentialData("{\"hashIterations\":" + DEFAULT_ITERATIONS + ",\"algorithm\":\"" + ID + "\",\"additionalParameters\":{}}") + .build(); + /* save */ + credential = credentialRepository.save(credential); + user.setCredentials(List.of(credential)); + log.info("Updated user password with id {}", user.getId()); + return user; + } + + @Override + public User toggleTheme(String id, UserThemeSetDto data, Principal principal) throws UserNotFoundException, + ForeignUserException { + /* check */ + final User user = findById(id); + if (!user.getUsername().equals(principal.getName())) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + final Optional<UserAttribute> optional = userAttributeRepository.findByUserIdAndName(user.getId(), "theme_dark"); + if (optional.isEmpty()) { + final UserAttribute theme = UserAttribute.builder() + .user(user) + .value(data.getThemeDark().toString()) + .build(); + final UserAttribute attribute = userAttributeRepository.save(theme); + log.info("Updated theme by creating attribute with id {}", attribute); + return user; + } + final UserAttribute theme = optional.get(); + theme.setValue(data.getThemeDark().toString()); + final UserAttribute attribute = userAttributeRepository.save(theme); + user.setAttributes(List.of(attribute)); + log.info("Updated theme by updating attribute with id {}", attribute); + return user; + } + @Override public User find(String id) throws UserNotFoundException { final Optional<User> optional = userRepository.findById(id);