release v2.0.0 #4
|
@ -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()) {
|
||||
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()
|
||||
}
|
||||
} 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