From e080a1a7593e83a49d623ffdd452fd0e1c617889 Mon Sep 17 00:00:00 2001 From: Derick Montague Date: Wed, 4 Dec 2019 16:30:08 -0600 Subject: Add login and logout functionality - Add AuthenticationStore - Add ability to login and logout - Add route navigation guard - Add login styles - Add temporary authentication for api call - Add Login directory - Add index.js In order to login a .env.development.local file that contains BASE_URL="https:// or " Signed-off-by: Derick Montague Change-Id: I88b93e287e66f4bae82a1ec2934cdef12d78264e --- src/App.vue | 31 +----- src/assets/images/openbmc-logo.svg | 1 + src/assets/styles/_obmc-custom.scss | 13 --- src/components/AppHeader/AppHeader.vue | 9 +- src/layouts/AppLayout.vue | 38 +++++++ src/main.js | 7 ++ src/router/index.js | 47 ++++++--- src/store/api.js | 15 +-- src/store/index.js | 4 +- .../modules/Authentication/AuthenticanStore.js | 56 +++++++++++ src/views/Login/Login.vue | 111 +++++++++++++++++++++ src/views/Login/index.js | 2 + 12 files changed, 265 insertions(+), 69 deletions(-) create mode 100644 src/assets/images/openbmc-logo.svg create mode 100644 src/layouts/AppLayout.vue create mode 100644 src/store/modules/Authentication/AuthenticanStore.js create mode 100644 src/views/Login/Login.vue create mode 100644 src/views/Login/index.js diff --git a/src/App.vue b/src/App.vue index d0e1a0ae..56674955 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,18 +1,6 @@ @@ -21,22 +9,7 @@ - - diff --git a/src/assets/images/openbmc-logo.svg b/src/assets/images/openbmc-logo.svg new file mode 100644 index 00000000..d0fa158c --- /dev/null +++ b/src/assets/images/openbmc-logo.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/src/assets/styles/_obmc-custom.scss b/src/assets/styles/_obmc-custom.scss index 45dec1f8..7deb6cba 100644 --- a/src/assets/styles/_obmc-custom.scss +++ b/src/assets/styles/_obmc-custom.scss @@ -1,16 +1,3 @@ -// Major breakpoints using 16px base em * 16 -// xs: 0, sm: 768px, md: 1024px, lg: 1376px, xl: 1600px -// Using em's will allow for changes if base font size is updated -// to accommodate for responsive text. Using 0 as xs due to -// Bootstrap requirements. -$grid-breakpoints: ( - xs: 0, - sm: 48em, - md: 64em, - lg: 86em, - xl: 100em -); - // Required @import "~bootstrap/scss/functions"; @import "./functions"; diff --git a/src/components/AppHeader/AppHeader.vue b/src/components/AppHeader/AppHeader.vue index 9177403c..8dacd03d 100644 --- a/src/components/AppHeader/AppHeader.vue +++ b/src/components/AppHeader/AppHeader.vue @@ -7,9 +7,9 @@ BMC System Management - + - User Avatar + Logout @@ -77,6 +77,11 @@ export default { methods: { getHostInfo() { this.$store.dispatch("global/getHostName"); + }, + logout() { + this.$store.dispatch("authentication/logout").then(() => { + this.$router.push("/login"); + }); } } }; diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue new file mode 100644 index 00000000..dcfb52e7 --- /dev/null +++ b/src/layouts/AppLayout.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/main.js b/src/main.js index e18ce89e..6f4acc6d 100644 --- a/src/main.js +++ b/src/main.js @@ -7,7 +7,10 @@ import { BadgePlugin, ButtonPlugin, CollapsePlugin, + FormPlugin, FormCheckboxPlugin, + FormGroupPlugin, + FormInputPlugin, LayoutPlugin, LinkPlugin, ListGroupPlugin, @@ -22,7 +25,11 @@ Vue.filter("date", dateFilter); Vue.use(BadgePlugin); Vue.use(ButtonPlugin); Vue.use(CollapsePlugin); +Vue.use(FormPlugin); Vue.use(FormCheckboxPlugin); +Vue.use(FormGroupPlugin); +Vue.use(FormInputPlugin); +Vue.use(LayoutPlugin); Vue.use(LayoutPlugin); Vue.use(LinkPlugin); Vue.use(ListGroupPlugin); diff --git a/src/router/index.js b/src/router/index.js index 11d1a475..698aa700 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,28 +1,35 @@ import Vue from "vue"; import VueRouter from "vue-router"; +import store from "../store/index"; +import AppLayout from "../layouts/AppLayout.vue"; Vue.use(VueRouter); const routes = [ { path: "/", - name: "overview", - component: () => import("@/views/Overview") + name: "", + meta: { + requiresAuth: true + }, + component: AppLayout, + children: [ + { + path: "", + component: () => import("@/views/Overview") + }, + { + path: "/access-control/local-user-management", + name: "local-users", + component: () => import("@/views/AccessControl/LocalUserManagement") + } + ] }, { - path: "/access-control/local-user-management", - name: "local-users", - component: () => import("@/views/AccessControl/LocalUserManagement") + path: "/login", + name: "login", + component: () => import("@/views/Login") } - // { - // path: "/about", - // name: "about", - // // route level code-splitting - // // this generates a separate chunk (about.[hash].js) for this route - // // which is lazy-loaded when the route is visited. - // component: () => - // import(/* webpackChunkName: "about" */ "../views/About.vue") - // } ]; const router = new VueRouter({ @@ -32,4 +39,16 @@ const router = new VueRouter({ linkExactActiveClass: "nav__link--current" }); +router.beforeEach((to, from, next) => { + if (to.matched.some(record => record.meta.requiresAuth)) { + if (store.getters["authentication/isLoggedIn"]) { + next(); + return; + } + next("/login"); + } else { + next(); + } +}); + export default router; diff --git a/src/store/api.js b/src/store/api.js index d40ad0ad..39a6355c 100644 --- a/src/store/api.js +++ b/src/store/api.js @@ -2,15 +2,9 @@ import Axios from "axios"; const api = Axios.create(); -// TODO: this is a temporary workaround until -// authentication with login is working -const username = process.env.VUE_APP_USERNAME; -const password = process.env.VUE_APP_PASSWORD; -if (username && password) { - api.defaults.auth = {}; - api.defaults.auth.username = username; - api.defaults.auth.password = password; -} +// TODO: Permanent authentication solution +// Using defaults to set auth for sending +// auth object in header export default { get(path) { @@ -30,5 +24,6 @@ export default { }, all(promises) { return Axios.all(promises); - } + }, + defaults: api.defaults }; diff --git a/src/store/index.js b/src/store/index.js index af06a471..b4be6ccd 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,8 +1,9 @@ import Vue from "vue"; import Vuex from "vuex"; -import LocalUserManagementStore from "./modules/AccessControl/LocalUserMangementStore"; import GlobalStore from "./modules/GlobalStore"; +import AuthenticationStore from "./modules/Authentication/AuthenticanStore"; +import LocalUserManagementStore from "./modules/AccessControl/LocalUserMangementStore"; Vue.use(Vuex); @@ -12,6 +13,7 @@ export default new Vuex.Store({ actions: {}, modules: { global: GlobalStore, + authentication: AuthenticationStore, localUsers: LocalUserManagementStore } }); diff --git a/src/store/modules/Authentication/AuthenticanStore.js b/src/store/modules/Authentication/AuthenticanStore.js new file mode 100644 index 00000000..828c3cc8 --- /dev/null +++ b/src/store/modules/Authentication/AuthenticanStore.js @@ -0,0 +1,56 @@ +import api from "../../api"; + +const AuthenticationStore = { + namespaced: true, + state: { + auth: {}, + status: "", + token: sessionStorage.getItem("token") || "" + }, + getters: { + authStatus: state => state.status, + isLoggedIn: state => !!state.token + }, + mutations: { + authRequest(state) { + state.status = "loading"; + }, + authSuccess(state, token, auth) { + state.status = "authenicated"; + state.auth = auth; + state.token = token; + }, + authError(state) { + state.status = "error"; + }, + logout(state) { + state.status = ""; + state.token = ""; + } + }, + actions: { + login({ commit }, auth) { + commit("authRequest"); + return api + .post("/login", auth) + .then(response => { + const token = response.data.token; + sessionStorage.setItem("token", token); + api.defaults.auth = auth; // TODO Permanent Solution + commit("authSuccess", token, auth); + }) + .catch(error => { + commit("authError"); + sessionStorage.removeItem("token"); + throw new Error(error); + }); + }, + logout({ commit }) { + commit("logout"); + sessionStorage.removeItem("token"); + api.defaults.auth = {}; // Permanent solution + } + } +}; + +export default AuthenticationStore; diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue new file mode 100644 index 00000000..f122d289 --- /dev/null +++ b/src/views/Login/Login.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/src/views/Login/index.js b/src/views/Login/index.js new file mode 100644 index 00000000..7fc2b5ca --- /dev/null +++ b/src/views/Login/index.js @@ -0,0 +1,2 @@ +import Login from "./Login.vue"; +export default Login; -- cgit v1.2.3