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);
           });
       });