Cleanup + Login with plugin backend
This commit is contained in:
		
							parent
							
								
									bea9f9f5dc
								
							
						
					
					
						commit
						82d4b52e24
					
				| 
						 | 
				
			
			@ -1,20 +1,25 @@
 | 
			
		|||
import { boot } from 'quasar/wrappers';
 | 
			
		||||
import { StateInterface } from '../store';
 | 
			
		||||
 | 
			
		||||
export default boot(({ Vue, router, store }) => {
 | 
			
		||||
    router.beforeEach((to, from, next) => {
 | 
			
		||||
        if (to.matched.some(record => record.meta.requiresAuth)) {
 | 
			
		||||
            // this route requires auth, check if logged in
 | 
			
		||||
            // if not, redirect to login page.
 | 
			
		||||
            if (!store.getters.isLoggedIn()) {
 | 
			
		||||
                next({
 | 
			
		||||
                    path: '/login',
 | 
			
		||||
                    query: { redirect: to.fullPath }
 | 
			
		||||
                })
 | 
			
		||||
            } else {
 | 
			
		||||
                next()
 | 
			
		||||
            }
 | 
			
		||||
        let user = (<StateInterface>store.state).user;
 | 
			
		||||
 | 
			
		||||
        if (to.matched.some(record => {
 | 
			
		||||
            // permissions is set AND has NO matching permission
 | 
			
		||||
            return record.meta.permissions !== undefined &&
 | 
			
		||||
                !(record.meta.permissions.filter(
 | 
			
		||||
                    (value: string) =>
 | 
			
		||||
                        user.permissions.includes(value)
 | 
			
		||||
                ).length > 0);
 | 
			
		||||
        })
 | 
			
		||||
        ) {
 | 
			
		||||
            next({
 | 
			
		||||
                path: '/login',
 | 
			
		||||
                query: { redirect: to.fullPath }
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            next() // make sure to always call next()!
 | 
			
		||||
            next();
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,9 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <q-page padding class="fit row  justify-center items-center content-center">
 | 
			
		||||
    <q-card
 | 
			
		||||
      class="col-xs-11 col-sm-8 col-md-6 col-lg-4 justify-center items-center content-center"
 | 
			
		||||
    >
 | 
			
		||||
  <q-page
 | 
			
		||||
    padding
 | 
			
		||||
    class="fit row  justify-center items-center content-center"
 | 
			
		||||
  >
 | 
			
		||||
    <q-card class="col-xs-11 col-sm-8 col-md-6 col-lg-4 justify-center items-center content-center">
 | 
			
		||||
      <q-toolbar class="bg-primary text-white">
 | 
			
		||||
        <q-toolbar-title>
 | 
			
		||||
          Login
 | 
			
		||||
| 
						 | 
				
			
			@ -10,10 +11,14 @@
 | 
			
		|||
      </q-toolbar>
 | 
			
		||||
 | 
			
		||||
      <q-card-section>
 | 
			
		||||
        <q-form ref="LoginForm" @submit="doLogin" class="q-gutter-md">
 | 
			
		||||
        <q-form
 | 
			
		||||
          ref="LoginForm"
 | 
			
		||||
          @submit="doLogin"
 | 
			
		||||
          class="q-gutter-md"
 | 
			
		||||
        >
 | 
			
		||||
          <q-input
 | 
			
		||||
            filled
 | 
			
		||||
            v-model="username"
 | 
			
		||||
            v-model="userid"
 | 
			
		||||
            label="Benutzername oder E-Mail"
 | 
			
		||||
            :rules="rules"
 | 
			
		||||
          />
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +30,11 @@
 | 
			
		|||
            :rules="rules"
 | 
			
		||||
          />
 | 
			
		||||
          <div class="row justify-end">
 | 
			
		||||
            <q-btn label="Login" type="submit" color="primary" />
 | 
			
		||||
            <q-btn
 | 
			
		||||
              label="Login"
 | 
			
		||||
              type="submit"
 | 
			
		||||
              color="primary"
 | 
			
		||||
            />
 | 
			
		||||
          </div>
 | 
			
		||||
        </q-form>
 | 
			
		||||
      </q-card-section>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,18 +48,22 @@ import { defineComponent, ref } from '@vue/composition-api';
 | 
			
		|||
export default defineComponent({
 | 
			
		||||
  // name: 'PageName'
 | 
			
		||||
  setup(_, ctx) {
 | 
			
		||||
    const username = ref('');
 | 
			
		||||
    const userid = ref('');
 | 
			
		||||
    const password = ref('');
 | 
			
		||||
    const rules = [
 | 
			
		||||
      (val: string) => (val && val.length > 0) || 'Feld darf nicht leer sein!'
 | 
			
		||||
      (val: string) => (val && val.length > 0) || 'Feld darf nicht leer sein!',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    function doLogin() {
 | 
			
		||||
      console.log(username.value, password.value);
 | 
			
		||||
      void ctx.root.$router.push({ name: 'main' });
 | 
			
		||||
      ctx.root.$store.dispatch('user/login', {
 | 
			
		||||
        userid: userid.value,
 | 
			
		||||
        password: password.value,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      void ctx.root.$router.push({ name: 'user' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return { username, password, doLogin, rules };
 | 
			
		||||
  }
 | 
			
		||||
    return { userid, password, doLogin, rules };
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ const routes: RouteConfig[] = [
 | 
			
		|||
      {
 | 
			
		||||
        path: 'plugin1',
 | 
			
		||||
        name: 'plugin1',
 | 
			
		||||
        meta: { permissions: ['user'] },
 | 
			
		||||
        components: {
 | 
			
		||||
          default: () => import('../pages/Plugin.vue'),
 | 
			
		||||
          'plugin-nav': () => import('../components/navigation/PluginLinks.vue')
 | 
			
		||||
| 
						 | 
				
			
			@ -18,11 +19,13 @@ const routes: RouteConfig[] = [
 | 
			
		|||
          {
 | 
			
		||||
            path: 'plugin1_1',
 | 
			
		||||
            name: 'plugin1_1',
 | 
			
		||||
            meta: { permissions: ['user'] },
 | 
			
		||||
            component: () => import('../pages/NewPlugin.vue')
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            path: 'plugin1_2',
 | 
			
		||||
            name: 'plugin1_2',
 | 
			
		||||
            meta: { permissions: ['user'] },
 | 
			
		||||
            component: () => import('../pages/OldPlugin.vue')
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,22 @@
 | 
			
		|||
    <q-page
 | 
			
		||||
      padding
 | 
			
		||||
      class="fit row justify-center content-center items-center"
 | 
			
		||||
      v-if="$route.name == mainLink.link"
 | 
			
		||||
      v-if="true"
 | 
			
		||||
    >
 | 
			
		||||
      <q-card class="col-4" height="">
 | 
			
		||||
      <q-card
 | 
			
		||||
        class="col-4"
 | 
			
		||||
        height=""
 | 
			
		||||
      >
 | 
			
		||||
        <q-card-section>
 | 
			
		||||
          {{ mainLink.title }}
 | 
			
		||||
          Name: {{ userState.user.firstname }} {{ userState.user.lastname }}<br />
 | 
			
		||||
          E-Mail: {{ userState.user.mail }}<br />
 | 
			
		||||
          Roles: <ul
 | 
			
		||||
            v-for="role in userState.user.roles"
 | 
			
		||||
            v-bind:key="role"
 | 
			
		||||
          >
 | 
			
		||||
            <li>{{ role }}</li>
 | 
			
		||||
          </ul><br />
 | 
			
		||||
          Token expires: {{ userState.token.expires }}
 | 
			
		||||
        </q-card-section>
 | 
			
		||||
      </q-card>
 | 
			
		||||
    </q-page>
 | 
			
		||||
| 
						 | 
				
			
			@ -16,13 +27,17 @@
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent } from '@vue/composition-api';
 | 
			
		||||
import { mainLink } from '../plugin';
 | 
			
		||||
import { defineComponent, computed } from '@vue/composition-api';
 | 
			
		||||
import { UserStateInterface } from '../../../store/module-user/state';
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  // name: 'PageName'
 | 
			
		||||
  setup(_, ctx) {
 | 
			
		||||
    const a = ctx.root.$flaschengeistPluginsMainLinks;
 | 
			
		||||
    return { a, mainLink };
 | 
			
		||||
  }
 | 
			
		||||
  setup(_, { root }) {
 | 
			
		||||
    const userState = computed(
 | 
			
		||||
      () => <UserStateInterface>root.$store.state.user
 | 
			
		||||
    );
 | 
			
		||||
    const a = root.$flaschengeistPluginsMainLinks;
 | 
			
		||||
    return { a, userState };
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,12 +20,13 @@ const routes: RouteConfig[] = [
 | 
			
		|||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/main',
 | 
			
		||||
    name: 'main',
 | 
			
		||||
    redirect: 'user',
 | 
			
		||||
    component: () => import('layouts/MainLayout.vue'),
 | 
			
		||||
    children: [
 | 
			
		||||
      {
 | 
			
		||||
        name: 'about',
 | 
			
		||||
        path: 'about',
 | 
			
		||||
        meta: { 'permissions': ['user'] },
 | 
			
		||||
        component: () => import('pages/about/About.vue')
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
import { store } from 'quasar/wrappers';
 | 
			
		||||
import Vuex from 'vuex';
 | 
			
		||||
 | 
			
		||||
// import example from './module-example';
 | 
			
		||||
// import { ExampleStateInterface } from './module-example/state';
 | 
			
		||||
import user from './module-user';
 | 
			
		||||
import { UserStateInterface } from './module-user/state';
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * If not building with SSR mode, you can
 | 
			
		||||
| 
						 | 
				
			
			@ -11,17 +11,15 @@ import Vuex from 'vuex';
 | 
			
		|||
 | 
			
		||||
export interface StateInterface {
 | 
			
		||||
  // Define your own store structure, using submodules if needed
 | 
			
		||||
  // example: ExampleStateInterface;
 | 
			
		||||
  // Declared as unknown to avoid linting issue. Best to strongly type as per the line above.
 | 
			
		||||
  example: unknown;
 | 
			
		||||
  user: UserStateInterface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default store(function({ Vue }) {
 | 
			
		||||
export default store(function ({ Vue }) {
 | 
			
		||||
  Vue.use(Vuex);
 | 
			
		||||
 | 
			
		||||
  const Store = new Vuex.Store<StateInterface>({
 | 
			
		||||
    modules: {
 | 
			
		||||
      // example
 | 
			
		||||
      user
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // enable strict mode (adds overhead!)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
import { ActionTree } from 'vuex';
 | 
			
		||||
import { StateInterface } from '../index';
 | 
			
		||||
import { ExampleStateInterface } from './state';
 | 
			
		||||
 | 
			
		||||
const actions: ActionTree<ExampleStateInterface, StateInterface> = {
 | 
			
		||||
  someAction (/* context */) {
 | 
			
		||||
    // your code
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default actions;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
import { MutationTree } from 'vuex';
 | 
			
		||||
import { ExampleStateInterface } from './state';
 | 
			
		||||
 | 
			
		||||
const mutation: MutationTree<ExampleStateInterface> = {
 | 
			
		||||
  someMutation (/* state: ExampleStateInterface */) {
 | 
			
		||||
    // your code
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default mutation;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
export interface ExampleStateInterface {
 | 
			
		||||
  prop: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const state: ExampleStateInterface = {
 | 
			
		||||
  prop: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default state;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import axios from 'axios';
 | 
			
		||||
import { ActionTree } from 'vuex';
 | 
			
		||||
import { StateInterface } from '../index';
 | 
			
		||||
import { UserStateInterface } from './state';
 | 
			
		||||
 | 
			
		||||
const actions: ActionTree<UserStateInterface, StateInterface> = {
 | 
			
		||||
  login ({ commit }, payload): any {
 | 
			
		||||
    axios.post("/auth", {
 | 
			
		||||
      userid: payload.userid,
 | 
			
		||||
      password: payload.password
 | 
			
		||||
    }).then(function (response) {
 | 
			
		||||
      let token = (<UserStateInterface>response.data).token;
 | 
			
		||||
      console.log(token);
 | 
			
		||||
      if (token)
 | 
			
		||||
        token.expires = new Date(token.expires);
 | 
			
		||||
      commit('setUser', (<UserStateInterface>response.data).user);
 | 
			
		||||
      commit('setToken', token);
 | 
			
		||||
      commit('setPermissions', (<UserStateInterface>response.data).permissions);
 | 
			
		||||
    }).catch(function (error) {
 | 
			
		||||
      console.error(error);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default actions;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
import { GetterTree } from 'vuex';
 | 
			
		||||
import { StateInterface } from '../index';
 | 
			
		||||
import { ExampleStateInterface } from './state';
 | 
			
		||||
import { UserStateInterface } from './state';
 | 
			
		||||
 | 
			
		||||
const getters: GetterTree<ExampleStateInterface, StateInterface> = {
 | 
			
		||||
const getters: GetterTree<UserStateInterface, StateInterface> = {
 | 
			
		||||
  someAction (/* context */) {
 | 
			
		||||
    console.log("GOOOOOOOOOOOOOOOOOOO");
 | 
			
		||||
    // your code
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
import { Module } from 'vuex';
 | 
			
		||||
import { StateInterface } from '../index';
 | 
			
		||||
import state, { ExampleStateInterface } from './state';
 | 
			
		||||
import state, { UserStateInterface } from './state';
 | 
			
		||||
import actions from './actions';
 | 
			
		||||
import getters from './getters';
 | 
			
		||||
import mutations from './mutations';
 | 
			
		||||
 | 
			
		||||
const exampleModule: Module<ExampleStateInterface, StateInterface> = {
 | 
			
		||||
const exampleModule: Module<UserStateInterface, StateInterface> = {
 | 
			
		||||
  namespaced: true,
 | 
			
		||||
  actions,
 | 
			
		||||
  getters,
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
import { MutationTree } from 'vuex';
 | 
			
		||||
import { TokenInterface, UserInterface, UserStateInterface } from './state';
 | 
			
		||||
 | 
			
		||||
const mutation: MutationTree<UserStateInterface> = {
 | 
			
		||||
  setToken (state: UserStateInterface, token: TokenInterface) {
 | 
			
		||||
    state.token = token
 | 
			
		||||
  },
 | 
			
		||||
  setUser (state: UserStateInterface, user: UserInterface) {
 | 
			
		||||
    state.user = user
 | 
			
		||||
  },
 | 
			
		||||
  setPermissions (state: UserStateInterface, permissions: Array<string>) {
 | 
			
		||||
    state.permissions = permissions
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default mutation;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
export interface TokenInterface {
 | 
			
		||||
  token: string,
 | 
			
		||||
  expires: Date,
 | 
			
		||||
  lifetime: number,
 | 
			
		||||
  browser: string,
 | 
			
		||||
  platform: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UserInterface {
 | 
			
		||||
  display_name: string | null,
 | 
			
		||||
  firstname: string,
 | 
			
		||||
  lastname: string,
 | 
			
		||||
  mail: string | null,
 | 
			
		||||
  roles: Array<string>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UserStateInterface {
 | 
			
		||||
  token: TokenInterface | null,
 | 
			
		||||
  user: UserInterface | null,
 | 
			
		||||
  permissions: Array<string>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const state: UserStateInterface = {
 | 
			
		||||
  token: null,
 | 
			
		||||
  user: null,
 | 
			
		||||
  permissions: []
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default state;
 | 
			
		||||
		Loading…
	
		Reference in New Issue