Mercurial > gemma
changeset 160:061209505028
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.
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 04 Jul 2018 17:21:10 +0200 |
parents | 3d9341f6da4e |
children | b7ac2e4f9c5c |
files | client/src/components/Sidebar.vue client/src/router.js client/src/stores/user.js |
diffstat | 3 files changed, 81 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ <a class="nav-link" href="#">Link</a> <a class="nav-link disabled" href="#">Disabled</a> </nav> - <div class="userinfo"> + <div class="user d-flex justify-content-center"> + <div class="userinfo"> {{ userinfo }} </div> + <div class="logout"> + <span @click="logoff"><i class="fa fa-power-off"></i></span> + </div> + </div> </div> </template> @@ -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; +} </style>
--- 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();
--- 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); }); });