@@ -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==" | ||||