| @@ -26,6 +26,7 @@ | |||||
| "@types/chai": "^4.2.15", | "@types/chai": "^4.2.15", | ||||
| "@types/luxon": "^3.1.0", | "@types/luxon": "^3.1.0", | ||||
| "@types/mocha": "^8.2.1", | "@types/mocha": "^8.2.1", | ||||
| "@types/node": "^18.11.19", | |||||
| "@typescript-eslint/eslint-plugin": "^5.4.0", | "@typescript-eslint/eslint-plugin": "^5.4.0", | ||||
| "@typescript-eslint/parser": "^5.4.0", | "@typescript-eslint/parser": "^5.4.0", | ||||
| "@vue/cli-plugin-babel": "~5.0.0", | "@vue/cli-plugin-babel": "~5.0.0", | ||||
| @@ -2485,11 +2486,10 @@ | |||||
| "license": "MIT" | "license": "MIT" | ||||
| }, | }, | ||||
| "node_modules/@types/node": { | "node_modules/@types/node": { | ||||
| "version": "18.11.9", | |||||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", | |||||
| "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", | |||||
| "dev": true, | |||||
| "license": "MIT" | |||||
| "version": "18.11.19", | |||||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", | |||||
| "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", | |||||
| "dev": true | |||||
| }, | }, | ||||
| "node_modules/@types/normalize-package-data": { | "node_modules/@types/normalize-package-data": { | ||||
| "version": "2.4.1", | "version": "2.4.1", | ||||
| @@ -16514,9 +16514,9 @@ | |||||
| "dev": true | "dev": true | ||||
| }, | }, | ||||
| "@types/node": { | "@types/node": { | ||||
| "version": "18.11.9", | |||||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", | |||||
| "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", | |||||
| "version": "18.11.19", | |||||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", | |||||
| "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", | |||||
| "dev": true | "dev": true | ||||
| }, | }, | ||||
| "@types/normalize-package-data": { | "@types/normalize-package-data": { | ||||
| @@ -27,6 +27,7 @@ | |||||
| "@types/chai": "^4.2.15", | "@types/chai": "^4.2.15", | ||||
| "@types/luxon": "^3.1.0", | "@types/luxon": "^3.1.0", | ||||
| "@types/mocha": "^8.2.1", | "@types/mocha": "^8.2.1", | ||||
| "@types/node": "^18.11.19", | |||||
| "@typescript-eslint/eslint-plugin": "^5.4.0", | "@typescript-eslint/eslint-plugin": "^5.4.0", | ||||
| "@typescript-eslint/parser": "^5.4.0", | "@typescript-eslint/parser": "^5.4.0", | ||||
| "@vue/cli-plugin-babel": "~5.0.0", | "@vue/cli-plugin-babel": "~5.0.0", | ||||
| @@ -22,9 +22,9 @@ | |||||
| <RouterLink to="/admin/dashboard" class="button is-primary"> | <RouterLink to="/admin/dashboard" class="button is-primary"> | ||||
| Admin | Admin | ||||
| </RouterLink> | </RouterLink> | ||||
| <RouterLink to="/logout" class="button is-white"> | |||||
| <button class="button is-white" @click="logout"> | |||||
| Log out | Log out | ||||
| </RouterLink> | |||||
| </button> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -63,6 +63,7 @@ import { | |||||
| } from 'vue'; | } from 'vue'; | ||||
| import jwtDecode from 'jwt-decode'; | import jwtDecode from 'jwt-decode'; | ||||
| import { Claims } from '@/api/types'; | import { Claims } from '@/api/types'; | ||||
| import { removeToken } from '@/lib/auth'; | |||||
| const userData = ref({ | const userData = ref({ | ||||
| username: '', | username: '', | ||||
| @@ -113,6 +114,10 @@ const logoElements: LogoElement[] = [ | |||||
| letter: 't', | letter: 't', | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| const logout = () => { | |||||
| removeToken(); | |||||
| }; | |||||
| </script> | </script> | ||||
| <style lang="stylus"> | <style lang="stylus"> | ||||
| @@ -3,7 +3,7 @@ import jwtDecode from 'jwt-decode'; | |||||
| import { Claims } from '@/api/types'; | import { Claims } from '@/api/types'; | ||||
| import * as luxon from 'luxon'; | import * as luxon from 'luxon'; | ||||
| const removeToken = () => { | |||||
| export const removeToken = () => { | |||||
| sessionStorage.removeItem('jwt'); | sessionStorage.removeItem('jwt'); | ||||
| store.commit('clearToken'); | store.commit('clearToken'); | ||||
| }; | }; | ||||
| @@ -13,9 +13,9 @@ import AdminView from '@/views/AdminView.vue'; | |||||
| import ModifyQueueView from '@/views/ModifyQueueView.vue'; | import ModifyQueueView from '@/views/ModifyQueueView.vue'; | ||||
| import AdminDashboardView from '@/views/AdminDashboardView.vue'; | import AdminDashboardView from '@/views/AdminDashboardView.vue'; | ||||
| import ModifyUserView from '@/views/ModifyUserView.vue'; | import ModifyUserView from '@/views/ModifyUserView.vue'; | ||||
| import LogoutView from '@/views/LogoutView.vue'; | |||||
| import ChangePasswordView from '@/views/ChangePasswordView.vue'; | import ChangePasswordView from '@/views/ChangePasswordView.vue'; | ||||
| import store from '@/store'; | import store from '@/store'; | ||||
| import ForbiddenView from '@/views/ForbiddenView.vue'; | |||||
| const routes: Array<RouteRecordRaw> = [ | const routes: Array<RouteRecordRaw> = [ | ||||
| { | { | ||||
| @@ -42,11 +42,6 @@ const routes: Array<RouteRecordRaw> = [ | |||||
| component: ChangePasswordView, | component: ChangePasswordView, | ||||
| meta: { title: 'Change Password' }, | meta: { title: 'Change Password' }, | ||||
| }, | }, | ||||
| { | |||||
| path: '/logout', | |||||
| name: 'logout', | |||||
| component: LogoutView, | |||||
| }, | |||||
| { | { | ||||
| path: '/admin', | path: '/admin', | ||||
| name: 'admin', | name: 'admin', | ||||
| @@ -122,6 +117,11 @@ const routes: Array<RouteRecordRaw> = [ | |||||
| title: 'Administrator', | title: 'Administrator', | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | |||||
| path: '/forbidden', | |||||
| name: 'forbidden', | |||||
| component: ForbiddenView, | |||||
| }, | |||||
| { | { | ||||
| path: '/:pathMatch(.*)*', | path: '/:pathMatch(.*)*', | ||||
| name: 'wildcard', | name: 'wildcard', | ||||
| @@ -0,0 +1,13 @@ | |||||
| <template> | |||||
| <section class="section is-medium"> | |||||
| <span class="is-size-3">403</span> | |||||
| <p>Forbidden</p> | |||||
| </section> | |||||
| </template> | |||||
| <script setup lang="ts"> | |||||
| </script> | |||||
| <style scoped> | |||||
| </style> | |||||
| @@ -1,20 +0,0 @@ | |||||
| <template> | |||||
| <div> | |||||
| Logging out... | |||||
| </div> | |||||
| </template> | |||||
| <script setup lang="ts"> | |||||
| import { useRouter } from 'vue-router'; | |||||
| import store from '@/store'; | |||||
| store.commit('clearToken'); | |||||
| window.sessionStorage.removeItem('jwt'); | |||||
| const router = useRouter(); | |||||
| router.push('/'); | |||||
| </script> | |||||
| <style scoped lang="stylus"> | |||||
| </style> | |||||
| @@ -0,0 +1,13 @@ | |||||
| <template> | |||||
| </template> | |||||
| <script setup lang="ts"> | |||||
| export default { | |||||
| name: "NotFoundView" | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| </style> | |||||
| @@ -1270,10 +1270,10 @@ | |||||
| "resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz" | "resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz" | ||||
| "version" "8.2.3" | "version" "8.2.3" | ||||
| "@types/node@*": | |||||
| "integrity" "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" | |||||
| "resolved" "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz" | |||||
| "version" "18.11.9" | |||||
| "@types/node@*", "@types/node@^18.11.19": | |||||
| "integrity" "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==" | |||||
| "resolved" "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz" | |||||
| "version" "18.11.19" | |||||
| "@types/normalize-package-data@^2.4.0": | "@types/normalize-package-data@^2.4.0": | ||||
| "integrity" "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" | "integrity" "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" | ||||