From 325502a7b1b2f03e70c07211fabb5882fc8b1e1a Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Wed, 15 Jul 2020 16:29:43 -0400 Subject: [PATCH] Rework logout flow + add no app access state --- src/api.ts | 4 ++-- src/app.vue | 18 ++++++++++++++++-- src/lang/en-US/index.json | 3 +++ src/router.ts | 7 +++++-- src/routes/logout/index.ts | 4 ---- src/routes/logout/logout.test.ts | 23 ----------------------- src/routes/logout/logout.vue | 27 --------------------------- src/routes/logout/readme.md | 7 ------- src/stores/user/types.ts | 1 + 9 files changed, 27 insertions(+), 67 deletions(-) delete mode 100644 src/routes/logout/index.ts delete mode 100644 src/routes/logout/logout.test.ts delete mode 100644 src/routes/logout/logout.vue delete mode 100644 src/routes/logout/readme.md diff --git a/src/api.ts b/src/api.ts index 7cf652f640..c0fc74be69 100644 --- a/src/api.ts +++ b/src/api.ts @@ -53,11 +53,11 @@ export const onError = async (error: RequestError) => { /* istanbul ignore next */ const code = error.response?.data?.error?.code; - if (status === 401 && code === 'INVALID_CREDENTIALS') { + if (status === 401 && code === 'INVALID_CREDENTIALS' && error.response?.config?.url !== '/auth/refresh') { try { await refresh(); - /** @todo retry failed request */ + /** @todo retry failed request after successful refresh */ } catch { logout({ reason: LogoutReason.ERROR_SESSION_EXPIRED }); } diff --git a/src/app.vue b/src/app.vue index d8fa00cbed..73062b99ae 100644 --- a/src/app.vue +++ b/src/app.vue @@ -5,7 +5,16 @@ - + + + + + {{ $t('no_app_access_copy') }} + + + @@ -69,7 +78,12 @@ export default defineComponent({ } ); - return { hydrating, brandStyle }; + const appAccess = computed(() => { + if (!userStore.state.currentUser) return true; + return userStore.state.currentUser?.role?.app_access; + }); + + return { hydrating, brandStyle, appAccess }; }, }); diff --git a/src/lang/en-US/index.json b/src/lang/en-US/index.json index 330e756bad..101ab943b0 100644 --- a/src/lang/en-US/index.json +++ b/src/lang/en-US/index.json @@ -348,6 +348,9 @@ "unexpected_error_copy": "Something went wrong.. Please try again later.", "copy_details": "Copy Details", + "no_app_access": "No App Access", + "no_app_access_copy": "This user isn't allowed to use the admin app.", + "password_reset_sent": "We've sent you a secure link to reset your password", "password_reset_successful": "Password successfully reset", "create_project": "Create Project", diff --git a/src/router.ts b/src/router.ts index b69ca156fc..e713247525 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,7 +1,6 @@ import VueRouter, { NavigationGuard, RouteConfig, Route } from 'vue-router'; import LoginRoute from '@/routes/login'; import InstallRoute from '@/routes/install'; -import LogoutRoute from '@/routes/logout'; import ResetPasswordRoute from '@/routes/reset-password'; import { refresh } from '@/auth'; import { hydrate } from '@/hydrate'; @@ -9,6 +8,7 @@ import useAppStore from '@/stores/app'; import useUserStore from '@/stores/user'; import PrivateNotFoundRoute from '@/routes/private-not-found'; import useSettingsStore from '@/stores/settings'; +import { logout } from '@/auth'; import getRootPath from '@/utils/get-root-path'; @@ -50,7 +50,10 @@ export const defaultRoutes: RouteConfig[] = [ { name: 'logout', path: '/logout', - component: LogoutRoute, + async beforeEnter(to, from, next) { + await logout({ navigate: false }); + next('/login'); + }, meta: { public: true, }, diff --git a/src/routes/logout/index.ts b/src/routes/logout/index.ts deleted file mode 100644 index 7623c9914c..0000000000 --- a/src/routes/logout/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import LogoutRoute from './logout.vue'; - -export { LogoutRoute }; -export default LogoutRoute; diff --git a/src/routes/logout/logout.test.ts b/src/routes/logout/logout.test.ts deleted file mode 100644 index 861d53e555..0000000000 --- a/src/routes/logout/logout.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import LogoutRoute from './logout.vue'; -import { logout } from '@/auth'; -import VCircularProgress from '@/components/v-progress/circular/'; -import VueCompositionAPI from '@vue/composition-api'; - -jest.mock('@/auth'); - -const localVue = createLocalVue(); -localVue.component('v-progress-circular', VCircularProgress); -localVue.use(VueCompositionAPI); - -describe('Routes / Logout', () => { - it('Calls logout on mount', async () => { - const component = shallowMount(LogoutRoute, { - localVue, - }); - - await (component.vm as any).$nextTick(); - - expect(logout).toHaveBeenCalled(); - }); -}); diff --git a/src/routes/logout/logout.vue b/src/routes/logout/logout.vue deleted file mode 100644 index 03d36b5ee3..0000000000 --- a/src/routes/logout/logout.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - diff --git a/src/routes/logout/readme.md b/src/routes/logout/readme.md deleted file mode 100644 index 469de464b6..0000000000 --- a/src/routes/logout/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# Logout View - -Renders an empty page with a spinner, and logs the user out. Once the user is logged out, it will redirect to login. - -## Why a separate route? - -If we were to logout on any other route that uses the private view, it would mean that there will be a bunch of errors in the devtools, as a lot of things will be trying to read from the store, which will be cleared. This extra route makes sure we can safely empty the store without any component still reading from it. diff --git a/src/stores/user/types.ts b/src/stores/user/types.ts index d94222dc75..7c98b206fb 100644 --- a/src/stores/user/types.ts +++ b/src/stores/user/types.ts @@ -20,6 +20,7 @@ export type Role = { enforce_2fa: null | boolean; external_id: null | string; ip_whitelist: string[]; + app_access: boolean; }; export type Avatar = {