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