release v2.0.0 #4
|
@ -1719,6 +1719,12 @@
|
|||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
|
||||
"integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
|
||||
"dev": true
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.2.0.tgz",
|
||||
"integrity": "sha512-khkrcUIzMcI1rDcNtqkvLwfRFzB97GmJEsPAQdj7t/VvpGhmXLOkUfhc+Ah8CvpSXGXwuWuQO+x8Sy/xDhXZIA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -4262,9 +4268,9 @@
|
|||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
|
||||
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz",
|
||||
"integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.6.5",
|
||||
|
@ -13650,10 +13656,9 @@
|
|||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.2.0.tgz",
|
||||
"integrity": "sha512-khkrcUIzMcI1rDcNtqkvLwfRFzB97GmJEsPAQdj7t/VvpGhmXLOkUfhc+Ah8CvpSXGXwuWuQO+x8Sy/xDhXZIA==",
|
||||
"dev": true
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.3.2.tgz",
|
||||
"integrity": "sha512-5sEbcfb7MW8mY8lbUVbF4kgcipGXsagkM/X+pb6n0MhjP+RorWIUTPAPSqgPaiPOxVCXgAItBl8Vwz8vq78faA=="
|
||||
},
|
||||
"vue-server-renderer": {
|
||||
"version": "2.6.12",
|
||||
|
|
12
package.json
12
package.json
|
@ -13,8 +13,9 @@
|
|||
"@quasar/extras": "^1.9.10",
|
||||
"@vue/composition-api": "^0.6.4",
|
||||
"axios": "^0.18.1",
|
||||
"core-js": "^3.6.5",
|
||||
"quasar": "^1.14.3"
|
||||
"core-js": "^3.7.0",
|
||||
"quasar": "^1.14.3",
|
||||
"vue-router": "3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/app": "^2.1.6",
|
||||
|
@ -34,15 +35,14 @@
|
|||
"last 10 Chrome versions",
|
||||
"last 10 Firefox versions",
|
||||
"last 4 Edge versions",
|
||||
"last 7 Safari versions",
|
||||
"last 6 Safari versions",
|
||||
"last 8 Android versions",
|
||||
"last 8 ChromeAndroid versions",
|
||||
"last 8 FirefoxAndroid versions",
|
||||
"last 10 iOS versions",
|
||||
"last 5 Opera versions"
|
||||
"last 10 iOS versions"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.18.1",
|
||||
"node": ">= 11.0.0",
|
||||
"npm": ">= 6.13.4",
|
||||
"yarn": ">= 1.21.1"
|
||||
}
|
||||
|
|
|
@ -36,10 +36,13 @@ export default boot<Store<StateInterface>>(({ Vue, store }) => {
|
|||
error => {
|
||||
if (error) {
|
||||
const e = <AxiosError>error;
|
||||
if (e.code === 'ECONNABORTED' || e.response && e.response.status === 502) {
|
||||
if (
|
||||
e.code === 'ECONNABORTED' ||
|
||||
(e.response && e.response.status === 502)
|
||||
) {
|
||||
store.commit('session/setOffline', true);
|
||||
} else if (e.response && e.response.status == 401) {
|
||||
return store.dispatch('session/clearup');
|
||||
return store.dispatch('session/clearCurrent');
|
||||
}
|
||||
}
|
||||
return Promise.reject(error);
|
||||
|
|
|
@ -35,7 +35,13 @@ export default boot<Store<StateInterface>>(({ router, store }) => {
|
|||
next({ name: 'login', query: { redirect: to.fullPath } });
|
||||
}
|
||||
} else {
|
||||
if (store.state.user.currentUser && !to.params['logout']) {
|
||||
// Called login while already logged in
|
||||
void next({ name: 'user-main' });
|
||||
} else {
|
||||
// Not logged in or from logout
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
import EssentialLink from 'components/navigation/EssentialLink.vue';
|
||||
import ShortCutLink from 'components/navigation/ShortCutLink.vue';
|
||||
import BackendOffline from 'components/loading/BackendOffline.vue';
|
||||
import { Screen } from 'quasar';
|
||||
import { Screen, Loading } from 'quasar';
|
||||
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||
import { Store } from 'vuex';
|
||||
import { StateInterface } from 'src/store';
|
||||
|
@ -180,11 +180,11 @@ export default defineComponent({
|
|||
});
|
||||
|
||||
function logout() {
|
||||
const store = <Store<StateInterface>>ctx.root.$store;
|
||||
store
|
||||
.dispatch('session/logout', store.state.session.currentSession?.token)
|
||||
.catch(error => {
|
||||
console.warn(error);
|
||||
Loading.show({ message: 'Session wird abgemeldet' });
|
||||
(<Store<StateInterface>>ctx.root.$store)
|
||||
.dispatch('session/logout')
|
||||
.finally(() => {
|
||||
Loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,14 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from '@vue/composition-api';
|
||||
import { Loading } from 'quasar';
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, { root }) {
|
||||
const mainRoute = { name: 'user-main' };
|
||||
|
||||
/* Stuff for the real login page */
|
||||
const userid = ref('');
|
||||
const password = ref('');
|
||||
const rules = [
|
||||
|
@ -46,13 +50,22 @@ export default defineComponent({
|
|||
];
|
||||
|
||||
function doLogin() {
|
||||
Loading.show({
|
||||
message: 'Du wirst angemeldet'
|
||||
});
|
||||
root.$store
|
||||
.dispatch('session/login', {
|
||||
userid: userid.value,
|
||||
password: password.value
|
||||
})
|
||||
.catch(error => {
|
||||
console.warn(error);
|
||||
.then(() => {
|
||||
const x = root.$route.query['redirect'];
|
||||
void root.$router.replace(
|
||||
typeof x === 'string' ? { path: x } : mainRoute
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
Loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { StateInterface } from 'src/store';
|
|||
import { axios } from 'src/boot/axios';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { Router } from 'src/router';
|
||||
import { LocalStorage, Loading } from 'quasar';
|
||||
import { LocalStorage } from 'quasar';
|
||||
|
||||
export interface SessionInterface {
|
||||
currentSession?: FG.Session;
|
||||
|
@ -13,7 +13,11 @@ export interface SessionInterface {
|
|||
backendOffline: boolean;
|
||||
}
|
||||
|
||||
function loadFromLocal() {
|
||||
/**
|
||||
* Load current session from LocalStorage
|
||||
* Used when we were already authenticated using this browser
|
||||
*/
|
||||
function loadCurrentSession() {
|
||||
const session = LocalStorage.getItem<FG.Session>('currentSession');
|
||||
if (session) session.expires = new Date(session.expires);
|
||||
return session;
|
||||
|
@ -21,7 +25,7 @@ function loadFromLocal() {
|
|||
|
||||
const state: SessionInterface = {
|
||||
sessions: [],
|
||||
currentSession: loadFromLocal() || undefined,
|
||||
currentSession: loadCurrentSession() || undefined,
|
||||
loading: false,
|
||||
backendOffline: false
|
||||
};
|
||||
|
@ -47,11 +51,13 @@ const mutations: MutationTree<SessionInterface> = {
|
|||
};
|
||||
|
||||
const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||
/** Used to authenticate the user
|
||||
* Setting current Session, User and Permissions.
|
||||
* @param param0 Context
|
||||
* @param data Credentitals
|
||||
*/
|
||||
login({ commit }, data: LoginData) {
|
||||
Loading.show({
|
||||
message: 'Du wirst angemeldet'
|
||||
});
|
||||
void axios
|
||||
return axios
|
||||
.post('/auth', data)
|
||||
.then((response: AxiosResponse<LoginResponse>) => {
|
||||
response.data.session.expires = new Date(response.data.session.expires);
|
||||
|
@ -60,38 +66,38 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('user/setCurrentPermissions', response.data.permissions, {
|
||||
root: true
|
||||
});
|
||||
})
|
||||
.catch(error => console.warn(error))
|
||||
.finally(() => {
|
||||
void Router.push({ name: 'user-main' });
|
||||
Loading.hide();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Logout from current session
|
||||
* Alias of deleteSession with current session as target
|
||||
*/
|
||||
logout({ dispatch, rootState }) {
|
||||
Loading.show({ message: 'Session wird abgemeldet' });
|
||||
dispatch('deleteSession', rootState.session.currentSession?.token).finally(
|
||||
() => {
|
||||
Loading.hide();
|
||||
if (rootState.session.currentSession) {
|
||||
dispatch('deleteSession', rootState.session.currentSession.token).catch(
|
||||
error => {
|
||||
console.log(error);
|
||||
void dispatch('clearCurrent', false);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
void dispatch('clearCurrent', false);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Delete a given session
|
||||
*/
|
||||
deleteSession({ commit, dispatch, rootState }, token: string | null) {
|
||||
if (token === null) return;
|
||||
|
||||
deleteSession({ commit, dispatch, rootState }, token: string) {
|
||||
commit('setLoading', true);
|
||||
axios
|
||||
.delete(`/auth/${token}`)
|
||||
.then(() => {
|
||||
if (token === rootState.session.currentSession?.token) {
|
||||
void dispatch('clearup');
|
||||
void dispatch('clearCurrent', false);
|
||||
} else {
|
||||
commit('getSessions');
|
||||
dispatch('getSessions').catch(error => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
|
@ -101,15 +107,23 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
commit('setLoading', false);
|
||||
});
|
||||
},
|
||||
clearup({ commit }) {
|
||||
/**
|
||||
* Clear current session and logged in user
|
||||
*/
|
||||
clearCurrent({ commit }, redirect = true) {
|
||||
void Router.push({
|
||||
name: 'login',
|
||||
query: redirect ? { redirect: Router.currentRoute.fullPath } : {},
|
||||
params: { logout: 'true' }
|
||||
}).then(() => {
|
||||
commit('clearCurrentSession');
|
||||
commit('user/clearCurrentUser', null, { root: true });
|
||||
void Router.push({ name: 'login' });
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Get all sessions from current User
|
||||
*/
|
||||
getSessions({ commit, state, dispatch }) {
|
||||
getSessions({ commit, state }) {
|
||||
commit('setLoading', true);
|
||||
axios
|
||||
.get('/auth')
|
||||
|
@ -122,11 +136,11 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
|||
return session.token === state.currentSession?.token;
|
||||
});
|
||||
if (currentSession) {
|
||||
void dispatch('setCurrentSession', currentSession);
|
||||
commit('setCurrentSession', currentSession);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.exception(error);
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
commit('setLoading', false);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"extends": "@quasar/app/tsconfig-preset",
|
||||
"compilerOptions": {
|
||||
"types": ["node", "webpack-env", "@quasar/app"],
|
||||
"baseUrl": "."
|
||||
"baseUrl": ".",
|
||||
"lib": ["DOM", "ES2019"]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue