diff --git a/frontend/src/components/Login.vue b/frontend/src/components/Login.vue index 1344def47c2964d613a4014abdba0d1ff387146e..021cb6600a9e2ad80eb017d6b98d4b7828f8bbd0 100644 --- a/frontend/src/components/Login.vue +++ b/frontend/src/components/Login.vue @@ -51,13 +51,15 @@ ...mapActions([ 'getJWTToken', 'getExamModule', - 'getUserRole' + 'getUserRole', + 'getJWTTimeDelta' ]), submit () { this.getJWTToken(this.credentials).then(() => { this.$router.push('/student/') this.getExamModule() this.getUserRole() + this.getJWTTimeDelta() }).catch(() => { this.error = this.$store.state.error }) diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 32587176fc476c53522d50b320d5e90e919d5442..6569eb171384c6ab28ab899414c1ddfb858c6799 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -1,5 +1,6 @@ import Vue from 'vue' import Router from 'vue-router' +import store from '../store/store' import Login from '@/components/Login' import StudentPage from '@/components/student/StudentPage' import StudentLayout from '@/components/student/StudentLayout' @@ -11,7 +12,7 @@ import AnnotatedSubmission from '@/components/submission_notes/AnnotatedSubmissi Vue.use(Router) -export default new Router({ +const router = new Router({ routes: [ { path: '/', @@ -55,3 +56,19 @@ export default new Router({ } ] }) + +router.beforeEach((to, from, next) => { + if (from.path === '/') { + next() + } else { + const now = new Date() + if (now - store.state.logInTime > store.state.jwtTimeDelta * 1000) { + store.dispatch('logout').then(() => next('/')) + } else { + store.dispatch('refreshJWTToken') + next() + } + } +}) + +export default router diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index 9d5acae05dfddfde951986a929c079f9e46be3c2..214908640b8247ea79825a1656806e5b5318d392 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -16,13 +16,15 @@ const store = new Vuex.Store({ state: { token: '', loggedIn: false, + logInTime: {}, username: '', + jwtTimeDelta: 0, userRole: '', error: '', examInstance: '' }, getters: { - gradySpeak: state => { + gradySpeak: () => { return gradySays[Math.floor(Math.random() * gradySays.length)] } }, @@ -32,8 +34,12 @@ const store = new Vuex.Store({ }, 'SET_JWT_TOKEN': function (state, token) { state.token = token + state.logInTime = new Date() ax.defaults.headers.common['Authorization'] = 'JWT ' + token }, + 'SET_JWT_TIME_DELTA': function (state, timeDelta) { + state.jwtTimeDelta = timeDelta + }, 'LOGIN': function (state, username) { state.loggedIn = true state.username = username @@ -66,6 +72,16 @@ const store = new Vuex.Store({ } } }, + refreshJWTToken (context) { + ax.post('/api-token-refresh/', {token: context.state.token}).then(response => { + context.commit('SET_JWT_TOKEN', response.data.token) + }) + }, + getJWTTimeDelta (context) { + ax.get('api/jwt-time-delta/').then(response => { + context.commit('SET_JWT_TIME_DELTA', response.data.timeDelta) + }) + }, getUserRole (context) { ax.get('api/user-role/').then(response => context.commit('SET_USER_ROLE', response.data.role)) },