diff --git a/fda-authentication-service/Dockerfile b/fda-authentication-service/Dockerfile index 8315953c3840d95a458306dea64c52a0bdfca7fa..9af6f05c5a09e4e3533781afe60d396844a2a4fc 100644 --- a/fda-authentication-service/Dockerfile +++ b/fda-authentication-service/Dockerfile @@ -1,24 +1,6 @@ ###### FIRST STAGE ###### -FROM maven:slim as build -MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> - -WORKDIR /app - -COPY ./rabbitmq-event-listener/pom.xml ./pom.xml - -RUN mvn -fn -B dependency:go-offline > /dev/null - -COPY ./rabbitmq-event-listener ./ - -# Make sure it compiles -RUN mvn -q clean package -DskipTests > /dev/null - -RUN mv ./target/rabbitmq-event-listener-*.jar ./target/rabbitmq-event-listener.jar - -###### SECOND STAGE ###### FROM keycloak/keycloak:21.0 as config - -COPY --from=build /app/target/rabbitmq-event-listener.jar /opt/keycloak/providers/rabbitmq-event-listener.jar +MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> # Enable health and metrics support ENV KC_HEALTH_ENABLED=true @@ -34,7 +16,7 @@ WORKDIR /opt/keycloak RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore RUN /opt/keycloak/bin/kc.sh build -###### THIRD STAGE ###### +###### SECOND STAGE ###### FROM redhat/ubi9-minimal as binary RUN microdnf update -y && microdnf install -y curl-minimal libcurl-minimal @@ -45,7 +27,6 @@ FROM keycloak/keycloak:21.0 as runtime COPY --from=config /opt/keycloak/ /opt/keycloak/ COPY --from=binary /usr/lib64 /usr/lib64 COPY --from=binary /usr/bin/curl /usr/bin/curl -COPY --from=build /app/target/rabbitmq-event-listener.jar /opt/keycloak/providers/rabbitmq-event-listener.jar USER root diff --git a/fda-authentication-service/dbrepo-realm.json b/fda-authentication-service/dbrepo-realm.json index 82c2595fb2dfecadbc1dcfb0b25f20367f408b4d..37c61f0a609bb5d179f24b67008cddad6e3c3a0f 100644 --- a/fda-authentication-service/dbrepo-realm.json +++ b/fda-authentication-service/dbrepo-realm.json @@ -1589,7 +1589,7 @@ }, "smtpServer" : { }, "eventsEnabled" : false, - "eventsListeners" : [ "rabbitmq-event-listener", "jboss-logging" ], + "eventsListeners" : [ "jboss-logging" ], "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_CONSENT_ERROR", "GRANT_CONSENT", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REVOKE_GRANT", "UPDATE_TOTP", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "RESTART_AUTHENTICATION", "IMPERSONATE", "UPDATE_PROFILE_ERROR", "LOGIN", "OAUTH2_DEVICE_VERIFY_USER_CODE", "UPDATE_PASSWORD_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "TOKEN_EXCHANGE", "AUTHREQID_TO_TOKEN", "LOGOUT", "REGISTER", "DELETE_ACCOUNT_ERROR", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "DELETE_ACCOUNT", "UPDATE_PASSWORD", "CLIENT_DELETE", "FEDERATED_IDENTITY_LINK_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "CLIENT_DELETE_ERROR", "VERIFY_EMAIL", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "EXECUTE_ACTIONS", "REMOVE_FEDERATED_IDENTITY_ERROR", "TOKEN_EXCHANGE_ERROR", "PERMISSION_TOKEN", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "SEND_VERIFY_EMAIL", "OAUTH2_DEVICE_AUTH", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "OAUTH2_DEVICE_CODE_TO_TOKEN", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "EXECUTE_ACTION_TOKEN", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "AUTHREQID_TO_TOKEN_ERROR", "UPDATE_PROFILE", "CLIENT_REGISTER_ERROR", "FEDERATED_IDENTITY_LINK", "SEND_IDENTITY_PROVIDER_LINK", "SEND_VERIFY_EMAIL_ERROR", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "OAUTH2_DEVICE_AUTH_ERROR", "UPDATE_CONSENT", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "CUSTOM_REQUIRED_ACTION_ERROR", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "VERIFY_PROFILE", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], "adminEventsEnabled" : false, "adminEventsDetailsEnabled" : false, diff --git a/fda-authentication-service/rabbitmq-event-listener/pom.xml b/fda-authentication-service/rabbitmq-event-listener/pom.xml deleted file mode 100644 index 5a23bb1780159c5ec35530c7728845b9ea15fc82..0000000000000000000000000000000000000000 --- a/fda-authentication-service/rabbitmq-event-listener/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <groupId>org.example</groupId> - <artifactId>rabbitmq-event-listener</artifactId> - <version>1.0-SNAPSHOT</version> - <packaging>jar</packaging> - - <name>Keycloak - Custom Event Listener</name> - <description>This event listener will notify an admin about new registrations via Email.</description> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - - <maven.compiler.source>11</maven.compiler.source> - <maven.compiler.target>11</maven.compiler.target> - - <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-parent --> - <keycloak.version>21.0.1</keycloak.version> - <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin --> - <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> - <!-- https://mvnrepository.com/artifact/org.wildfly.plugins/wildfly-maven-plugin --> - <maven-wildfly-plugin.version>2.0.2.Final</maven-wildfly-plugin.version> - </properties> - - <dependencies> - <dependency> - <groupId>org.keycloak</groupId> - <artifactId>keycloak-server-spi</artifactId> - <version>${keycloak.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.keycloak</groupId> - <artifactId>keycloak-server-spi-private</artifactId> - <version>${keycloak.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.keycloak</groupId> - <artifactId>keycloak-services</artifactId> - <version>${keycloak.version}</version> - <scope>provided</scope> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>${maven-compiler-plugin.version}</version> - </plugin> - <plugin> - <groupId>org.wildfly.plugins</groupId> - <artifactId>wildfly-maven-plugin</artifactId> - <version>${maven-wildfly-plugin.version}</version> - <configuration> - <skip>false</skip> - </configuration> - </plugin> - </plugins> - </build> - -</project> \ No newline at end of file diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java b/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java deleted file mode 100644 index c6e2b52a323257d5c89ad81f1a6e1c783b430c7a..0000000000000000000000000000000000000000 --- a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -package at.tuwien; - -import org.jboss.logging.Logger; -import org.keycloak.email.DefaultEmailSenderProvider; -import org.keycloak.email.EmailException; -import org.keycloak.events.Event; -import org.keycloak.events.EventListenerProvider; -import org.keycloak.events.EventType; -import org.keycloak.events.admin.AdminEvent; -import org.keycloak.events.admin.OperationType; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.UserModel; - -import java.util.Map; - -public class CustomEventListenerProvider implements EventListenerProvider { - - private static final Logger log = Logger.getLogger(CustomEventListenerProvider.class); - - private final KeycloakSession session; - private final RealmProvider model; - - public CustomEventListenerProvider(KeycloakSession session) { - this.session = session; - this.model = session.realms(); - } - - @Override - public void onEvent(Event event) { - if (event.getType().equals(EventType.REGISTER)) { - - } - } - - @Override - public void onEvent(AdminEvent adminEvent, boolean b) { - if (adminEvent.getOperationType().equals(OperationType.CREATE) && adminEvent.getResourcePath().startsWith("users/")) { - log.infof("=======> Created user!!"); - } else if (adminEvent.getOperationType().equals(OperationType.ACTION) && adminEvent.getResourcePath().startsWith("users/") && adminEvent.getResourcePath().endsWith("reset-password")) { - log.infof("=======> Modified user password!!"); - } - } - - @Override - public void close() { - - } - - private void createUser(String username) { - - } -} \ No newline at end of file diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java b/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java deleted file mode 100644 index 89d9ded5455b8c6e22b7c08f9f1f6fba60198bf7..0000000000000000000000000000000000000000 --- a/fda-authentication-service/rabbitmq-event-listener/src/main/java/at/tuwien/CustomEventListenerProviderFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package at.tuwien; - -import org.keycloak.Config; -import org.keycloak.events.EventListenerProvider; -import org.keycloak.events.EventListenerProviderFactory; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionFactory; - -public class CustomEventListenerProviderFactory implements EventListenerProviderFactory { - - @Override - public EventListenerProvider create(KeycloakSession keycloakSession) { - return new CustomEventListenerProvider(keycloakSession); - } - - @Override - public void init(Config.Scope scope) { - - } - - @Override - public void postInit(KeycloakSessionFactory keycloakSessionFactory) { - - } - - @Override - public void close() { - - } - - @Override - public String getId() { - return "rabbitmq-event-listener"; - } -} \ No newline at end of file diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml b/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml deleted file mode 100644 index c0330ba082479a3bd9d0caf86508b5067251ed84..0000000000000000000000000000000000000000 --- a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/jboss-deployment-structure.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<jboss-deployment-structure> - <deployment> - <dependencies> - <module name="org.keycloak.keycloak-services" /> - </dependencies> - </deployment> -</jboss-deployment-structure> \ No newline at end of file diff --git a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory b/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory deleted file mode 100644 index 5dee2484cc921ab377ff100fc9fe266025f26688..0000000000000000000000000000000000000000 --- a/fda-authentication-service/rabbitmq-event-listener/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory +++ /dev/null @@ -1 +0,0 @@ -at.tuwien.CustomEventListenerProviderFactory \ No newline at end of file diff --git a/fda-ui/api/user/index.js b/fda-ui/api/user/index.js new file mode 100644 index 0000000000000000000000000000000000000000..ce0317ad3d4566da88394bd2c134f662631f16cf --- /dev/null +++ b/fda-ui/api/user/index.js @@ -0,0 +1,21 @@ +const axios = require('axios/dist/browser/axios.cjs') +const qs = require('qs') +const { clientSecret } = require('@/config') +function authenticate (username, password) { + const payload = { + client_id: 'dbrepo-client', + username, + password, + grant_type: 'password', + client_secret: clientSecret, + scope: 'openid' + } + console.debug('===>', clientSecret) + return axios.post('/api/auth/realms/dbrepo/protocol/openid-connect/token', qs.stringify(payload), { + headers: { ContentType: 'application/form-data' } + }) +} + +module.exports = { + authenticate +} diff --git a/fda-ui/config.js b/fda-ui/config.js new file mode 100644 index 0000000000000000000000000000000000000000..8e22479f037e05308d518ac8026378441b4720db --- /dev/null +++ b/fda-ui/config.js @@ -0,0 +1,19 @@ +const config = {} + +config.api = process.env.API || 'http://localhost:9095' +config.search = process.env.SEARCH || 'http://localhost:9200' +config.sandbox = process.env.SANDBOX || false +config.title = process.env.TITLE || 'Database Repository' +config.icon = process.env.ICON || '/favicon.ico' +config.brokerUsername = process.env.BROKER_USERNAME || 'fda' +config.brokerPassword = process.env.BROKER_PASSWORD || 'fda' +config.sharedFilesystem = process.env.SHARED_FILESYSTEM || '/tmp' +config.version = process.env.VERSION || 'latest' +config.logo = process.env.LOGO || '/logo.png' +config.mailVerify = process.env.MAIL_VERIFY || false +config.tokenMax = process.env.TOKEN_MAX || 5 +config.elasticPassword = process.env.ELASTIC_PASSWORD || 'elastic' +config.elasticPassword = process.env.ELASTIC_PASSWORD || 'elastic' +config.clientSecret = process.env.CLIENT_SECRET + +module.exports = config diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue index 5116d0397fb34a6a4150e097496f7a3eac23b0a0..3b310b25aba3d80ca452a9f31c8a3cb94b4a8321 100644 --- a/fda-ui/layouts/default.vue +++ b/fda-ui/layouts/default.vue @@ -122,7 +122,7 @@ </template> <script> -import { isDeveloper } from '@/utils' +import { isDeveloper, jwtToUser } from '@/utils' export default { name: 'DefaultLayout', data () { @@ -136,7 +136,13 @@ export default { loadingUser: true, loadingSearch: false, loadingDatabases: false, - search: null + search: null, + refreshToken: { + client_id: 'dbrepo-client', + grant_type: 'refresh_token', + client_secret: this.$config.client_secret, + refresh_token: null + } } }, computed: { @@ -173,6 +179,14 @@ export default { headers: { Authorization: `Bearer ${this.token}` } } }, + keycloakConfig () { + return { + headers: { + Authorization: `Bearer ${this.token}`, + ContentType: 'application/x-www-form-urlencoded' + } + } + }, silentConfig () { return { headers: this.config.headers, @@ -238,6 +252,7 @@ export default { }, logout () { this.$store.commit('SET_TOKEN', null) + this.$store.commit('SET_REFRESH_TOKEN', null) this.$store.commit('SET_USER', null) this.$store.commit('SET_ACCESS', null) this.$vuetify.theme.dark = false @@ -250,11 +265,13 @@ export default { try { this.loadingUser = true const res = await this.$axios.get('/api/auth/realms/dbrepo/protocol/openid-connect/userinfo', this.keycloakConfig) - this.$store.commit('SET_USER', res.data) - console.debug('user information', this.user) - this.$vuetify.theme.dark = this.user.theme_dark + const user = jwtToUser(res.data) + console.debug('user information', user) + this.$store.commit('SET_USER', user) + this.$vuetify.theme.dark = user.theme_dark this.loading = false } catch (err) { + console.error('Failed to load user', err) const { status } = err.response if (status === 401) { console.error('Token expired', err) diff --git a/fda-ui/nuxt.config.js b/fda-ui/nuxt.config.js index 9327472ae752ff3efb05dd23cab75300030936f0..d5ca9c8cae59bc2d3bba419cff396660b21da296 100644 --- a/fda-ui/nuxt.config.js +++ b/fda-ui/nuxt.config.js @@ -1,17 +1,14 @@ import path from 'path' import colors from 'vuetify/es5/util/colors' +import { sandbox, title, icon, brokerUsername, brokerPassword, sharedFilesystem, version, logo, mailVerify, tokenMax, elasticPassword, clientSecret, api, search } from './config' // pick env vars from .env file or get them passed through docker-compose require('dotenv').config() -if (process.env.SANDBOX) { +if (sandbox) { console.info('[FDA] Running in sandbox environment') } -const configTitle = process.env.TITLE || 'Database Repository' -const configIcon = process.env.ICON || '/favicon.ico' -const sandbox = process.env.SANDBOX || false - export default { target: 'server', ssr: false, @@ -25,14 +22,14 @@ export default { }, head: { - title: configTitle, + title, meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: '' } ], link: [ - { rel: 'icon', type: 'image/x-icon', href: configIcon } + { rel: 'icon', type: 'image/x-icon', href: icon } ] }, @@ -74,20 +71,20 @@ export default { }, publicRuntimeConfig: { - brokerUsername: process.env.BROKER_USERNAME || 'fda', - brokerPassword: process.env.BROKER_PASSWORD || 'fda', + brokerUsername, + brokerPassword, sandbox, - sharedFilesystem: process.env.SHARED_FILESYSTEM || '/tmp', - version: process.env.VERSION || 'latest', - logo: process.env.LOGO || '/logo.png', - mailVerify: process.env.MAIL_VERIFY || false, - tokenMax: process.env.TOKEN_MAX || 5, - elasticPassword: process.env.ELASTIC_PASSWORD || 'elastic', - client_secret: process.env.CLIENT_SECRET + sharedFilesystem, + version, + logo, + mailVerify, + tokenMax, + elasticPassword, + clientSecret }, proxy: { - '/api': process.env.API || 'http://localhost:9095', + '/api': api, '/pid': { target: process.env.API + '/api' || 'http://localhost:9095/api', changeOrigin: true, @@ -96,7 +93,7 @@ export default { } }, '/retrieve': { - target: process.env.SEARCH || 'http://localhost:9200', + target: search, changeOrigin: true, pathRewrite: { '^/retrieve': '' diff --git a/fda-ui/package.json b/fda-ui/package.json index e0e1c96189fd7d7bf0604df48d5fa0f11324266e..e80cb0ce28d45fa035bf1e7fd21b771b2fb2851a 100644 --- a/fda-ui/package.json +++ b/fda-ui/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "dev": "export NODE_TLS_REJECT_UNAUTHORIZED=0 && nuxt --env.NODE_TLS_REJECT_UNAUTHORIZED=0 --port 3001", + "dev": "nuxt --port 3001", "docker": "nuxt > /dev/null", "build": "nuxt build", "start": "nuxt start", @@ -31,6 +31,7 @@ "core-js": "^3.6.5", "date-fns": "^2.16.1", "date-fns-tz": "^1.3.6", + "dotenv": "^16.0.3", "eslint": "^7.27.0", "express": "^4.17.1", "is-docker": "^2.2.1", diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue index 5d61dd88f1a870cc102ca627c9261ffe32f84c72..434c091a86c2bd71d5fe1364a7f609f440dfdbb4 100644 --- a/fda-ui/pages/login.vue +++ b/fda-ui/pages/login.vue @@ -14,7 +14,7 @@ <v-row dense> <v-col sm="6"> <v-text-field - v-model="loginAccount.username" + v-model="username" autocomplete="off" autofocus required @@ -26,7 +26,7 @@ <v-row dense> <v-col sm="6"> <v-text-field - v-model="loginAccount.password" + v-model="password" autocomplete="off" type="password" required @@ -56,22 +56,15 @@ </template> <script> -import VueJwtDecode from 'vue-jwt-decode' -import qs from 'qs' +import { authenticate } from '@/api/user' export default { data () { return { loading: false, error: false, // XXX: `error` is never changed valid: false, - loginAccount: { - client_id: 'dbrepo-client', - username: null, - password: null, - grant_type: 'password', - client_secret: this.$config.client_secret, - scope: 'openid' - } + username: null, + password: null } }, computed: { @@ -91,11 +84,6 @@ export default { return { headers: { Authorization: `Bearer ${this.token}` } } - }, - keycloakConfig () { - return { - headers: { ContentType: 'application/x-www-form-urlencoded' } - } } }, mounted () { @@ -114,36 +102,38 @@ export default { async login () { try { this.loading = true - const res = await this.$axios.post('/api/auth/realms/dbrepo/protocol/openid-connect/token', qs.stringify(this.loginAccount), this.keycloakConfig) + const res = await authenticate(this.username, this.password) console.debug('login user', res.data) // eslint-disable-next-line camelcase - const { access_token } = res.data - this.$store.commit('SET_TOKEN', access_token) - const data = VueJwtDecode.decode(access_token) - const user = { - id: data.sub, - firstname: data.given_name, - lastname: data.family_name, - username: data.preferred_username, - theme_dark: data.theme_dark, - email_verified: data.email_verified - } - this.$store.commit('SET_USER', user) - this.$vuetify.theme.dark = false - await this.$router.push({ path: this.$route.query.redirect ? this.$route.query.redirect : '/container' }) + // const { access_token, refresh_token } = res.data + // this.$store.commit('SET_TOKEN', access_token) + // this.$store.commit('SET_REFRESH_TOKEN', refresh_token) + // const data = VueJwtDecode.decode(access_token) + // const user = { + // id: data.sub, + // firstname: data.given_name, + // lastname: data.family_name, + // username: data.preferred_username, + // theme_dark: data.theme_dark, + // email_verified: data.email_verified + // } + // this.$store.commit('SET_USER', user) + // this.$vuetify.theme.dark = user?.theme_dark || false + // await this.$router.push({ path: this.$route.query.redirect ? this.$route.query.redirect : '/container' }) } catch (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) - } - this.loading = false + 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) + // } + // this.loading = false } }, signup () { diff --git a/fda-ui/pages/user/info.vue b/fda-ui/pages/user/info.vue index c4870864e7966fc4f70dc6aea6d5b140608dc98b..d9d6adc43651dc3c141f8ff182316bd08fef7096 100644 --- a/fda-ui/pages/user/info.vue +++ b/fda-ui/pages/user/info.vue @@ -1,5 +1,6 @@ <template> <div v-if="token"> + <pre>{{ user }}</pre> <UserToolbar /> <v-tabs-items v-model="tab"> <v-tab-item> diff --git a/fda-ui/store/index.js b/fda-ui/store/index.js index 890c896dd56aca203765f500eca2f91102fb2155..d7cd95a022d8731e46b4287d1f36ab461ddbbadb 100644 --- a/fda-ui/store/index.js +++ b/fda-ui/store/index.js @@ -1,5 +1,6 @@ export const state = () => ({ token: null, + refreshToken: null, user: null, database: null, table: null, @@ -13,6 +14,9 @@ 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 diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js index 2cb3310639179d677ae038562ba7be92a03504c8..29c0e8385d09c11e92592062266d66069ef9b059 100644 --- a/fda-ui/utils/index.js +++ b/fda-ui/utils/index.js @@ -1,4 +1,5 @@ const { format } = require('date-fns') +const VueJwtDecode = require('vue-jwt-decode') function notEmpty (str) { return typeof str === 'string' && str.trim().length > 0 @@ -152,6 +153,29 @@ function formatTimestampUTC (str) { return format(new Date(date), 'yyyy-MM-dd HH:mm:ss') } +function jwtToUser (jwt) { + // eslint-disable-next-line camelcase + const { access_token } = jwt + const data = VueJwtDecode.decode(access_token) + return { + id: data.sub, + firstname: data.given_name, + lastname: data.family_name, + username: data.preferred_username, + theme_dark: data?.theme_dark, + orcid: data?.orcid, + titles_before: data?.titles_before, + titles_after: data?.titles_after, + email_verified: data.email_verified + } +} + +function isTokenExpired (accessToken) { + const data = VueJwtDecode.decode(accessToken) + const exp = new Date(data.exp) + return exp <= new Date() +} + module.exports = { notEmpty, formatTimestamp, @@ -166,5 +190,7 @@ module.exports = { formatCreators, isDeveloper, isResearcher, - isDataSteward + isDataSteward, + jwtToUser, + isTokenExpired } diff --git a/fda-ui/yarn.lock b/fda-ui/yarn.lock index c13f79ce87b2b72bc9c6e59bcb8157db87582c41..3ca5ba3bbdd1ae9baf45f3e80b9d117037d8068c 100644 --- a/fda-ui/yarn.lock +++ b/fda-ui/yarn.lock @@ -4744,6 +4744,11 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +dotenv@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + dotenv@^8.1.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -5774,6 +5779,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fs@^0.0.1-security: + version "0.0.1-security" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== + fsevents@^1.2.7: version "1.2.13" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"