From 82470fac4c972649f4a39f5930bde194fc369d19 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sat, 25 Jan 2025 15:18:11 +0100 Subject: [PATCH] Added OIDC auth Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- dbrepo-ui/bun.lockb | Bin 381903 -> 441810 bytes dbrepo-ui/components/OntologiesList.vue | 15 +- .../components/database/DatabaseToolbar.vue | 21 +- dbrepo-ui/components/identifier/Persist.vue | 20 +- dbrepo-ui/components/identifier/Select.vue | 15 +- dbrepo-ui/components/identifier/Summary.vue | 4 +- dbrepo-ui/components/subset/Builder.vue | 15 +- dbrepo-ui/components/subset/SubsetList.vue | 9 +- dbrepo-ui/components/subset/SubsetToolbar.vue | 20 +- dbrepo-ui/components/table/TableList.vue | 14 +- dbrepo-ui/components/table/TableToolbar.vue | 27 +- dbrepo-ui/components/user/UserToolbar.vue | 24 +- dbrepo-ui/components/view/ViewList.vue | 5 - dbrepo-ui/components/view/ViewToolbar.vue | 23 +- dbrepo-ui/composables/axios-instance.ts | 36 +-- dbrepo-ui/composables/upload-service.ts | 10 +- dbrepo-ui/composables/user-service.ts | 45 --- dbrepo-ui/layouts/default.vue | 61 ++-- dbrepo-ui/nuxt.config.ts | 29 +- dbrepo-ui/package.json | 1 + dbrepo-ui/pages/container/index.vue | 24 +- .../pages/database/[database_id]/info.vue | 15 +- .../persist/[identifier_id]/index.vue | 18 +- .../database/[database_id]/persist/index.vue | 23 +- .../pages/database/[database_id]/settings.vue | 20 +- .../[database_id]/subset/[subset_id]/info.vue | 7 +- .../persist/[identifier_id]/index.vue | 18 +- .../subset/[subset_id]/persist/index.vue | 17 +- .../database/[database_id]/subset/create.vue | 18 +- .../[database_id]/table/[table_id]/data.vue | 31 +- .../[database_id]/table/[table_id]/import.vue | 15 +- .../[database_id]/table/[table_id]/info.vue | 27 +- .../persist/[identifier_id]/index.vue | 14 +- .../table/[table_id]/persist/index.vue | 7 +- .../[database_id]/table/[table_id]/schema.vue | 25 +- .../table/[table_id]/settings.vue | 31 +- .../[database_id]/table/create/dataset.vue | 14 +- .../[database_id]/table/create/schema.vue | 14 +- .../[database_id]/view/[view_id]/data.vue | 19 +- .../[database_id]/view/[view_id]/info.vue | 24 +- .../persist/[identifier_id]/index.vue | 14 +- .../view/[view_id]/persist/index.vue | 7 +- .../[database_id]/view/[view_id]/schema.vue | 20 +- .../[database_id]/view/[view_id]/settings.vue | 29 +- .../database/[database_id]/view/create.vue | 16 +- dbrepo-ui/pages/index.vue | 35 ++- dbrepo-ui/pages/login.vue | 160 ---------- dbrepo-ui/pages/search.vue | 13 +- dbrepo-ui/pages/semantic/index.vue | 194 ------------- .../semantic/ontology/_ontology_id/index.vue | 273 ------------------ dbrepo-ui/pages/semantic/ontology/index.vue | 96 ------ dbrepo-ui/pages/signup.vue | 6 +- dbrepo-ui/pages/user/authentication.vue | 26 +- dbrepo-ui/pages/user/developer.vue | 230 --------------- dbrepo-ui/pages/user/index.vue | 20 +- dbrepo-ui/pages/user/info.vue | 43 +-- dbrepo-ui/stores/cache.js | 20 ++ dbrepo-ui/stores/user.js | 60 ---- docker-compose.yml | 9 +- 59 files changed, 460 insertions(+), 1586 deletions(-) delete mode 100644 dbrepo-ui/pages/login.vue delete mode 100644 dbrepo-ui/pages/semantic/index.vue delete mode 100644 dbrepo-ui/pages/semantic/ontology/_ontology_id/index.vue delete mode 100644 dbrepo-ui/pages/semantic/ontology/index.vue delete mode 100644 dbrepo-ui/pages/user/developer.vue delete mode 100644 dbrepo-ui/stores/user.js diff --git a/dbrepo-ui/bun.lockb b/dbrepo-ui/bun.lockb index 45a8c51c621dab127458d68a4493b23d2df9f88d..7ee1d3897245ee94212d8bfb6a6b97556b64f1d2 100755 GIT binary patch delta 109688 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 delta 75538 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 diff --git a/dbrepo-ui/components/OntologiesList.vue b/dbrepo-ui/components/OntologiesList.vue index c7120cac4a..432d26e428 100644 --- a/dbrepo-ui/components/OntologiesList.vue +++ b/dbrepo-ui/components/OntologiesList.vue @@ -34,29 +34,20 @@ </div> </template> +<script setup> +</script> <script> -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { data () { return { - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - token () { - return this.userStore.getToken - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, ontologies () { - return this.cacheStore.getOntologies + return [] } }, mounted () { diff --git a/dbrepo-ui/components/database/DatabaseToolbar.vue b/dbrepo-ui/components/database/DatabaseToolbar.vue index 4177ae592c..9d43b262e3 100644 --- a/dbrepo-ui/components/database/DatabaseToolbar.vue +++ b/dbrepo-ui/components/database/DatabaseToolbar.vue @@ -81,9 +81,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import { useCacheStore } from '@/stores/cache.js' -import { useUserStore } from '@/stores/user.js' import ResourceStatus from '@/components/ResourceStatus.vue' export default { @@ -94,8 +100,7 @@ export default { return { tab: null, error: false, - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { @@ -103,13 +108,7 @@ export default { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles + return this.cacheStore.getAccess }, isContrastTheme () { return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') @@ -172,7 +171,7 @@ export default { if (!this.database || !this.user) { return false } - return this.database.owner.username === this.user.username + return this.database.owner.id === this.userInfo.uid }, buttonVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/components/identifier/Persist.vue b/dbrepo-ui/components/identifier/Persist.vue index 3dba450e63..408d7e8265 100644 --- a/dbrepo-ui/components/identifier/Persist.vue +++ b/dbrepo-ui/components/identifier/Persist.vue @@ -827,10 +827,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import { formatYearUTC, formatMonthUTC, formatDayUTC, languages } from '@/utils' import { useCacheStore } from '@/stores/cache.js' -import { useUserStore } from '@/stores/user.js' import { MerkleJson } from 'merkle-json' export default { @@ -962,17 +968,10 @@ export default { { value: 'IsObsoletedBy' }, { value: 'Obsoletes' } ], - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, isSubset () { return this.type === 'subset' }, @@ -1045,9 +1044,6 @@ export default { } } }, - isUpdate () { - return 'id' in this.identifier && this.identifier.id - }, canInsertSelf () { if (!this.user) { return false diff --git a/dbrepo-ui/components/identifier/Select.vue b/dbrepo-ui/components/identifier/Select.vue index 4404a09635..84f87e321f 100644 --- a/dbrepo-ui/components/identifier/Select.vue +++ b/dbrepo-ui/components/identifier/Select.vue @@ -41,10 +41,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import Banner from '@/components/identifier/Banner.vue' import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -68,17 +74,10 @@ export default { data () { return { idx: null, - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, displayIdentifiers () { if (!this.identifiers) { return [] diff --git a/dbrepo-ui/components/identifier/Summary.vue b/dbrepo-ui/components/identifier/Summary.vue index 655a7bb907..6ef120599b 100644 --- a/dbrepo-ui/components/identifier/Summary.vue +++ b/dbrepo-ui/components/identifier/Summary.vue @@ -170,10 +170,10 @@ export default { }, computed: { access () { - return this.userStore.getAccess.value + return this.cacheStore.getAccess }, database () { - return this.cacheStore.getDatabase.value + return this.cacheStore.getDatabase }, pid () { return `/pid/${this.database.identifier.id}` diff --git a/dbrepo-ui/components/subset/Builder.vue b/dbrepo-ui/components/subset/Builder.vue index b45881479c..ae7df27683 100644 --- a/dbrepo-ui/components/subset/Builder.vue +++ b/dbrepo-ui/components/subset/Builder.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="loggedIn"> <v-toolbar flat> <v-btn size="small" @@ -303,12 +304,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> import TimeDrift from '@/components/TimeDrift.vue' import Raw from '@/components/subset/Raw.vue' import Results from '@/components/subset/Results.vue' import { useCacheStore } from '@/stores/cache.js' -import { useUserStore } from '@/stores/user.js' import { format } from 'sql-formatter' export default { @@ -359,8 +364,7 @@ export default { tabs: 0, loadingQuery: false, loadingColumns: false, - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { @@ -388,9 +392,6 @@ export default { } return this.database.container.image.data_types }, - user () { - return this.userStore.getUser - }, viewNames () { if (!this.database) { return [] diff --git a/dbrepo-ui/components/subset/SubsetList.vue b/dbrepo-ui/components/subset/SubsetList.vue index 6908b2b438..eb6a27aacd 100644 --- a/dbrepo-ui/components/subset/SubsetList.vue +++ b/dbrepo-ui/components/subset/SubsetList.vue @@ -45,8 +45,6 @@ </template> <script> -import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -55,14 +53,10 @@ export default { loadingSubsets: false, loadingIdentifiers: false, subsets: [], - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -130,7 +124,6 @@ export default { } } </script> - <style lang="scss" scoped> .pid-icon { flex: 0 !important; diff --git a/dbrepo-ui/components/subset/SubsetToolbar.vue b/dbrepo-ui/components/subset/SubsetToolbar.vue index d5f45e48e3..45ca762628 100644 --- a/dbrepo-ui/components/subset/SubsetToolbar.vue +++ b/dbrepo-ui/components/subset/SubsetToolbar.vue @@ -55,10 +55,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +</script> <script> import DownloadButton from '@/components/identifier/DownloadButton.vue' import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -71,7 +76,6 @@ export default { loading: false, loadingSave: false, downloadLoading: false, - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -86,13 +90,7 @@ export default { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles + return this.cacheStore.getAccess }, subset () { return this.cacheStore.getSubset @@ -154,10 +152,10 @@ export default { return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, canGetPid () { - if (!this.user || !this.subset || !this.database) { + if (!this.userInfo || !this.subset || !this.database) { return false } - return this.database.owner.id === this.user.id || (this.subset.owner.id === this.user.id && this.hasReadAccess) + return this.database.owner.id === this.userInfo.uid || (this.subset.owner.id === this.userInfo.uid && this.hasReadAccess) }, title () { if (!this.identifier) { diff --git a/dbrepo-ui/components/table/TableList.vue b/dbrepo-ui/components/table/TableList.vue index b78e20ae3a..d34483422d 100644 --- a/dbrepo-ui/components/table/TableList.vue +++ b/dbrepo-ui/components/table/TableList.vue @@ -38,9 +38,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -74,19 +80,15 @@ export default { { value: 'string', title: 'Character Varying' }, { value: 'text', title: 'Text' } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, tables () { if (!this.database) { diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue index d6fd4868ea..9aee22348f 100644 --- a/dbrepo-ui/components/table/TableToolbar.vue +++ b/dbrepo-ui/components/table/TableToolbar.vue @@ -77,10 +77,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import EditTuple from '@/components/dialogs/EditTuple.vue' import { useCacheStore } from '@/stores/cache.js' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -93,8 +99,7 @@ export default { error: false, edit: false, dropTableDialog: false, - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { @@ -105,7 +110,7 @@ export default { return this.cacheStore.getTable }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -113,17 +118,11 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, canUpdateTable () { if (!this.roles || !this.user || !this.table) { return false } - return this.roles.includes('update-table') && this.table.owner.id === this.user.id + return this.roles.includes('update-table') && this.table.owner.id === this.userInfo.uid }, canExecuteQuery () { if (!this.roles || !this.table || !this.user) { @@ -149,7 +148,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid }, canViewSchema () { if (!this.table) { @@ -161,7 +160,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid }, canImportCsv () { if (!this.roles || !this.table || !this.user) { @@ -173,7 +172,7 @@ export default { if (!this.user || !this.table || !this.database) { return false } - return this.database.owner.id === this.user.id || this.table.owner.id === this.user.id + return this.database.owner.id === this.userInfo.uid || this.table.owner.id === this.userInfo.uid }, buttonVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/components/user/UserToolbar.vue b/dbrepo-ui/components/user/UserToolbar.vue index e5a20c75a3..868bab88a9 100644 --- a/dbrepo-ui/components/user/UserToolbar.vue +++ b/dbrepo-ui/components/user/UserToolbar.vue @@ -1,6 +1,9 @@ <template> - <div> - <v-toolbar title="Settings" flat> + <div + v-if="loggedIn"> + <v-toolbar + title="Settings" + flat> <template v-slot:extension> <v-tabs v-model="tab" @@ -11,31 +14,20 @@ <v-tab :text="$t('toolbars.user.authentication')" to="/user/authentication" /> - <v-tab - :text="$t('toolbars.user.developer')" - to="/user/developer" /> </v-tabs> </template> </v-toolbar> </div> </template> +<script setup> +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> -import { useUserStore } from '@/stores/user.js' - export default { data () { return { tab: null, - userStore: useUserStore() - } - }, - computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles } } } diff --git a/dbrepo-ui/components/view/ViewList.vue b/dbrepo-ui/components/view/ViewList.vue index d6539bd253..58038b7a82 100644 --- a/dbrepo-ui/components/view/ViewList.vue +++ b/dbrepo-ui/components/view/ViewList.vue @@ -34,7 +34,6 @@ </template> <script> -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -43,14 +42,10 @@ export default { loading: false, loadingDetails: false, error: false, - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/components/view/ViewToolbar.vue b/dbrepo-ui/components/view/ViewToolbar.vue index 4ed83ff43f..74eac9dedf 100644 --- a/dbrepo-ui/components/view/ViewToolbar.vue +++ b/dbrepo-ui/components/view/ViewToolbar.vue @@ -56,8 +56,14 @@ </v-toolbar> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' import CreateOntology from '@/components/dialogs/CreateOntology.vue' import ViewVisibility from '@/components/dialogs/ViewVisibility.vue' @@ -73,7 +79,6 @@ export default { loading: false, loadingDelete: false, updateViewDialog: false, - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -101,7 +106,7 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.userInfo.id || this.database.owner.id === this.userInfo.id }, canViewSchema () { if (!this.view) { @@ -113,13 +118,13 @@ export default { if (!this.user) { return false } - return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.userInfo.id || this.database.owner.id === this.userInfo.id }, canViewSettings () { if (!this.user || !this.view) { return false } - return this.view.owner.id === this.user.id + return this.view.owner.id === this.userInfo.id }, canCreatePid () { if (!this.roles || !this.user || !this.view) { @@ -129,13 +134,7 @@ export default { return this.roles.includes('create-identifier') && userService.hasReadAccess(this.access) }, access () { - return this.userStore.getAccess - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { diff --git a/dbrepo-ui/composables/axios-instance.ts b/dbrepo-ui/composables/axios-instance.ts index 95edea3c28..ca7a7b111c 100644 --- a/dbrepo-ui/composables/axios-instance.ts +++ b/dbrepo-ui/composables/axios-instance.ts @@ -1,11 +1,9 @@ import axios, {type AxiosInstance} from 'axios' -import {useUserStore} from '@/stores/user' let instance: AxiosInstance | null = null; export const useAxiosInstance = () => { const config = useRuntimeConfig() - const userStore = useUserStore() if (!instance) { instance = axios.create({ timeout: 90_000, @@ -18,38 +16,16 @@ export const useAxiosInstance = () => { baseURL: config.public.api.client }); instance.interceptors.request.use((config) => { - const token = userStore.getToken - const refreshToken = userStore.getRefreshToken - if (!token || !refreshToken) { + const { loggedIn, user, login, logout } = useOidcAuth() + if (!loggedIn) { return config } - const authenticationService = useAuthenticationService() - if (authenticationService.isExpiredToken(refreshToken)) { - console.warn('Refresh token is expired: trigger logout of user') - userStore.logout() + const { accessToken } = user.value + if (!accessToken) { return config } - if (!authenticationService.isExpiredToken(token)) { - config.headers.Authorization = `Bearer ${token}` - return config - } - console.warn('Access token expired: request a new one') - const userService = useUserService() - return userService.refreshToken(refreshToken) - .then((response: KeycloakOpenIdTokenDto) => { - userStore.setToken(response.access_token) - userStore.setRefreshToken(response.refresh_token) - console.debug('new access token expires:', authenticationService.tokenToExpiryDate(response.access_token)) - config.headers.Authorization = `Bearer ${response.access_token}` - return config - }) - .catch((error: ApiErrorDto) => { - if (error.code === 'error.user.credentials') { - console.warn('User session expired.') - userStore.logout() - } - return config - }); + config.headers.Authorization = `Bearer ${accessToken}` + return config }) } return instance; diff --git a/dbrepo-ui/composables/upload-service.ts b/dbrepo-ui/composables/upload-service.ts index f7a6964d58..ee0bdd5dc0 100644 --- a/dbrepo-ui/composables/upload-service.ts +++ b/dbrepo-ui/composables/upload-service.ts @@ -1,11 +1,9 @@ import * as tus from 'tus-js-client' import {useCacheStore} from '@/stores/cache' -import {useUserStore} from '@/stores/user' export const useUploadService = (): any => { function create (data: File) { - const userStore = useUserStore() const config = useRuntimeConfig() const endpoint = config.public.upload.client return new Promise<string>((resolve, reject) => { @@ -13,10 +11,16 @@ export const useUploadService = (): any => { console.error('Your browser does not support uploads!') return } + const { loggedIn, user, login, logout } = useOidcAuth() + if (!loggedIn || !user.value?.accessToken) { + console.error('Please login to use the upload!') + return + } + const { accessToken } = user.value const uploadClient: tus.Upload = new tus.Upload(data, { endpoint, headers: { - 'Authorization': `Bearer ${userStore.getToken}` + 'Authorization': `Bearer ${accessToken}` }, retryDelays: [0, 3000, 5000, 10000, 20000], onError (error) { diff --git a/dbrepo-ui/composables/user-service.ts b/dbrepo-ui/composables/user-service.ts index e68b914e0e..5381fee565 100644 --- a/dbrepo-ui/composables/user-service.ts +++ b/dbrepo-ui/composables/user-service.ts @@ -80,32 +80,6 @@ export const useUserService = (): any => { }) } - async function obtainToken(username: string, password: string): Promise<KeycloakOpenIdTokenDto> { - console.debug('obtain user token for user with username', username) - return new Promise<KeycloakOpenIdTokenDto>((resolve, reject) => { - const config = useRuntimeConfig() - const userStore = useUserStore() - const instance = axios.create({ - timeout: 90_000, - params: {}, - baseURL: config.public.api.client - }) - instance.post<KeycloakOpenIdTokenDto>('/api/user/token', {username, password}) - .then((response) => { - console.info('Obtained user token') - // eslint-disable-next-line camelcase - const {access_token, refresh_token} = response.data - userStore.setToken(access_token) - userStore.setRefreshToken(refresh_token) - userStore.setRoles(tokenToRoles(access_token)) - resolve(response.data) - }).catch((error) => { - console.error('Failed to obtain user token', error) - reject(axiosErrorToApiError(error)) - }) - }) - } - async function refreshToken(refreshToken: string): Promise<KeycloakOpenIdTokenDto> { console.debug('refresh user token') return new Promise<KeycloakOpenIdTokenDto>((resolve, reject) => { @@ -136,21 +110,6 @@ export const useUserService = (): any => { return data.realm_access.roles || [] } - function tokenToUserId(token: string): string { - const data: Token = jwtDecode<Token>(token) - return data.uid - } - - function userInfoToUser(data: UserDto) { - const obj: UserDto = Object.assign({}, data) - obj.attributes = { - theme: data.attributes.theme, - orcid: data.attributes.orcid, - affiliation: data.attributes.affiliation - } - return obj - } - function nameIdentifierToNameIdentifierScheme(nameIdentifier: string) { if (nameIdentifier.includes('orcid.org')) { return 'ORCID' @@ -197,11 +156,7 @@ export const useUserService = (): any => { update, create, updatePassword, - obtainToken, refreshToken, - tokenToRoles, - tokenToUserId, - userInfoToUser, nameIdentifierToNameIdentifierScheme, userToFullName, hasReadAccess, diff --git a/dbrepo-ui/layouts/default.vue b/dbrepo-ui/layouts/default.vue index 0ad4cb818d..e65a256906 100644 --- a/dbrepo-ui/layouts/default.vue +++ b/dbrepo-ui/layouts/default.vue @@ -96,16 +96,16 @@ @click:append-inner="retrieve" /> <v-spacer /> <v-btn - v-if="!user" + v-if="!loggedIn" class="mr-2" color="secondary" variant="flat" :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-login' : null" - to="/login"> + @click="login()"> {{ $t('navigation.login') }} </v-btn> <v-btn - v-if="!user" + v-if="!loggedIn" color="primary" variant="flat" :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-account-plus' : null" @@ -113,12 +113,12 @@ {{ $t('navigation.signup') }} </v-btn> <v-btn - v-if="user" + v-if="loggedIn" to="/user" variant="plain" - :text="user.username" /> + :text="userInfo.preferred_username" /> <v-menu - v-if="user" + v-if="loggedIn" location="bottom"> <template v-slot:activator="{ props }"> <v-btn @@ -140,7 +140,7 @@ </v-list-item> <v-list-item v-if="user" - @click="logout"> + @click="logout()"> {{ $t('navigation.logout') }} </v-list-item> </v-list> @@ -163,6 +163,9 @@ <script setup> import { ref } from 'vue' +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) const runtimeConfig = useRuntimeConfig() const config = ref(runtimeConfig) useServerHead({ @@ -175,10 +178,10 @@ useServerHead({ </script> <script> import JumboBox from '@/components/JumboBox.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' import { errorCodeKey, makeError } from '@/utils' + export default { components: { JumboBox @@ -197,26 +200,13 @@ export default { loadingSearch: false, loadingDatabases: false, search: null, - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - token () { - return this.userStore.getToken - }, - user () { - return this.userStore.getUser - }, - locale () { - return this.userStore.getLocale - }, messages () { return this.cacheStore.getMessages }, - access () { - return this.userStore.getAccess - }, table () { return this.cacheStore.getTable }, @@ -244,9 +234,6 @@ export default { } return 'database' }, - roles () { - return this.userStore.getRoles - }, version () { return this.$config.public.version }, @@ -295,6 +282,9 @@ export default { logo () { return this.$config.public.logo }, + locale () { + return this.cacheStore.getLocale + }, searchVariant () { const runtimeConfig = useRuntimeConfig() return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : 'solo-filled' @@ -319,8 +309,8 @@ export default { .catch((error) => { this.databaseError = error }) - if (this.user) { - this.userStore.setRouteAccess(newObj.database_id) + if (this.userInfo) { + this.cacheStore.setRouteAccess(newObj.database_id, this.userInfo.uid) } /* load table */ if (newObj.table_id) { @@ -357,27 +347,14 @@ export default { this.cacheStore.reloadMessages() }, methods: { - errorCodeKey, - login () { - const redirect = ![undefined, '/', '/login'].includes(this.$router.currentRoute.path) - this.$router.push({ path: '/login', query: redirect ? { redirect: this.$router.currentRoute.path } : {} }) - }, - logout () { - this.$vuetify.theme.global.name = 'tuwThemeLight' - this.userStore.logout() - this.$router.push('/database') - }, retrieve () { console.debug('performing fuzzy search') this.$router.push({ path: '/search', query: { q: this.search } }) }, initEnvironment () { - if (this.token && !this.user) { - console.error('Something went wrong with loading the user: reset user cache') - this.userStore.logout() - } if (!this.locale) { - this.userStore.setLocale('en') + this.cacheStore.setLocale('en') + return } this.$i18n.locale = this.locale }, @@ -398,7 +375,7 @@ export default { } }, setLocale (code) { - this.userStore.setLocale(code) + this.cacheStore.setLocale(code) this.$i18n.locale = this.locale } } diff --git a/dbrepo-ui/nuxt.config.ts b/dbrepo-ui/nuxt.config.ts index 4b1833d816..1804b3a3fd 100644 --- a/dbrepo-ui/nuxt.config.ts +++ b/dbrepo-ui/nuxt.config.ts @@ -107,11 +107,32 @@ export default defineNuxtConfig({ port: 3001 }, + oidc: { + providers: { + keycloak: { + audience: 'account', + baseUrl: 'http://localhost:8080/realms/dbrepo', + clientId: 'dbrepo-client', + clientSecret: '', // inject on runtime + scope: ['openid', 'roles'], + optionalClaims: ['realm_access'], + redirectUri: 'http://localhost/auth/keycloak/callback', + userNameClaim: 'preferred_username', + exposeAccessToken: true, + logoutRedirectUri: 'http://localhost', + }, + }, + middleware: { + globalMiddlewareEnabled: false + }, + }, + modules: [ - '@artmizu/nuxt-prometheus', + ['@artmizu/nuxt-prometheus', {verbose: false}], '@nuxtjs/i18n', '@pinia/nuxt', '@pinia-plugin-persistedstate/nuxt', + 'nuxt-oidc-auth', async (options, nuxt) => { nuxt.hooks.hook('vite:extendConfig', config => config.plugins.push( vuetify() @@ -160,6 +181,8 @@ export default defineNuxtConfig({ }, }, - devtools: {enabled: true}, - compatibilityDate: '2024-07-24' + devtools: { + enabled: false + }, + compatibilityDate: '2025-01-25' }) diff --git a/dbrepo-ui/package.json b/dbrepo-ui/package.json index a135477820..ec3ae1e6a4 100644 --- a/dbrepo-ui/package.json +++ b/dbrepo-ui/package.json @@ -28,6 +28,7 @@ "merkle-json": "^2.6.0", "moment": "^2.30.1", "nuxt": "^3.10.3", + "nuxt-oidc-auth": "^1.0.0-beta.5", "parse-md": "^3.0.3", "pinia": "^2.1.7", "qs": "^6.11.2", diff --git a/dbrepo-ui/pages/container/index.vue b/dbrepo-ui/pages/container/index.vue index 360ce1543f..ec2149372e 100644 --- a/dbrepo-ui/pages/container/index.vue +++ b/dbrepo-ui/pages/container/index.vue @@ -25,19 +25,19 @@ export default { containers: [] } }, - computed: { - roles () { - return this.userStore.getRoles - }, - }, mounted () { - this.loading = true - const containerService = useContainerService(); - containerService.findAll() - .then((containers) => { - this.containers = containers - this.loading = false - }) + this.fetchContainers() + }, + methods: { + fetchContainers () { + this.loading = true + const containerService = useContainerService(); + containerService.findAll() + .then((containers) => { + this.containers = containers + this.loading = false + }) + } } } </script> diff --git a/dbrepo-ui/pages/database/[database_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/info.vue index 6e1e35aabb..33d63b29a9 100644 --- a/dbrepo-ui/pages/database/[database_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/info.vue @@ -163,13 +163,17 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import Summary from '@/components/identifier/Summary.vue' import Select from '@/components/identifier/Select.vue' import UserBadge from '@/components/user/UserBadge.vue' import { sizeToHumanLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -197,7 +201,6 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -223,15 +226,9 @@ export default { } return this.database.identifier.publisher }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, - roles () { - return this.userStore.getRoles - }, identifiers () { if (!this.database) { return [] @@ -257,7 +254,7 @@ export default { return this.filteredIdentifiers[0] }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, pid () { return this.$route.query.pid diff --git a/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue index a57b439b21..2c2e5ef120 100644 --- a/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/persist/[identifier_id]/index.vue @@ -8,10 +8,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -39,17 +44,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/persist/index.vue index df675d262e..a3581c0c82 100644 --- a/dbrepo-ui/pages/database/[database_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/persist/index.vue @@ -8,10 +8,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -35,17 +41,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -56,10 +55,10 @@ export default { return false }, isOwner () { - if (!this.database || !this.user) { + if (!this.database || !this.userInfo) { return false } - return this.database.owner.username === this.user.username + return this.database.owner.id === this.userInfo.uid }, canCreateIdentifier () { if (!this.roles || this.hasIdentifier) { diff --git a/dbrepo-ui/pages/database/[database_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/settings.vue index d0fb517dae..5b0aa2a453 100644 --- a/dbrepo-ui/pages/database/[database_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/settings.vue @@ -244,10 +244,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import EditAccess from '@/components/dialogs/EditAccess.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -323,7 +329,6 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -335,16 +340,7 @@ export default { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess - }, - token () { - return this.userStore.getToken - }, - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser + return this.cacheStore.getAccess }, uploadProgress () { return this.cacheStore.getUploadProgress diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue index f067fbadb4..a9956278d1 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue @@ -92,7 +92,6 @@ import SubsetToolbar from '@/components/subset/SubsetToolbar.vue' import Select from '@/components/identifier/Select.vue' import UserBadge from '@/components/user/UserBadge.vue' import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -134,7 +133,6 @@ export default { downloadLoading: false, error: false, promises: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -146,14 +144,11 @@ export default { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, subset () { return this.cacheStore.getSubset }, - user () { - return this.userStore.getUser - }, identifiers () { if (!this.database || !this.database.subsets || this.database.subsets.length === 0) { return [] diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue index b15ecb3292..0e1dac8c7e 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/[identifier_id]/index.vue @@ -8,10 +8,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -47,17 +52,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue index 07be66bc73..cc0dbf4958 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/persist/index.vue @@ -9,10 +9,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import Persist from '~/components/identifier/Persist.vue' -import { useUserStore } from '~/stores/user.js' -import { useCacheStore } from '~/stores/cache.js' +import Persist from '@/components/identifier/Persist.vue' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -47,19 +52,15 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, canPersistQuery () { if (this.loadingQuery || !this.query) { diff --git a/dbrepo-ui/pages/database/[database_id]/subset/create.vue b/dbrepo-ui/pages/database/[database_id]/subset/create.vue index 0fb591f9f8..2ea1c5022a 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/create.vue @@ -6,8 +6,13 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> -import { useUserStore } from '@/stores/user.js' import Builder from '@/components/subset/Builder.vue' import {useCacheStore} from '@/stores/cache.js' @@ -36,22 +41,15 @@ export default { disabled: true } ], - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue index 07747ed0cb..ca120e89f7 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/data.vue @@ -81,6 +81,7 @@ @close="pickVersion" /> </v-dialog> <v-dialog + v-if="loggedIn" v-model="addTupleDialog" persistent max-width="640"> @@ -91,6 +92,7 @@ @close="close" /> </v-dialog> <v-dialog + v-if="loggedIn" v-model="editTupleDialog" persistent max-width="640"> @@ -104,12 +106,18 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableHistory from '@/components/table/TableHistory.vue' import TimeDrift from '@/components/TimeDrift.vue' import TableToolbar from '@/components/table/TableToolbar.vue' import { formatTimestamp } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' import EditTuple from '@/components/dialogs/EditTuple.vue' import BlobDownload from '@/components/table/BlobDownload.vue' @@ -179,25 +187,18 @@ export default { ], headers: [], rows: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, table () { return this.cacheStore.getTable }, - user () { - return this.userStore.getUser - }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -230,10 +231,10 @@ export default { return this.version.substring(0, 10) + 'T' + this.version.substring(11, 19) + 'Z' }, canModify () { - if (!this.user || !this.access || !this.table) { + if (!this.userInfo || !this.access || !this.table) { return false } - if (this.access.type === 'write_own' && this.table.owner.id === this.user.id) { + if (this.access.type === 'write_own' && this.table.owner.id === this.userInfo.uid) { return true } return this.access.type === 'write_all' @@ -264,28 +265,28 @@ export default { return false } const userService = useUserService() - return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('insert-table-data') + return userService.hasWriteAccess(this.table, this.access, this.userInfo) && this.roles.includes('insert-table-data') }, canSelectTuples () { if (!this.roles) { return false } const userService = useUserService() - return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('insert-table-data') + return userService.hasWriteAccess(this.table, this.access, this.userInfo) && this.roles.includes('insert-table-data') }, canEditTuple () { if (!this.roles || this.selection === null || this.selection.length !== 1) { return false } const userService = useUserService() - return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('insert-table-data') + return userService.hasWriteAccess(this.table, this.access, this.userInfo) && this.roles.includes('insert-table-data') }, canDeleteTuple () { if (!this.roles || this.selection === null || this.selection.length < 1) { return false } const userService = useUserService() - return userService.hasWriteAccess(this.table, this.access, this.user) && this.roles.includes('delete-table-data') + return userService.hasWriteAccess(this.table, this.access, this.userInfo) && this.roles.includes('delete-table-data') } }, watch: { diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue index 4cf0057ea4..46eb7106fd 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue @@ -28,9 +28,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableImport from '@/components/table/TableImport.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -69,17 +75,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, table () { return this.cacheStore.getTable }, diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue index 916c72b850..ca295a5587 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue @@ -118,12 +118,18 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableToolbar from '@/components/table/TableToolbar.vue' import Select from '@/components/identifier/Select.vue' import Summary from '@/components/identifier/Summary.vue' import UserBadge from '@/components/user/UserBadge.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -165,7 +171,6 @@ export default { loading: false, exchange: null, queue: null, - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -173,18 +178,12 @@ export default { pid () { return this.$route.query.pid }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, table () { return this.cacheStore.getTable }, - roles () { - return this.userStore.getRoles - }, canRead () { if (this.database && this.database.is_public) { return true @@ -204,19 +203,19 @@ export default { if (this.table.is_schema_public || this.table.is_public) { return true } - if (!this.user) { + if (!this.userInfo) { return false } - return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid }, canWrite () { if (!this.table || !this.user || !this.access) { return false } - return (this.access.type === 'write_own' && this.table.owned_by === this.user.id) || this.access.type === 'write_all' + return (this.access.type === 'write_own' && this.table.owned_by === this.userInfo.uid) || this.access.type === 'write_all' }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasDescription () { return this.table && this.table.description @@ -237,10 +236,10 @@ export default { if (!this.identifiers) { return [] } - if (!this.user) { + if (!this.userInfo) { return this.identifiers.filter(i => i.status === 'published') } - return this.identifiers.filter(i => i.status === 'published' || i.owned_by === this.user.id) + return this.identifiers.filter(i => i.status === 'published' || i.owned_by === this.userInfo.uid) }, identifier () { if (this.pid) { diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue index 663b2a5550..0e82a2210b 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/[identifier_id]/index.vue @@ -6,9 +6,14 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import Persist from '@/components/identifier/Persist.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -45,17 +50,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue index 250fedaa5d..ef608876be 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/persist/index.vue @@ -13,7 +13,6 @@ <script> import Persist from '@/components/identifier/Persist.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -48,19 +47,15 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, table () { return this.cacheStore.getTable diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue index 0c6a60e15b..4cbb8d37d1 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue @@ -120,9 +120,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableToolbar from '@/components/table/TableToolbar.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -168,14 +174,10 @@ export default { { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, ], dateColumns: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -183,7 +185,7 @@ export default { return this.cacheStore.getTable }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -191,9 +193,6 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, - roles () { - return this.userStore.getRoles - }, canViewSchema () { if (this.error) { return false @@ -204,16 +203,16 @@ export default { if (this.table.is_schema_public) { return true } - if (!this.user) { + if (!this.userInfo) { return false } - return this.hasReadAccess || this.table.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.table.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid }, primaryKeysColumns () { return this.table.constraints.primary_key.map(pk => pk.column.internal_name).join(', ') }, canAssignSemanticInformation () { - if (!this.user) { + if (!this.userInfo) { return false } if (this.roles.includes('modify-foreign-table-column-semantics')) { @@ -222,7 +221,7 @@ export default { if (!this.access) { return false } - return this.roles.includes('modify-table-column-semantics') && (this.access.type === 'write_all' || this.table.owner.username === this.user.username) + return this.roles.includes('modify-table-column-semantics') && (this.access.type === 'write_all' || this.table.owner.id === this.userInfo.uid) }, inputVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue index f953071136..ddf319328c 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue @@ -3,7 +3,7 @@ v-if="canUpdateTable"> <TableToolbar /> <v-window - v-if="user" + v-if="loggedIn" v-model="tab"> <v-window-item> <v-form @@ -114,9 +114,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableToolbar from '@/components/table/TableToolbar.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' import { max } from '@/utils' @@ -175,14 +181,10 @@ export default { { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, ], dateColumns: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -190,7 +192,7 @@ export default { return this.cacheStore.getTable }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -198,9 +200,6 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, - roles () { - return this.userStore.getRoles - }, isChange () { if (!this.table) { return false @@ -211,26 +210,26 @@ export default { return this.table.is_schema_public !== this.modify.is_schema_public }, canUpdateTable () { - if (!this.roles || !this.user || !this.table) { + if (!this.roles || !this.userInfo || !this.table) { return false } - return this.roles.includes('update-table') && this.table.owner.id === this.user.id + return this.roles.includes('update-table') && this.table.owner.id === this.userInfo.uid }, canModifyVisibility () { - if (!this.roles || !this.user || !this.table) { + if (!this.roles || !this.userInfo || !this.table) { return false } - return this.roles.includes('update-table') && this.table.owner.id === this.user.id + return this.roles.includes('update-table') && this.table.owner.id === this.userInfo.uid }, canDropTable () { - if (!this.roles || !this.table || !this.user) { + if (!this.roles || !this.table || !this.userInfo) { return false } if (this.roles.includes('delete-foreign-table')) { return true } const tableService = useTableService() - return tableService.isOwner(this.table, this.user) && this.roles.includes('delete-table') && this.table.identifiers.length === 0 + return tableService.isOwner(this.table, this.userInfo) && this.roles.includes('delete-table') && this.table.identifiers.length === 0 }, inputVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue b/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue index df74cc6e70..78bd136751 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/create/dataset.vue @@ -219,10 +219,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableSchema from '@/components/table/TableSchema.vue' import { notEmpty } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -304,7 +309,6 @@ export default { loading: false, url: null, columns: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -316,12 +320,6 @@ export default { this.tableCreate.is_schema_public = this.database.is_schema_public }, computed: { - user() { - return this.userStore.getUser - }, - roles() { - return this.userStore.getRoles - }, database() { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue index c900ba31aa..cf8de848de 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/create/schema.vue @@ -185,10 +185,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import TableSchema from '@/components/table/TableSchema.vue' import { notEmpty } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -247,7 +252,6 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, @@ -259,12 +263,6 @@ export default { const tableService = useTableService() return tableService.tableNameToInternalName(this.tableCreate.name) }, - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue index 54c54dad00..0b0caa3c4f 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/data.vue @@ -34,10 +34,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +</script> <script> import TimeDrift from '@/components/TimeDrift.vue' import QueryResults from '@/components/subset/Results.vue' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -70,14 +75,10 @@ export default { disabled: true } ], - cacheStore: useCacheStore(), - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -85,7 +86,7 @@ export default { return this.cacheStore.getView }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -100,10 +101,10 @@ export default { if (this.view.is_public) { return true } - if (!this.user) { + if (!this.userInfo) { return false } - return this.view.owner.id === this.user.id || this.hasReadAccess + return this.view.owner.id === this.userInfo.uid || this.hasReadAccess }, }, mounted () { diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue index c9865a1b4a..0ed006c4be 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue @@ -59,13 +59,18 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +</script> <script> import ViewToolbar from '@/components/view/ViewToolbar.vue' import Summary from '@/components/identifier/Summary.vue' import Select from '@/components/identifier/Select.vue' import UserBadge from '@/components/user/UserBadge.vue' import { formatTimestampUTCLabel } from '@/utils' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -103,22 +108,15 @@ export default { } ], error: false, - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, view () { return this.cacheStore.getView @@ -139,10 +137,10 @@ export default { if (!this.identifiers) { return [] } - if (!this.user) { + if (!this.userInfo) { return this.identifiers.filter(i => i.status === 'published') } - return this.identifiers.filter(i => i.status === 'published' || i.owner.id === this.user.id) + return this.identifiers.filter(i => i.status === 'published' || i.owner.id === this.userInfo.uid) }, identifier () { if (this.pid) { @@ -179,10 +177,10 @@ export default { if (this.view.is_public) { return true } - if (!this.user) { + if (!this.userInfo) { return false } - return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id + return this.hasReadAccess || this.view.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid } }, methods: { diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue index 8c1f24c2a1..f528c86675 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/[identifier_id]/index.vue @@ -8,9 +8,14 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import Persist from '@/components/identifier/Persist.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -47,17 +52,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue index b76d076645..c5082c3be9 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/persist/index.vue @@ -11,7 +11,6 @@ <script> import Persist from '@/components/identifier/Persist.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -45,14 +44,10 @@ export default { disabled: true } ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - roles () { - return this.userStore.getRoles - }, database () { return this.cacheStore.getDatabase }, @@ -63,7 +58,7 @@ export default { return this.database.views.filter(v => v.id === Number(this.$route.params.view_id))[0] }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, canPersistView () { if (!this.view) { diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue index 477654f656..5bd1ff5f9c 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/schema.vue @@ -51,9 +51,14 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +</script> <script> import TableToolbar from '@/components/table/TableToolbar.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -95,14 +100,10 @@ export default { { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') }, { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, ], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -110,7 +111,7 @@ export default { return this.cacheStore.getView }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -125,13 +126,10 @@ export default { if (this.view.is_schema_public) { return true } - if (!this.user) { + if (!this.userInfo) { return false } - return this.hasReadAccess || this.view.owner.id === this.user.id || this.database.owner.id === this.user.id - }, - roles () { - return this.userStore.getRoles + return this.hasReadAccess || this.view.owner.id === this.userInfo.uid || this.database.owner.id === this.userInfo.uid }, inputVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue index 18d73d0576..575e5b5f27 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/settings.vue @@ -90,9 +90,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import ViewToolbar from '@/components/view/ViewToolbar.vue' -import { useUserStore } from '@/stores/user.js' import { useCacheStore } from '@/stores/cache.js' export default { @@ -148,14 +154,10 @@ export default { { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, ], dateColumns: [], - userStore: useUserStore(), cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, database () { return this.cacheStore.getDatabase }, @@ -163,7 +165,7 @@ export default { return this.cacheStore.getView }, access () { - return this.userStore.getAccess + return this.cacheStore.getAccess }, hasReadAccess () { if (!this.access) { @@ -171,9 +173,6 @@ export default { } return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own' }, - roles () { - return this.userStore.getRoles - }, isChange () { if (!this.view) { return false @@ -184,22 +183,22 @@ export default { return this.view.is_schema_public !== this.modify.is_schema_public }, canUpdateVisibility () { - if (!this.roles || !this.user || !this.view) { + if (!this.roles || !this.userInfo || !this.view) { return false } - return this.roles.includes('modify-view-visibility') && this.view.owner.id === this.user.id + return this.roles.includes('modify-view-visibility') && this.view.owner.id === this.userInfo.uid }, canDeleteView () { - if (!this.roles || !this.user || !this.view) { + if (!this.roles || !this.userInfo || !this.view) { return false } - return this.roles.includes('delete-database-view') && this.view.owner.id === this.user.id + return this.roles.includes('delete-database-view') && this.view.owner.id === this.userInfo.uid }, canViewSettings () { - if (!this.user || !this.view) { + if (!this.userInfo || !this.view) { return false } - return this.view.owner.id === this.user.id + return this.view.owner.id === this.userInfo.uid }, inputVariant () { const runtimeConfig = useRuntimeConfig() diff --git a/dbrepo-ui/pages/database/[database_id]/view/create.vue b/dbrepo-ui/pages/database/[database_id]/view/create.vue index 47b56cfbad..b9d4a684d7 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/create.vue @@ -6,9 +6,14 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import Builder from '@/components/subset/Builder.vue' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -34,17 +39,10 @@ export default { to: `/database/${this.$route.params.database_id}/view/create`, disabled: true } - ], - userStore: useUserStore() + ] } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, canCreateView () { if (!this.roles) { return false diff --git a/dbrepo-ui/pages/index.vue b/dbrepo-ui/pages/index.vue index 1c30c25e5c..16cbbb283f 100644 --- a/dbrepo-ui/pages/index.vue +++ b/dbrepo-ui/pages/index.vue @@ -27,10 +27,12 @@ </div> </template> +<script setup> +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> import DatabaseList from '@/components/database/DatabaseList.vue' import DatabaseCreate from '@/components/database/DatabaseCreate.vue' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -41,13 +43,21 @@ export default { return { loading: true, dialog: null, - databases: [], - userStore: useUserStore() + databases: [] } }, computed: { + userInfo () { + if (!this.user) { + return null + } + return this.user.userInfo + }, roles () { - return this.userStore.getRoles + if (!this.user) { + return [] + } + return [] }, canCreateDatabase () { if (!this.roles) { @@ -57,17 +67,20 @@ export default { } }, mounted () { - this.loading = true - const databaseService = useDatabaseService(); - databaseService.findAll() - .then((databases) => { - this.databases = databases - this.loading = false - }) + this.fetchDatabases() }, methods: { closed () { this.dialog = false + }, + fetchDatabases () { + this.loading = true + const databaseService = useDatabaseService() + databaseService.findAll() + .then((databases) => { + this.databases = databases + this.loading = false + }) } } } diff --git a/dbrepo-ui/pages/login.vue b/dbrepo-ui/pages/login.vue deleted file mode 100644 index 532a221c48..0000000000 --- a/dbrepo-ui/pages/login.vue +++ /dev/null @@ -1,160 +0,0 @@ -<template> - <div> - <v-toolbar - v-if="!user" - variant="flat" - :title="$t('pages.login.name')"> - </v-toolbar> - <v-card - rounded="0" - variant="flat"> - <v-card-text> - <v-form - v-if="!user" - ref="form" - v-model="valid" - @submit.prevent="submit"> - <v-row - dense> - <v-col - md="8"> - <v-text-field - v-model="username" - autocomplete="off" - autofocus - required - name="username" - persistent-hint - :rules="[v => !!v || $t('validation.required')]" - :label="$t('pages.login.username.label')" - :hint="$t('pages.login.username.hint')"/> - </v-col> - </v-row> - <v-row - dense> - <v-col - md="8"> - <v-text-field - v-model="password" - autocomplete="off" - type="password" - required - name="password" - persistent-hint - :rules="[v => !!v || $t('validation.required')]" - :label="$t('pages.login.password.label')" - :hint="$t('pages.login.password.hint')"/> - </v-col> - </v-row> - <v-row> - <v-col - md="8"> - <v-btn - id="login" - class="mb-2" - :disabled="!valid" - color="primary" - variant="flat" - type="submit" - name="submit" - :loading="loading" - :text="$t('pages.login.submit.label')" - @click="login"/> - </v-col> - </v-row> - </v-form> - </v-card-text> - <v-card-actions> - <v-spacer/> - <v-btn - v-for="(link, i) in loginLinks" - :key="`li-${i}`" - variant="plain" - size="small" - :text="link.text" - :href="link.href"/> - </v-card-actions> - </v-card> - </div> -</template> - -<script> -import {useUserStore} from '@/stores/user.js' - -export default { - data() { - return { - loading: false, - valid: false, - username: null, - password: null, - userStore: useUserStore() - } - }, - computed: { - user() { - return this.userStore.getUser - }, - loginLinks() { - if (!this.$config.public.links) { - return [] - } - return Object.keys(this.$config.public.links).map(key => { - return this.$config.public.links[key] - }) - } - }, - methods: { - submit() { - this.$refs.form.validate() - }, - login() { - this.loading = true - const userService = useUserService() - userService.obtainToken(this.username, this.password) - .then((data) => { - const userId = userService.tokenToUserId(data.access_token) - userService.findOne(userId) - .then((user) => { - const toast = useToastInstance() - toast.success(this.$t('success.user.login', { username : user.username })) - switch (user.attributes.theme) { - case 'dark': - this.$vuetify.theme.global.name = 'tuwThemeDark' - break - case 'light': - this.$vuetify.theme.global.name = 'tuwThemeLight' - break - case 'light-contrast': - this.$vuetify.theme.global.name = 'tuwThemeLightContrast' - break - case 'dark-contrast': - this.$vuetify.theme.global.name = 'tuwThemeDarkContrast' - break - } - this.userStore.setUser(user) - this.$router.push('/database') - }) - .catch(({code}) => { - const toast = useToastInstance() - if (typeof code !== 'string') { - return - } - toast.error(this.$t(code)) - }) - }) - .catch(({code}) => { - this.loading = false - const toast = useToastInstance() - if (typeof code !== 'string') { - return - } - toast.error(this.$t(code)) - }) - .finally(() => { - this.loading = false - }) - } - } -} -</script> diff --git a/dbrepo-ui/pages/search.vue b/dbrepo-ui/pages/search.vue index 15475b212b..ca80b1efda 100644 --- a/dbrepo-ui/pages/search.vue +++ b/dbrepo-ui/pages/search.vue @@ -63,9 +63,14 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import AdvancedSearch from '@/components/search/AdvancedSearch.vue' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -75,14 +80,10 @@ export default { return { results: [], type: 'database', - loading: false, - userStore: useUserStore() + loading: false } }, computed: { - roles () { - return this.userStore.getRoles - }, q () { if (!this.$route.query || !this.$route.query.q) { return null diff --git a/dbrepo-ui/pages/semantic/index.vue b/dbrepo-ui/pages/semantic/index.vue deleted file mode 100644 index db555b4c0d..0000000000 --- a/dbrepo-ui/pages/semantic/index.vue +++ /dev/null @@ -1,194 +0,0 @@ -<template> - <div v-if="canListOntologies"> - <v-toolbar flat> - <v-toolbar-title> - {{ $t('pages.semantics.title') }} - </v-toolbar-title> - <v-spacer /> - <v-btn - v-if="canListOntologies" - to="/semantic/ontology" - variant="flat" - :text="ontologies.length + ' ' + $t('toolbars.semantic.ontologies.text')" - color="secondary" /> - <template v-slot:extension> - <v-tabs - v-model="tab" - color="primary"> - <v-tab> - {{ $t('toolbars.semantic.ontologies.concepts') }} - </v-tab> - <v-tab> - {{ $t('toolbars.semantic.ontologies.units') }} - </v-tab> - </v-tabs> - </template> - </v-toolbar> - <v-card flat> - <v-card-text> - <v-data-table - :headers="headers" - :items="rows" - :options.sync="options" - :server-items-length="total" - :footer-props="footerProps" - :items-per-page-options="footerProps.itemsPerPageOptions"> - <template v-slot:item.uri="{ item }"> - <a :href="item.uri" - target="_blank"> - {{ item.uri }} - </a> - </template> - <template v-slot:item.action="{ item }"> - <v-btn - small - :disabled="disabled(item)" - :text="$t('pages.semantics.usages.text')" - @click="view(item)" /> - </template> - </v-data-table> - </v-card-text> - </v-card> - <v-dialog - v-model="viewSemanticEntityDialog" - max-width="640"> - <ViewSemanticEntity - :mode="mode" - :entity="entity" - @close="close" /> - </v-dialog> - <v-breadcrumbs - :items="items" - class="pa-0 mt-2" /> - </div> -</template> - -<script> -import ViewSemanticEntity from '@/components/dialogs/ViewSemanticEntity.vue' -import { useUserStore } from '@/stores/user.js' -import { useCacheStore } from '@/stores/cache.js' - -export default { - components: { - ViewSemanticEntity - }, - data () { - return { - loadingConcepts: false, - loadingUnits: false, - entity: null, - viewSemanticEntityDialog: false, - headers: [ - { text: 'URI', value: 'uri' }, - { text: 'Name', value: 'name' }, - { text: 'Description', value: 'description' }, - { text: 'Usages', value: 'usages' }, - { text: null, value: 'action' } - ], - options: { - page: 1, - itemsPerPage: 10 - }, - total: -1, - footerProps: { - itemsPerPageOptions: [10, 25, 50, 100] - }, - tab: 0, - tabs: [ - 'concepts', 'units' - ], - concepts: [], - units: [], - createOntologyDialog: false, - items: [ - { - title: `${this.$t('navigation.semantics')}`, - to: '/semantic' - } - ], - userStore: useUserStore(), - cacheStore: useCacheStore() - } - }, - computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, - ontologies () { - return this.cacheStore.getOntologies - }, - rows () { - return this.tab === 0 ? this.concepts : this.units - }, - mode () { - return this.tab === 0 ? 'concept' : 'unit' - }, - canListOntologies () { - if (!this.roles) { - return false - } - return this.roles.includes('list-ontologies') - } - }, - mounted () { - this.loadUnits() - this.loadConcepts() - }, - methods: { - loadConcepts () { - this.loadingConcepts = true - const conceptService = useConceptService() - conceptService.findAll() - .then((concepts) => { - concepts = concepts.map((column) => { - column.usages = column.columns.length - return column - }) - this.concepts = concepts - }) - .catch(() => { - this.loadingConcepts = false - }) - .finally(() => { - this.loadingConcepts = false - }) - }, - loadUnits () { - this.loadingUnits = true - const unitService = useUnitService() - unitService.findAll() - .then((units) => { - units = units.map((unit) => { - unit.usages = unit.columns.length - return unit - }) - this.units = units - }) - .catch(() => { - this.loadingUnits = false - }) - .finally(() => { - this.loadingUnits = false - }) - }, - disabled (item) { - return !item.usages || this.usages === 0 - }, - view (entity) { - this.entity = entity - this.viewSemanticEntityDialog = true - }, - close (event) { - if (this.mode === 'unit') { - this.loadUnits() - } else if (this.mode === 'concept') { - this.loadConcepts() - } - this.viewSemanticEntityDialog = false - } - } -} -</script> diff --git a/dbrepo-ui/pages/semantic/ontology/_ontology_id/index.vue b/dbrepo-ui/pages/semantic/ontology/_ontology_id/index.vue deleted file mode 100644 index 14749460c9..0000000000 --- a/dbrepo-ui/pages/semantic/ontology/_ontology_id/index.vue +++ /dev/null @@ -1,273 +0,0 @@ -<template> - <div - v-if="canListOntologies"> - <v-toolbar flat> - <v-toolbar-title> - <v-btn - id="back-btn" - plain - class="mr-2" - to="/semantic/ontology"> - <v-icon left>mdi-arrow-left</v-icon> - </v-btn> - </v-toolbar-title> - <v-toolbar-title> - <v-skeleton-loader - v-if="loading" - type="text" - class="skeleton-small" /> - <span v-if="!loading"> - Ontology - <a - v-if="ontology" - :href="ontology.uri" - target="_blank"> - {{ ontology.uri }} - </a> - </span> - </v-toolbar-title> - <v-spacer /> - <v-toolbar-title> - <v-btn - v-if="canDeleteOntology" - :loading="loadingDelete" - color="error" - @click="deleteOntology"> - Delete Ontology - </v-btn> - </v-toolbar-title> - </v-toolbar> - <v-form ref="form" v-model="valid" autocomplete="off" @submit.prevent="submit"> - <v-card v-if="ontology" variant="flat"> - <v-card-text> - <v-row dense> - <v-col cols="6"> - <v-text-field - id="prefix" - v-model="ontologyChangeDto.prefix" - name="prefix" - label="Prefix *" - hint="Only lowercase alphanumeric letters, max. 8" - autofocus - :rules="[ - v => notEmpty(v) || $t('validation.required'), - v => validPrefix(v) || $t('validation.prefix.pattern'), - v => validPrefixLength(v,1,8) || $t('validation.prefix.length'), - v => validPrefixNotExists(v) || $t('validation.prefix.exists') - ]" - required /> - </v-col> - </v-row> - <v-row dense> - <v-col cols="6"> - <v-text-field - id="uri" - v-model="ontologyChangeDto.uri" - name="uri" - label="URI *" - :rules="[ - v => notEmpty(v) || $t('validation.required'), - v => validUri(v) || $t('validation.uri.pattern'), - v => validUriNotExists(v) || $t('validation.uri.exists') - ]" - required /> - </v-col> - </v-row> - <v-row dense> - <v-col cols="6"> - <v-text-field - id="sparql-endpoint" - v-model="ontologyChangeDto.sparql_endpoint" - name="sparql-endpoint" - label="SPARQL Endpoint" - :rules="[ - v => validUriOptional(v) || $t('validation.uri.pattern') - ]" /> - </v-col> - </v-row> - </v-card-text> - <v-card-actions> - <v-btn - id="createDB" - class="mb-2 ml-2" - :disabled="!valid || loading" - color="primary" - type="submit" - :loading="loading" - @click="save"> - Update - </v-btn> - </v-card-actions> - </v-card> - </v-form> - <v-breadcrumbs :items="items" class="pa-0 mt-2" /> - </div> -</template> - -<script> -import { notEmpty } from '@/utils' -import { useUserStore } from '@/stores/user.js' -import { useCacheStore } from '@/stores/cache.js' - -export default { - data () { - return { - loading: false, - loadingDelete: false, - ontology: null, - ontologyChangeDto: { - uri: null, - prefix: null, - sparql_endpoint: null - }, - valid: false, - createOntologyDialog: false, - items: [ - { text: `${this.$t('layout.semantics')}`, to: '/semantic', activeClass: '' }, - { text: `${this.$t('layout.ontologies')}`, to: '/semantic/ontology', activeClass: '' }, - { text: `${this.$route.params.ontology_id}`, to: `/semantic/ontology/${this.$route.params.ontology_id}`, activeClass: '' } - ], - userStore: useUserStore(), - cacheStore: useCacheStore() - } - }, - computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, - ontologies () { - return this.cacheStore.getOntologies - }, - canListOntologies () { - if (!this.roles) { - return false - } - return this.roles.includes('list-ontologies') - }, - canDeleteOntology () { - if (!this.roles) { - return false - } - return this.roles.includes('delete-ontology') - } - }, - mounted () { - this.loadOntology() - }, - methods: { - loadOntology () { - this.loading = true - const ontologyService = useOntologyService() - ontologyService.findOne(this.$route.params.ontology_id) - .then((ontology) => { - this.ontology = ontology - this.ontologyChangeDto = Object.assign({}, ontology) - }) - .catch(() => { - this.loading = false - }) - .finally(() => { - this.loading = false - }) - }, - deleteOntology () { - this.loadingDelete = true - const ontologyService = useOntologyService() - ontologyService.remove(this.$route.params.ontology_id) - .then(async () => { - // await this.$store.dispatch('reloadOntologies') - await this.$router.push('/semantic/ontology') - }) - .catch(() => { - this.loadingDelete = false - }) - .finally(() => { - this.loadingDelete = false - }) - }, - save () { - this.loading = true - const payload = { - uri: this.ontologyChangeDto.uri, - prefix: this.ontologyChangeDto.prefix, - sparql_endpoint: this.ontologyChangeDto.sparql_endpoint - } - const ontologyService = useOntologyService() - ontologyService.update(this.$route.params.ontology_id, payload) - .then(() => { - this.loadOntology() - // this.$store.dispatch('reloadOntologies') - const toast = useToastInstance() - toast.success('Successfully update ontology!') - }) - .catch(() => { - this.loading = false - }) - .finally(() => { - this.loading = false - }) - }, - validPrefix (str) { - if (!str) { - return false - } - return str.match(/[a-z0-9]+/g) - }, - validPrefixLength (str, min, max) { - if (!str) { - return false - } - return str.length > min && str.length <= max - }, - validPrefixNotExists (str) { - const ontologies = this.ontologies.filter(o => o.prefix === str) - if (ontologies && ontologies.length !== 0) { - /* same prefix is fine for the same ontology, but not for others */ - return ontologies[0].id === this.ontology.id - } - return !this.ontologies.map(o => o.prefix).includes(str) - }, - validUriNotExists (str) { - const ontologies = this.ontologies.filter(o => o.uri === str) - if (ontologies && ontologies.length !== 0) { - /* same uri is fine for the same ontology, but not for others */ - return ontologies[0].id === this.ontology.id - } - return !this.ontologies.map(o => o.uri).includes(str) - }, - validUriOptional (str) { - if (!str) { - return true - } - return this.validUri(str) - }, - validUri (str) { - if (!str) { - return false - } - return str.match(/^https?:\/\//g) - }, - close (event) { - if (event.success) { - // this.$store.dispatch('reloadOntologies') - } - this.createOntologyDialog = false - }, - submit () { - this.$refs.form.validate() - }, - notEmpty - } -} -</script> -<style> -.skeleton-medium > div { - width: 200px !important; -} -.skeleton-xsmall > div { - width: 50px !important; -} -</style> diff --git a/dbrepo-ui/pages/semantic/ontology/index.vue b/dbrepo-ui/pages/semantic/ontology/index.vue deleted file mode 100644 index 36898d9073..0000000000 --- a/dbrepo-ui/pages/semantic/ontology/index.vue +++ /dev/null @@ -1,96 +0,0 @@ -<template> - <div v-if="canListOntologies"> - <v-toolbar flat> - <v-btn - variant="plain" - size="small" - icon="mdi-arrow-left" - to="/semantic" /> - <v-toolbar-title> - {{ ontologies.length + ' ' + $t('toolbars.semantic.ontologies.title') }} - </v-toolbar-title> - <v-spacer /> - <v-btn - v-if="canCreateOntology" - color="secondary" - variant="flat" - name="create-ontology" - prepend-icon="mdi-plus" - :text="$t('toolbars.semantic.ontology.text')" - @click.stop="createOntologyDialog = true" /> - </v-toolbar> - <OntologiesList /> - <v-dialog - v-model="createOntologyDialog" - persistent - max-width="640"> - <CreateOntology ref="ont" @close="close" /> - </v-dialog> - <v-breadcrumbs :items="items" class="pa-0 mt-2" /> - </div> -</template> - -<script> -import OntologiesList from '@/components/OntologiesList.vue' -import CreateOntology from '@/components/dialogs/CreateOntology.vue' -import { useUserStore } from '@/stores/user.js' -import { useCacheStore } from '@/stores/cache.js' - -export default { - components: { - OntologiesList, - CreateOntology - }, - data () { - return { - createOntologyDialog: false, - items: [ - { - title: `${this.$t('navigation.semantics')}`, - to: '/semantic' - }, - { - title: `${this.$t('navigation.ontologies')}`, - to: '/semantic/ontology' - } - ], - userStore: useUserStore(), - cacheStore: useCacheStore() - } - }, - computed: { - token () { - return this.userStore.getToken - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, - ontologies () { - return this.cacheStore.getOntologies - }, - canListOntologies () { - if (!this.roles) { - return false - } - return this.roles.includes('list-ontologies') - }, - canCreateOntology () { - if (!this.roles) { - return false - } - return this.roles.includes('create-ontology') - } - }, - methods: { - close (event) { - if (event.success) { - // this.$store.dispatch('reloadOntologies') - } - this.createOntologyDialog = false - } - } -} -</script> diff --git a/dbrepo-ui/pages/signup.vue b/dbrepo-ui/pages/signup.vue index 54c0060225..19f781572a 100644 --- a/dbrepo-ui/pages/signup.vue +++ b/dbrepo-ui/pages/signup.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="!loggedIn"> <v-toolbar :title="$t('pages.signup.name')" flat /> @@ -91,6 +92,9 @@ </div> </template> +<script setup> +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> export default { data () { diff --git a/dbrepo-ui/pages/user/authentication.vue b/dbrepo-ui/pages/user/authentication.vue index 3a43421a70..03c40e5d82 100644 --- a/dbrepo-ui/pages/user/authentication.vue +++ b/dbrepo-ui/pages/user/authentication.vue @@ -1,5 +1,6 @@ <template> - <div> + <div + v-if="loggedIn"> <UserToolbar /> <v-window v-model="tab"> <v-window-item> @@ -10,8 +11,7 @@ rounded="0"> <v-card-text> <v-form - v-model="valid2" - @submit.prevent="submit"> + v-model="valid2"> <v-row dense> <v-col md="6"> <v-text-field @@ -60,9 +60,15 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import UserToolbar from '@/components/user/UserToolbar.vue' -import { useUserStore } from '@/stores/user.js' export default { components: { @@ -87,14 +93,10 @@ export default { ], email: null, password: null, - password2: null, - userStore: useUserStore() + password2: null } }, computed: { - user () { - return this.userStore.getUser - }, inputVariant () { const runtimeConfig = useRuntimeConfig() return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal @@ -104,15 +106,11 @@ export default { return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal } }, - mounted () { - }, methods: { - submit () { - }, changePassword () { this.loadingUpdate = true const userService = useUserService() - userService.updatePassword(this.user.id, {'password': this.password}) + userService.updatePassword(this.userInfo.uid, {'password': this.password}) .then(() => { const toast = useToastInstance() toast.success(this.$t('success.user.password')) diff --git a/dbrepo-ui/pages/user/developer.vue b/dbrepo-ui/pages/user/developer.vue deleted file mode 100644 index de52a490af..0000000000 --- a/dbrepo-ui/pages/user/developer.vue +++ /dev/null @@ -1,230 +0,0 @@ -<template> - <div> - <UserToolbar /> - <v-window - v-model="tab"> - <v-window-item> - <v-card - v-if="canHandleMessages" - :title="$t('pages.settings.subpages.developer.maintenance.title')" - rounded="0" - variant="flat"> - <v-data-table - :headers="headers" - :items="messages" - :loading="loadingMessages" - :items-per-page="10"> - <template v-slot:item.action="{ item }"> - <v-btn - size="x-small" - variant="flat" - :text="$t('pages.settings.subpages.developer.maintenance.modify.text')" - @click="modifyMessage(item)" /> - </template> - </v-data-table> - <v-card-text> - <v-btn - size="small" - variant="flat" - :text="$t('pages.settings.subpages.developer.maintenance.add.text')" - :disabled="!canCreateMessage" - @click="createMessage" /> - </v-card-text> - </v-card> - <v-divider - v-if="canHandleMessages" /> - <v-card - :title="$t('pages.settings.subpages.developer.token.title')" - :subtitle="$t('pages.settings.subpages.developer.token.subtitle')" - variant="flat" - rounded="0"> - <v-card-text> - <v-row dense> - <v-col xl="4"> - <v-text-field - v-model="accessTokenField" - disabled - :variant="inputVariant" - :label="$t('pages.settings.subpages.developer.token.access.label')" /> - </v-col> - <v-col xl="2"> - <v-text-field - v-model="tokenExpiry" - disabled - :variant="inputVariant" - :label="expiryLabel(token)" /> - </v-col> - </v-row> - <v-row dense> - <v-col xl="4"> - <v-text-field - v-model="refreshTokenField" - disabled - :variant="inputVariant" - :label="$t('pages.settings.subpages.developer.token.refresh.label')" /> - </v-col> - <v-col xl="2"> - <v-text-field - v-model="refreshTokenExpiry" - disabled - :variant="inputVariant" - :label="expiryLabel(refreshToken)" /> - </v-col> - </v-row> - </v-card-text> - </v-card> - </v-window-item> - </v-window> - <v-breadcrumbs :items="items" class="pa-0 mt-2" /> - <v-dialog - v-model="dialog" - persistent - max-width="640"> - <EditMaintenanceMessage - :id="messageId" - @close-dialog="closeDialog" /> - </v-dialog> - </div> -</template> - -<script> -import UserToolbar from '@/components/user/UserToolbar.vue' -import EditMaintenanceMessage from '@/components/dialogs/EditMaintenanceMessage.vue' -import { formatTimestampUTCLabel, isActiveMessage, timestampsToHumanDifference } from '@/utils' -import { useUserStore } from '@/stores/user.js' -import { useCacheStore } from '@/stores/cache.js' - -export default { - components: { - UserToolbar, - EditMaintenanceMessage - }, - data () { - return { - tab: 0, - accessTokenField: null, - refreshTokenField: null, - headers: [ - { title: this.$t('pages.settings.subpages.developer.maintenance.active'), value: 'active' }, - { title: this.$t('pages.settings.subpages.developer.maintenance.type'), value: 'type' }, - { title: this.$t('pages.settings.subpages.developer.maintenance.message'), value: 'message' }, - { title: this.$t('pages.settings.subpages.developer.maintenance.action'), value: 'action' } - ], - items: [ - { - title: this.$t('navigation.user'), - to: '/user' - }, - { - title: this.$t('toolbars.user.developer'), - to: `/user/developer`, - disabled: true - } - ], - messages: [], - loadingMessages: false, - dialog: false, - messageId: null, - userStore: useUserStore(), - cacheStore: useCacheStore() - } - }, - computed: { - token () { - return this.userStore.getToken - }, - tokenExpiry () { - if (!this.token) { - return null - } - const authenticationService = useAuthenticationService() - return formatTimestampUTCLabel(authenticationService.tokenToExpiryDate(this.token)) - }, - refreshToken () { - return this.userStore.getRefreshToken - }, - refreshTokenExpiry () { - if (!this.refreshToken) { - return null - } - const authenticationService = useAuthenticationService() - return formatTimestampUTCLabel(authenticationService.tokenToExpiryDate(this.refreshToken)) - }, - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, - canCreateMessage () { - if (!this.roles) { - return false - } - return this.roles.includes('create-maintenance-message') - }, - canModifyMessage () { - if (!this.roles) { - return false - } - return this.roles.includes('modify-maintenance-message') - }, - canHandleMessages () { - return this.canCreateMessage || this.canModifyMessage - }, - inputVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal - }, - buttonVariant () { - const runtimeConfig = useRuntimeConfig() - return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal - } - }, - mounted () { - this.loadMessages() - if (!this.token || !this.refreshToken) { - return - } - this.accessTokenField = this.token - this.refreshTokenField = this.refreshToken - }, - methods: { - submit () { - }, - modifyMessage (message) { - this.messageId = message.id - this.dialog = true - }, - createMessage () { - this.messageId = null - this.dialog = true - }, - expiryLabel (token) { - const authenticationService = useAuthenticationService() - return this.$t('pages.settings.subpages.developer.token.expiry') + ' ' + timestampsToHumanDifference(Date.now(), authenticationService.tokenToExpiryDate(token)) - }, - loadMessages () { - const messageService = useMessageService() - messageService.findAll() - .then((messages) => { - this.messages = messages.map((message) => { - message.active = isActiveMessage(message) ? '● true' : 'false' - return message - }) - }) - .catch(() => { - this.loadingMessages = false - }) - .finally(() => { - this.loadingMessages = false - }) - }, - closeDialog (event) { - if (event.success) { - this.cacheStore.reloadMessages() - } - this.dialog = false - } - } -} -</script> diff --git a/dbrepo-ui/pages/user/index.vue b/dbrepo-ui/pages/user/index.vue index accae86105..1d76677059 100644 --- a/dbrepo-ui/pages/user/index.vue +++ b/dbrepo-ui/pages/user/index.vue @@ -2,25 +2,13 @@ <div /> </template> +<script setup> +const { loggedIn, user, login, logout } = useOidcAuth() +</script> <script> -import { useUserStore } from '@/stores/user.js' - export default { - data () { - return { - userStore: useUserStore() - } - }, - computed: { - token () { - return this.userStore.getToken - }, - user () { - return this.userStore.getUser - } - }, mounted () { - if (!this.user) { + if (!this.loggedIn) { return } this.$router.push('/user/info') diff --git a/dbrepo-ui/pages/user/info.vue b/dbrepo-ui/pages/user/info.vue index 9b94dde4da..58e265b59f 100644 --- a/dbrepo-ui/pages/user/info.vue +++ b/dbrepo-ui/pages/user/info.vue @@ -1,7 +1,8 @@ <template> <div> <UserToolbar /> - <v-window v-model="tab"> + <v-window + v-model="tab"> <v-window-item> <v-form v-model="valid1" @submit.prevent="submit"> <v-card @@ -122,9 +123,16 @@ </div> </template> +<script setup> +import { ref } from 'vue' + +const { loggedIn, user, login, logout } = useOidcAuth() +const userInfo = ref(loggedIn ? user.value?.userInfo : null) +const roles = ref(loggedIn ? user.value?.claims?.realm_access?.roles : []) +</script> <script> import UserToolbar from '@/components/user/UserToolbar.vue' -import { useUserStore } from '@/stores/user.js' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -169,18 +177,12 @@ export default { disabled: true } ], - userStore: useUserStore() + cacheStore: useCacheStore() } }, computed: { - user () { - return this.userStore.getUser - }, - roles () { - return this.userStore.getRoles - }, locale () { - return this.userStore.getLocale + return this.cacheStore.getLocale }, canModifyTheme () { return this.roles.includes('modify-user-theme') @@ -214,14 +216,13 @@ export default { language: this.model.language, } const userService = useUserService() - userService.update(this.user.id, payload) + userService.update(this.userInfo.id, payload) .then((user) => { console.info('Updated user information') const toast = useToastInstance() toast.success(this.$t('success.user.info')) - this.userStore.setUser(user) /* language */ - this.userStore.setLocale(this.model.language) + this.cacheStore.setLocale(this.model.language) this.$i18n.locale = this.locale /* theme */ switch (this.model.theme) { @@ -251,14 +252,14 @@ export default { return } this.model = { - id: this.user.id, - username: this.user.username, - firstname: this.user.given_name, - lastname: this.user.family_name, - orcid: this.user.attributes.orcid, - affiliation: this.user.attributes.affiliation, - theme: this.user.attributes.theme, - language: this.user.attributes.language + id: this.userInfo.id, + username: this.userInfo.username, + firstname: this.userInfo.given_name, + lastname: this.userInfo.family_name, + orcid: this.userInfo.attributes.orcid, + affiliation: this.userInfo.attributes.affiliation, + theme: this.userInfo.attributes.theme, + language: this.userInfo.attributes.language } }, retrieve () { diff --git a/dbrepo-ui/stores/cache.js b/dbrepo-ui/stores/cache.js index 41059ba727..4582dce199 100644 --- a/dbrepo-ui/stores/cache.js +++ b/dbrepo-ui/stores/cache.js @@ -7,7 +7,9 @@ export const useCacheStore = defineStore('cache', { database: null, table: null, view: null, + access: null, subset: null, + locale: null, ontologies: [], messages: [], uploadProgress: null @@ -17,7 +19,9 @@ export const useCacheStore = defineStore('cache', { getDatabase: (state) => state.database, getTable: (state) => state.table, getView: (state) => state.view, + getAccess: (state) => state.access, getSubset: (state) => state.subset, + getLocale: (state) => state.locale, getOntologies: (state) => state.ontologies, getMessages: (state) => state.messages, getUploadProgress: (state) => state.uploadProgress, @@ -32,9 +36,15 @@ export const useCacheStore = defineStore('cache', { setView(view) { this.view = view }, + setAccess(access) { + this.access = access + }, setSubset(subset) { this.subset = subset }, + setLocale(locale) { + this.locale = locale + }, setOntologies(ontologies) { this.ontologies = ontologies }, @@ -117,6 +127,16 @@ export const useCacheStore = defineStore('cache', { tableService.findOne(databaseId, tableId) .then(table => this.table = table) }, + setRouteAccess(databaseId, userId) { + if (!databaseId || !userId) { + this.access = null + console.error('Cannot set route access: missing database id', databaseId, 'or user id', userId) + return + } + const accessService = useAccessService() + accessService.findOne(databaseId, userId) + .then(access => this.access = access) + }, setRouteView(databaseId, viewId) { if (!databaseId || !viewId) { this.view = null diff --git a/dbrepo-ui/stores/user.js b/dbrepo-ui/stores/user.js deleted file mode 100644 index 522ce02a06..0000000000 --- a/dbrepo-ui/stores/user.js +++ /dev/null @@ -1,60 +0,0 @@ -import {defineStore} from 'pinia' - -export const useUserStore = defineStore('user', { - persist: true, - state: () => { - return { - /** @type String */ - token: null, - /** @type String */ - refreshToken: null, - roles: [], - user: null, - access: null, - locale: null - } - }, - getters: { - getToken: (state) => state.token, - getRefreshToken: (state) => state.refreshToken, - getRoles: (state) => state.roles, - getUser: (state) => state.user, - getAccess: (state) => state.access, - getLocale: (state) => state.locale - }, - actions: { - setToken(token) { - this.token = token - }, - setRefreshToken(refreshToken) { - this.refreshToken = refreshToken - }, - setRoles(roles) { - this.roles = roles - }, - setUser(user) { - this.user = user - }, - setAccess(access) { - this.access = access - }, - setLocale (locale) { - this.locale = locale - }, - logout() { - this.token = null - this.refreshToken = null - this.roles = [] - this.user = null - this.access = null - }, - setRouteAccess(databaseId) { - if (!databaseId || !this.user || !this.user.id) { - return - } - const accessService = useAccessService() - accessService.findOne(databaseId, this.user.id) - .then(access => this.access = access) - } - } -}) diff --git a/docker-compose.yml b/docker-compose.yml index ad1dacb6b7..efcc9a76cc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -329,8 +329,13 @@ services: network: host environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" - NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://localhost}" + NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://gateway-service}" NUXT_PUBLIC_UPLOAD_CLIENT: "${BASE_URL:-http://localhost}/api/upload/files" + NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL: "${BASE_URL:-http://localhost:8080}/realms/dbrepo" + NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID: "${AUTH_SERVICE_CLIENT:-dbrepo-client}" + NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET: "${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}" + NUXT_OIDC_PROVIDERS_KEYCLOAK_REDIRECT_URI: "${BASE_URL:-http://localhost}/auth/keycloak/callback" + NUXT_OIDC_PROVIDERS_KEYCLOAK_LOGOUT_REDIRECT_URI: "${BASE_URL:-http://localhost}" depends_on: dbrepo-search-service: condition: service_healthy @@ -341,6 +346,8 @@ services: interval: 10s timeout: 5s retries: 12 + extra_hosts: + - "localhost:host-gateway" logging: driver: json-file -- GitLab