From fd335d8eefc0b458a711a17d229025fdf0d5ee3c Mon Sep 17 00:00:00 2001
From: "robinwilliam.hundt" <robinwilliam.hundt@stud.uni-goettingen.de>
Date: Wed, 21 Feb 2018 17:31:54 +0100
Subject: [PATCH] Fix of auto logout bug / refactored to own component

---
 frontend/src/App.vue                         | 84 +-----------------
 frontend/src/api.js                          |  2 +-
 frontend/src/components/AutoLogout.vue       | 92 ++++++++++++++++++++
 frontend/src/store/modules/authentication.js | 10 +--
 4 files changed, 102 insertions(+), 86 deletions(-)
 create mode 100644 frontend/src/components/AutoLogout.vue

diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index a981b102..5e793836 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -3,93 +3,17 @@
     <v-app>
       <notifications/>
       <router-view/>
-      <v-dialog
-        persistent
-        width="fit-content"
-        v-model="logoutDialog"
-      >
-        <v-card>
-          <v-card-title class="headline">
-            You'll be logged out!
-          </v-card-title>
-          <v-card-text>
-            Due to inactivity you'll be logged out in a couple of moments.<br/>
-            Any unsaved work will be lost.
-            Click Continue to stay logged in.
-          </v-card-text>
-          <v-card-actions>
-            <v-btn flat color="grey lighten-0"
-                   @click="logout"
-            >Logout now</v-btn>
-            <v-spacer/>
-            <v-btn flat color="blue darken-2"
-                   @click="continueWork"
-            >Continue</v-btn>
-          </v-card-actions>
-        </v-card>
-      </v-dialog>
+      <auto-logout/>
     </v-app>
   </div>
 </template>
 
 <script>
-  import {mapState} from 'vuex'
+  import AutoLogout from '@/components/AutoLogout'
 
   export default {
-    name: 'app',
-    data () {
-      return {
-        timer: 0,
-        logoutDialog: false
-      }
-    },
-    computed: {
-      ...mapState([
-        'lastAppInteraction'
-      ]),
-      ...mapState({
-        lastTokenRefreshTry: state => state.authentication.lastTokenRefreshTry,
-        refreshingToken: state => state.authentication.refreshingToken,
-        jwtTimeDelta: state => state.authentication.jwtTimeDelta
-      })
-    },
-    methods: {
-      logout () {
-        this.logoutDialog = false
-        this.$store.dispatch('logout')
-      },
-      continueWork () {
-        this.$store.dispatch('refreshJWT')
-        this.logoutDialog = false
-      }
-    },
-    watch: {
-      lastAppInteraction: function (val) {
-        const timeSinceLastRefresh = Date.now() - this.lastTokenRefreshTry
-        const timeDelta = this.jwtTimeDelta
-        // refresh jwt if it's older than 20% of his maximum age
-        if (this.$route.name !== 'login' && timeSinceLastRefresh > timeDelta * 0.2 &&
-          !this.refreshingToken) {
-          this.$store.dispatch('refreshJWT')
-        }
-      }
-    },
-    mounted () {
-      const oneAndHalfMinute = 90 * 1e3
-      this.timer = setInterval(() => {
-        if (this.$route.name !== 'login' && this.$store.getters.isLoggedIn) {
-          if (Date.now() > this.lastTokenRefreshTry + this.jwtTimeDelta) {
-            this.logoutDialog = false
-            this.$store.dispatch('logout', "You've been logged out due to inactivity.")
-          } else if (Date.now() + oneAndHalfMinute > this.lastTokenRefreshTry + this.jwtTimeDelta) {
-            this.logoutDialog = true
-          }
-        }
-      }, 5 * 1e3)
-    },
-    beforeDestroy () {
-      clearInterval(this.timer)
-    }
+    components: {AutoLogout},
+    name: 'app'
   }
 </script>
 
