# HG changeset patch # User Thomas Junk # Date 1530717670 -7200 # Node ID 0612095050284c3f4160734a47f3235bb254100f # Parent 3d9341f6da4e26e6c62e2bc09587025a10fa2ebe feat: Login and logout with session restoration implemented Login information stored in local storage for restoration after browser restart. If a non expired session is found, it is restored before entering the main area. Username and logout are located in the lower sidebar. diff -r 3d9341f6da4e -r 061209505028 client/src/components/Sidebar.vue --- a/client/src/components/Sidebar.vue Tue Jul 03 17:46:06 2018 +0200 +++ b/client/src/components/Sidebar.vue Wed Jul 04 17:21:10 2018 +0200 @@ -6,9 +6,14 @@ Link Disabled -
+
+
{{ userinfo }}
+
+ +
+
@@ -26,6 +31,12 @@ }; } }, + methods: { + logoff() { + this.$store.commit("user/clear_auth"); + this.$router.push("/login"); + } + }, data() { return { collapsed: false @@ -52,4 +63,19 @@ .sidebarextended { width: $sidebar-full-width; } + +.user { + position: absolute; + left: 0; + bottom: $large-offset; + width: 90px; +} + +.userinfo { + font-weight: bold; +} + +.logout { + margin-left: $small-offset; +} diff -r 3d9341f6da4e -r 061209505028 client/src/router.js --- a/client/src/router.js Tue Jul 03 17:46:06 2018 +0200 +++ b/client/src/router.js Wed Jul 04 17:21:10 2018 +0200 @@ -19,6 +19,23 @@ component: Main, meta: { requiresAuth: true + }, + beforeEnter: (to, from, next) => { + const expiresFromPastSession = localStorage.getItem("expires"); + const pastSessionStillActive = () => { + if (!expiresFromPastSession) return false; + const now = new Date(); + const sessionEnd = new Date(expiresFromPastSession * 1000); + const stillActive = now < sessionEnd; + return stillActive; + }; + if (pastSessionStillActive()) { + store.commit("user/set_user", localStorage.getItem("user")); + store.commit("user/set_expires", expiresFromPastSession); + store.commit("user/set_roles", localStorage.getItem("roles")); + store.commit("user/authenticate", true); + } + next(); } }, { @@ -30,10 +47,11 @@ router.beforeEach((to, from, next) => { const requiresAuth = to.matched.some(record => record.meta.requiresAuth); - const currentUser = store.getters["user/authenticated"]; - if (requiresAuth && !currentUser) { + const currentUser = localStorage.getItem("token") != null; + const userIsAuthenticated = requiresAuth && !currentUser; + if (userIsAuthenticated) { next("/login"); - } else if (requiresAuth && currentUser) { + } else if (!userIsAuthenticated) { next(); } else { next(); diff -r 3d9341f6da4e -r 061209505028 client/src/stores/user.js --- a/client/src/stores/user.js Tue Jul 03 17:46:06 2018 +0200 +++ b/client/src/stores/user.js Wed Jul 04 17:21:10 2018 +0200 @@ -3,10 +3,10 @@ const User = { namespaced: true, state: { - user: "", authenticated: false, expires: null, - roles: [] + roles: [], + user: "" }, getters: { authenticated: state => { @@ -14,20 +14,44 @@ }, userinfo: state => { return state.user; + }, + roles: state => { + return state.roles; + }, + expires: state => { + return state.expires; } }, mutations: { auth_success: (state, data) => { - state.authenticated = true; const { token, user, expires, roles } = data; - state.user = user; + localStorage.setItem("expires", expires); + localStorage.setItem("roles", roles); + localStorage.setItem("token", token); + localStorage.setItem("user", user); state.expires = expires; state.roles = roles; - sessionStorage.setItem("token", token); + state.user = user; + state.authenticated = true; + }, + clear_auth: state => { + state.authenticated = false; + state.expires = null; + state.roles = []; + state.user = ""; + localStorage.clear(); }, - auth_failure: state => { - state.authenticated = false; - sessionStorage.removeItem("token"); + set_user: (state, name) => { + state.user = name; + }, + set_roles: (state, roles) => { + state.roles = roles; + }, + set_expires: (state, expires) => { + state.expires = expires; + }, + authenticate: state => { + state.authenticated = true; } }, actions: { @@ -39,7 +63,7 @@ resolve(response); }) .catch(error => { - commit("auth_failure"); + commit("clear_auth"); reject(error); }); });