release v2.0.0 #4
|
@ -1,7 +1,8 @@
|
|||
import axios, { AxiosInstance } from 'axios';
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { Token, UserStateInterface } from 'src/plugins/user/store/user';
|
||||
import { UserStateInterface } from 'src/plugins/user/store/user';
|
||||
import config from '../config';
|
||||
import { Store } from 'vuex';
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
|
@ -9,18 +10,15 @@ declare module 'vue/types/vue' {
|
|||
}
|
||||
}
|
||||
|
||||
export default boot(({ Vue, store }) => {
|
||||
export default boot<Store<any>>(({ Vue, store }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
Vue.prototype.$axios = axios;
|
||||
axios.defaults.baseURL = config.baseURL;
|
||||
|
||||
axios.interceptors.request.use(config => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
|
||||
const token: Token = store.getters['user/token'];
|
||||
if (token) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
config.headers['Token'] = token.token;
|
||||
//config.headers['Authorization'] = 'Token ' + token.token;
|
||||
const session: Session = store.getters['user/session'];
|
||||
if (session) {
|
||||
config.headers['Authorization'] = 'Token ' + session.token;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
|
|
@ -1,41 +1,37 @@
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import { UserStateInterface } from 'src/plugins/user/store/user';
|
||||
import { RouteRecord } from 'vue-router';
|
||||
import { Store } from 'vuex'
|
||||
import { StateInterface } from 'src/store';
|
||||
|
||||
export default boot(({ router, store }) => {
|
||||
export default boot<Store<StateInterface>>(({ router, store }) => {
|
||||
router.beforeEach((to, from, next) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
store.dispatch('user/loadFromLocalStorage');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
//const user: UserStateInterface = (<UserStateInterface>store.state).user;
|
||||
//const user: UserStateInterface = store.getters['user/user'];
|
||||
const permissions: [] = store.getters['user/permissions'];
|
||||
console.log('login_boot', permissions);
|
||||
if (
|
||||
to.matched.some((record: RouteRecord) => {
|
||||
// permissions is set AND has NO matching permission
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
record.meta.permissions !== undefined &&
|
||||
!(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
(
|
||||
record.meta.permissions.filter((value: string) =>
|
||||
permissions.includes(value)
|
||||
).length > 0
|
||||
store.dispatch('user/loadFromLocalStorage').then(() => {
|
||||
const permissions = store.getters['user/permissions'];
|
||||
console.log('login_boot', permissions);
|
||||
if (
|
||||
to.matched.some((record: RouteRecord) => {
|
||||
// permissions is set AND has NO matching permission
|
||||
return (
|
||||
permissions in record.meta &&
|
||||
!(
|
||||
(
|
||||
record.meta.permissions.filter((value: string) =>
|
||||
permissions.includes(value)
|
||||
).length > 0
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
})
|
||||
) {
|
||||
next({
|
||||
path: '/login',
|
||||
query: { redirect: to.fullPath }
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
);
|
||||
})
|
||||
) {
|
||||
next({
|
||||
path: '/login',
|
||||
query: { redirect: to.fullPath }
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}).catch(error => {
|
||||
console.exception(error);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import { RouteConfig } from 'vue-router';
|
||||
import { Module, Store } from 'vuex';
|
||||
import { StateInterface } from 'src/store';
|
||||
|
||||
const config = {
|
||||
// Do not change required Modules !!
|
||||
|
@ -19,7 +20,7 @@ interface ShortCutLink {
|
|||
interface Plugin {
|
||||
name: string;
|
||||
routes: RouteConfig[];
|
||||
store?: Map<string, Module<any, any>>;
|
||||
store?: Map<string, Module<any, StateInterface>>;
|
||||
mainLink: PluginMainLink;
|
||||
requiredModules: string[];
|
||||
shortcuts: ShortCutLink[];
|
||||
|
@ -61,7 +62,7 @@ export {
|
|||
};
|
||||
|
||||
// combine routes from source to target
|
||||
function combineRoutes(
|
||||
function combineRoutes (
|
||||
target: RouteConfig[],
|
||||
source: RouteConfig[]
|
||||
): RouteConfig[] {
|
||||
|
@ -74,15 +75,15 @@ function combineRoutes(
|
|||
);
|
||||
if (targetRouteConfig) {
|
||||
// if exists first layer in target exist iterate through 2nd layer e.g. /main/user, /main/about
|
||||
sourceRouteConfig.children?.forEach(
|
||||
sourceRouteConfig.children ?.forEach(
|
||||
(sourcePluginChildRouteConfig: RouteConfig) => {
|
||||
const targetPluginRouteConfig:
|
||||
| RouteConfig
|
||||
| undefined = targetRouteConfig.children?.find(
|
||||
(routeConfig: RouteConfig) => {
|
||||
return sourcePluginChildRouteConfig.path == routeConfig.path;
|
||||
}
|
||||
);
|
||||
| undefined = targetRouteConfig.children ?.find(
|
||||
(routeConfig: RouteConfig) => {
|
||||
return sourcePluginChildRouteConfig.path == routeConfig.path;
|
||||
}
|
||||
);
|
||||
if (targetPluginRouteConfig) {
|
||||
// if 2nd layer in target exist check if target has children path.
|
||||
if (targetPluginRouteConfig.children) {
|
||||
|
@ -113,7 +114,7 @@ function combineRoutes(
|
|||
}
|
||||
|
||||
// combine Links of Plugins from source to target
|
||||
function combineMainLinks(
|
||||
function combineMainLinks (
|
||||
target: PluginMainLink[],
|
||||
source: PluginMainLink
|
||||
): PluginMainLink[] {
|
||||
|
@ -134,7 +135,7 @@ function combineMainLinks(
|
|||
}
|
||||
|
||||
// loade plugins
|
||||
function loadPlugin(
|
||||
function loadPlugin (
|
||||
loadedPlugins: LoadedPlugins,
|
||||
modules: string[],
|
||||
plugins: Plugin[],
|
||||
|
@ -180,7 +181,7 @@ function loadPlugin(
|
|||
|
||||
// "async" is optional;
|
||||
// more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file
|
||||
export default boot(({ Vue, router, store }) => {
|
||||
export default boot<Store<StateInterface>>(({ Vue, router, store }) => {
|
||||
const plugins: Plugin[] = [];
|
||||
let loadedPlugins: LoadedPlugins = {
|
||||
routes: [],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const config = {
|
||||
baseURL: "http://flaschengeist.local:5000"
|
||||
baseURL: 'http://flaschengeist.local:5000'
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -0,0 +1,31 @@
|
|||
interface Session {
|
||||
user: User;
|
||||
expires: Date;
|
||||
token: string;
|
||||
lifetime: number;
|
||||
browser: string;
|
||||
platform: string;
|
||||
}
|
||||
interface User {
|
||||
roles: Array<Role>;
|
||||
userid: string;
|
||||
display_name: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
mail: string;
|
||||
}
|
||||
interface Permission {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
interface Role {
|
||||
permissions: Array<Permission>;
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
interface UserAttribute {
|
||||
id: number;
|
||||
user: number;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
|
@ -7,9 +7,7 @@
|
|||
<div class="text-h5 row">
|
||||
Deine Sessions:
|
||||
</div>
|
||||
<div
|
||||
class="fit row justify-center content-center items-center q-gutter-sm"
|
||||
>
|
||||
<div class="fit row justify-center content-center items-center q-gutter-sm">
|
||||
<circular-progress v-if="sessionsLoading" />
|
||||
<q-card
|
||||
class="col-12"
|
||||
|
@ -27,12 +25,18 @@
|
|||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
Browser:
|
||||
<q-icon :name="getBrowserIcon(session.browser)" size="24px" />
|
||||
<q-icon
|
||||
:name="getBrowserIcon(session.browser)"
|
||||
size="24px"
|
||||
/>
|
||||
{{ session.browser }}
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
Plattform:
|
||||
<q-icon :name="getPlatformIcon(session.platform)" size="24px" />
|
||||
<q-icon
|
||||
:name="getPlatformIcon(session.platform)"
|
||||
size="24px"
|
||||
/>
|
||||
{{ session.platform }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -58,7 +62,10 @@
|
|||
</q-card>
|
||||
</div>
|
||||
<div class="row">
|
||||
<q-btn label="show sessions" @click="showRootGetters" />
|
||||
<q-btn
|
||||
label="show sessions"
|
||||
@click="showRootGetters"
|
||||
/>
|
||||
</div>
|
||||
</q-page>
|
||||
</div>
|
||||
|
@ -103,7 +110,7 @@ export default defineComponent({
|
|||
root.$store.dispatch('sessions/deleteSession', token);
|
||||
}
|
||||
function isThisSession(token: string) {
|
||||
return root.$store.getters['user/token'].token == token;
|
||||
return root.$store.getters['user/session'].token == token;
|
||||
}
|
||||
|
||||
const sessionsLoading = computed(() => {
|
||||
|
|
|
@ -5,16 +5,22 @@
|
|||
class="fit row justify-center content-center items-center"
|
||||
v-if="checkMain"
|
||||
>
|
||||
<q-card class="col-4" height="">
|
||||
<q-card
|
||||
class="col-4"
|
||||
height=""
|
||||
>
|
||||
<q-card-section>
|
||||
Name: {{ userState.firstname }} {{ userState.lastname }}<br />
|
||||
E-Mail: {{ userState.mail }}<br />
|
||||
Name: {{ userSession.user.firstname }} {{ userSession.user.lastname }}<br />
|
||||
E-Mail: {{ userSession.user.mail }}<br />
|
||||
Roles:
|
||||
<ul v-for="role in userState.roles" v-bind:key="role">
|
||||
<ul
|
||||
v-for="role in userSession.user.roles"
|
||||
v-bind:key="role"
|
||||
>
|
||||
<li>{{ role }}</li>
|
||||
</ul>
|
||||
<br />
|
||||
Token expires: {{ userToken.expires }}
|
||||
Token expires: {{ userSession.expires }}
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-page>
|
||||
|
@ -30,19 +36,16 @@ import { mainLink } from '../plugin';
|
|||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, { root }) {
|
||||
const userState = computed(
|
||||
() => <UserStateInterface>root.$store.getters['user/user']
|
||||
);
|
||||
const userPermissions = computed(
|
||||
() => <UserStateInterface>root.$store.getters['user/permissions']
|
||||
);
|
||||
const userToken = computed(
|
||||
() => <UserStateInterface>root.$store.getters['user/token']
|
||||
const userSession = computed(
|
||||
() => <UserStateInterface>root.$store.getters['user/session']
|
||||
);
|
||||
const checkMain = computed(() => {
|
||||
return mainLink.name == root.$route.name;
|
||||
});
|
||||
return { userState, userPermissions, userToken, checkMain };
|
||||
return { userPermissions, userSession, checkMain };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Module } from 'vuex';
|
|||
import userStore from './store/user';
|
||||
import sessionsStore from './store/session';
|
||||
import routes from './routes';
|
||||
import { StateInterface } from 'src/store';
|
||||
|
||||
const mainLink: PluginMainLink = {
|
||||
name: 'user',
|
||||
|
@ -27,7 +28,7 @@ const plugin: Plugin = {
|
|||
shortcutsOut: [],
|
||||
shortcuts: [],
|
||||
version: '0.0.1',
|
||||
store: new Map<string, Module<any, any>>([
|
||||
store: new Map<string, Module<any, StateInterface>>([
|
||||
['user', userStore],
|
||||
['sessions', sessionsStore]
|
||||
])
|
||||
|
|
|
@ -1,38 +1,29 @@
|
|||
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
|
||||
import { StateInterface } from 'src/store';
|
||||
import { axios } from 'boot/axios';
|
||||
import { LoginData } from 'src/plugins/user/models';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { LocalStorage } from 'quasar';
|
||||
import { Router } from 'src/router';
|
||||
import { axios } from 'src/boot/axios';
|
||||
|
||||
|
||||
export interface SessionInterface {
|
||||
sessions: Session[];
|
||||
loading: boolean;
|
||||
}
|
||||
export interface Session {
|
||||
browser: string;
|
||||
expires: string;
|
||||
lifetime: number;
|
||||
platform: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
const state: SessionInterface = {
|
||||
sessions: [],
|
||||
loading: false
|
||||
};
|
||||
|
||||
const mutations: MutationTree<SessionInterface> = {
|
||||
setSessions(state, sessions: Session[]) {
|
||||
setSessions (state, sessions: Session[]) {
|
||||
state.sessions = sessions;
|
||||
},
|
||||
setLoading(state, value: boolean) {
|
||||
setLoading (state, value: boolean) {
|
||||
state.loading = value;
|
||||
}
|
||||
};
|
||||
|
||||
const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||
getSessions({ commit, rootGetters }) {
|
||||
getSessions ({ commit, rootGetters }) {
|
||||
console.log(rootGetters);
|
||||
commit('setLoading', true);
|
||||
axios
|
||||
|
@ -48,7 +39,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('setLoading', false);
|
||||
});
|
||||
},
|
||||
deleteSession({ commit, dispatch, rootGetters }, token) {
|
||||
deleteSession ({ commit, dispatch }, token: string) {
|
||||
commit('setLoading', true);
|
||||
console.log('axios', axios);
|
||||
axios
|
||||
|
@ -57,7 +48,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
void dispatch('getSessions');
|
||||
})
|
||||
.catch(error => {
|
||||
console.exception();
|
||||
console.exception(error);
|
||||
})
|
||||
.finally(() => {
|
||||
commit('setLoading', false);
|
||||
|
@ -66,10 +57,10 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
};
|
||||
|
||||
const getters: GetterTree<SessionInterface, StateInterface> = {
|
||||
sessions(state) {
|
||||
sessions (state) {
|
||||
return state.sessions;
|
||||
},
|
||||
loading(state) {
|
||||
loading (state) {
|
||||
return state.loading;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,69 +6,48 @@ import { AxiosResponse } from 'axios';
|
|||
import { LocalStorage, Loading } from 'quasar';
|
||||
import { Router } from 'src/router';
|
||||
|
||||
export interface Token {
|
||||
browser: string;
|
||||
expires: string;
|
||||
lifetime: number;
|
||||
platform: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
display_name: string | null;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
mail: string;
|
||||
roles: string[];
|
||||
userid: string;
|
||||
}
|
||||
|
||||
export interface UserStateInterface extends LoginResponse {
|
||||
loginLoading: boolean;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
permissions: string[];
|
||||
token: Token;
|
||||
user: User;
|
||||
userid: string;
|
||||
session: Session;
|
||||
}
|
||||
|
||||
const state: UserStateInterface = {
|
||||
permissions: [],
|
||||
token: { browser: '', expires: '', lifetime: -1, platform: '', token: '' },
|
||||
user: {
|
||||
display_name: '',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
mail: '',
|
||||
roles: [],
|
||||
userid: ''
|
||||
session: {
|
||||
browser: '', expires: new Date(), lifetime: -1, platform: '', token: '',
|
||||
user: {
|
||||
display_name: '',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
mail: '',
|
||||
roles: [],
|
||||
userid: ''
|
||||
}
|
||||
},
|
||||
loginLoading: false
|
||||
};
|
||||
|
||||
const mutations: MutationTree<UserStateInterface> = {
|
||||
setPermissions(state, data: []) {
|
||||
setPermissions (state, data: []) {
|
||||
state.permissions = data;
|
||||
},
|
||||
setToken(state, data: Token) {
|
||||
state.token = data;
|
||||
setSession (state, data: Session) {
|
||||
state.session = data;
|
||||
},
|
||||
setUser(state, data: User) {
|
||||
state.user = data;
|
||||
},
|
||||
setLoginLoading(state, data: boolean) {
|
||||
setLoginLoading (state, data: boolean) {
|
||||
state.loginLoading = data;
|
||||
},
|
||||
showState(state) {
|
||||
showState (state) {
|
||||
console.log(state);
|
||||
}
|
||||
};
|
||||
|
||||
const actions: ActionTree<UserStateInterface, StateInterface> = {
|
||||
login({ commit }, data: LoginData) {
|
||||
console.log('bla');
|
||||
login ({ commit }, data: LoginData) {
|
||||
commit('setLoginLoading', true);
|
||||
Loading.show({ message: 'Du wirst eingeloggt' });
|
||||
void axios
|
||||
|
@ -76,12 +55,10 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
|
|||
.then((response: AxiosResponse<LoginResponse>) => {
|
||||
commit('setPermissions', response.data.permissions);
|
||||
console.log('saved permisisons');
|
||||
commit('setToken', response.data.token);
|
||||
commit('setUser', response.data.user);
|
||||
commit('setSession', response.data.session);
|
||||
commit('showState');
|
||||
LocalStorage.set('permissions', response.data.permissions);
|
||||
LocalStorage.set('token', response.data.token);
|
||||
LocalStorage.set('user', response.data.user);
|
||||
LocalStorage.set('session', response.data.session);
|
||||
|
||||
void Router.push({ name: 'user' });
|
||||
})
|
||||
|
@ -93,46 +70,29 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
|
|||
Loading.hide();
|
||||
});
|
||||
},
|
||||
loadFromLocalStorage({ commit }) {
|
||||
loadFromLocalStorage ({ commit }) {
|
||||
console.log('load from store');
|
||||
let data = LocalStorage.getItem('permissions');
|
||||
commit('setPermissions', data ? data : []);
|
||||
data = LocalStorage.getItem('token');
|
||||
data = LocalStorage.getItem('session');
|
||||
commit(
|
||||
'setToken',
|
||||
'setSession',
|
||||
data
|
||||
? data
|
||||
: { browser: '', expires: '', lifetime: -1, platform: '', token: '' }
|
||||
);
|
||||
data = LocalStorage.getItem('user');
|
||||
commit(
|
||||
'setUser',
|
||||
data
|
||||
? data
|
||||
: {
|
||||
display_name: '',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
mail: '',
|
||||
roles: [],
|
||||
userid: ''
|
||||
}
|
||||
: { browser: '', expires: new Date(), lifetime: -1, platform: '', token: '' }
|
||||
);
|
||||
commit('showState');
|
||||
}
|
||||
};
|
||||
|
||||
const getters: GetterTree<UserStateInterface, StateInterface> = {
|
||||
permissions({ permissions }) {
|
||||
permissions ({ permissions }) {
|
||||
return permissions;
|
||||
},
|
||||
token({ token }) {
|
||||
return token;
|
||||
session ({ session }) {
|
||||
return session;
|
||||
},
|
||||
user({ user }) {
|
||||
return user;
|
||||
},
|
||||
loginLoading({ loginLoading }) {
|
||||
loginLoading ({ loginLoading }) {
|
||||
return loginLoading;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { route } from 'quasar/wrappers';
|
||||
import VueRouter from 'vue-router';
|
||||
import { Store } from 'vuex';
|
||||
import { StateInterface } from '../store';
|
||||
import routes from './routes';
|
||||
import { StateInterface } from 'src/store';
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
|
@ -19,7 +19,7 @@ export const Router: VueRouter = new VueRouter({
|
|||
base: process.env.VUE_ROUTER_BASE
|
||||
});
|
||||
|
||||
export default route<Store<StateInterface>>(function({ Vue }) {
|
||||
export default route<Store<StateInterface>>(function ({ Vue }) {
|
||||
Vue.use(VueRouter);
|
||||
|
||||
return Router;
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import { store } from 'quasar/wrappers';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import user from './module-user';
|
||||
import { UserStateInterface } from './module-user/state';
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
* directly export the Store instantiation
|
||||
*/
|
||||
|
||||
export interface StateInterface {
|
||||
// Define your own store structure, using submodules if needed
|
||||
example: unknown;
|
||||
|
||||
}
|
||||
|
||||
export default store(function({ Vue }) {
|
||||
|
||||
export default store(function ({ Vue }) {
|
||||
Vue.use(Vuex);
|
||||
|
||||
const Store = new Vuex.Store<StateInterface>({
|
||||
|
|
Loading…
Reference in New Issue