diff --git a/frontend/src/api.js b/frontend/src/api.js
index 26799ada..ead1f457 100644
--- a/frontend/src/api.js
+++ b/frontend/src/api.js
@@ -26,7 +26,7 @@ export async function fetchJWT (credentials) {
 export async function refreshJWT (token) {
   const newToken = (await ax.post('/api/refresh-token/', {token})).data.token
   ax.defaults.headers['Authorization'] = `JWT ${newToken}`
-  return token
+  return newToken
 }
 
 export async function fetchJWTTimeDelta () {
diff --git a/frontend/src/components/AutoLogout.vue b/frontend/src/components/AutoLogout.vue
new file mode 100644
index 00000000..e035b42b
--- /dev/null
+++ b/frontend/src/components/AutoLogout.vue
@@ -0,0 +1,92 @@
+<template>
+  <v-dialog
+    persistent
+    width="fit-content"
+    v-model="logoutDialog"
+  >
+    <v-card>
+      <v-card-title class="headline">
+        You'll be logged out!
+      </v-card-title>
+      <v-card-text>
+        Due to inactivity you'll be logged out in a couple of moments.<br/>
+        Any unsaved work will be lost.
+        Click Continue to stay logged in.
+      </v-card-text>
+      <v-card-actions>
+        <v-btn flat color="grey lighten-0"
+               @click="logout"
+        >Logout now</v-btn>
+        <v-spacer/>
+        <v-btn flat color="blue darken-2"
+               @click="continueWork"
+        >Continue</v-btn>
+      </v-card-actions>
+    </v-card>
+  </v-dialog>
+</template>
+
+<script>
+  import {mapState} from 'vuex'
+
+  export default {
+    name: 'auto-logout',
+    data () {
+      return {
+        timer: 0,
+        logoutDialog: false
+      }
+    },
+    computed: {
+      ...mapState([
+        'lastAppInteraction'
+      ]),
+      ...mapState({
+        lastTokenRefreshTry: state => state.authentication.lastTokenRefreshTry,
+        refreshingToken: state => state.authentication.refreshingToken,
+        jwtTimeDelta: state => state.authentication.jwtTimeDelta
+      })
+    },
+    methods: {
+      logout () {
+        this.logoutDialog = false
+        this.$store.dispatch('logout')
+      },
+      continueWork () {
+        this.$store.dispatch('refreshJWT')
+        this.logoutDialog = false
+      }
+    },
+    watch: {
+      lastAppInteraction: function (val) {
+        const timeSinceLastRefresh = Date.now() - this.lastTokenRefreshTry
+        const timeDelta = this.jwtTimeDelta
+        // refresh jwt if it's older than 20% of his maximum age
+        if (this.$route.name !== 'login' && timeSinceLastRefresh > timeDelta * 0.2 &&
+          !this.refreshingToken) {
+          this.$store.dispatch('refreshJWT')
+        }
+      }
+    },
+    mounted () {
+      this.timer = setInterval(() => {
+        const timeToLogOutDialog = Math.min(600 * 1e3,
+          this.jwtTimeDelta ? this.jwtTimeDelta * 0.3 : Infinity)
+        if (this.$route.name !== 'login' && this.$store.getters.isLoggedIn) {
+          if (Date.now() > this.lastTokenRefreshTry + this.jwtTimeDelta) {
+            this.logoutDialog = false
+            this.$store.dispatch('logout', "You've been logged out due to inactivity.")
+          } else if (Date.now() + timeToLogOutDialog > this.lastTokenRefreshTry + this.jwtTimeDelta) {
+            this.logoutDialog = true
+          }
+        }
+      }, 5 * 1e3)
+    },
+    beforeDestroy () {
+      clearInterval(this.timer)
+    }
+  }
+</script>
+
+<style>
+</style>
diff --git a/frontend/src/store/modules/authentication.js b/frontend/src/store/modules/authentication.js
index 4720ff5b..64afb260 100644
--- a/frontend/src/store/modules/authentication.js
+++ b/frontend/src/store/modules/authentication.js
@@ -1,4 +1,4 @@
-import {fetchJWT, fetchJWTTimeDelta, fetchUserRole, refreshJWT} from '@/api'
+import * as api from '@/api'
 import gradySays from '../grady_speak'
 
 function initialState () {
@@ -75,7 +75,7 @@ const authentication = {
   actions: {
     async getJWT (context, credentials) {
       try {
-        const token = await fetchJWT(credentials)
+        const token = await api.fetchJWT(credentials)
         context.commit(authMut.SET_USERNAME, credentials.username)
         context.commit(authMut.SET_JWT_TOKEN, token)
       } catch (error) {
@@ -96,7 +96,7 @@ const authentication = {
     async refreshJWT ({state, commit}) {
       commit(authMut.SET_REFRESHING_TOKEN, true)
       try {
-        const token = await refreshJWT(state.token)
+        const token = await api.refreshJWT(state.token)
         commit(authMut.SET_JWT_TOKEN, token)
       } finally {
         commit(authMut.SET_REFRESHING_TOKEN, false)
@@ -105,7 +105,7 @@ const authentication = {
     },
     async getUserRole ({commit}) {
       try {
-        const userRole = await fetchUserRole()
+        const userRole = await api.fetchUserRole()
         commit(authMut.SET_USER_ROLE, userRole)
       } catch (err) {
         commit(authMut.SET_MESSAGE, "You've been logged out.")
@@ -113,7 +113,7 @@ const authentication = {
     },
     async getJWTTimeDelta ({commit}) {
       try {
-        const delta = await fetchJWTTimeDelta()
+        const delta = await api.fetchJWTTimeDelta()
         // multiply by 1000 to convert to ms
         commit(authMut.SET_JWT_TIME_DELTA, delta * 1000)
       } catch (err) {
-- 
GitLab