Fix supplant users
This commit is contained in:
parent
0246e39f0f
commit
a97219ad59
|
@ -2,11 +2,14 @@
|
|||
import { useAppStore } from 'stores/app';
|
||||
import { useUserStore } from 'stores/user';
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await userStore.init();
|
||||
await userStore.init(router);
|
||||
await appStore.init();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -13,7 +13,7 @@ const appStore = useAppStore();
|
|||
const hiddenMenuItems = new Set(['Reports']);
|
||||
|
||||
const refreshContentKey = ref(0);
|
||||
const { user, supplantedUser } = storeToRefs(userStore);
|
||||
const { mainUser, supplantedUser } = storeToRefs(userStore);
|
||||
const { menuEssentialLinks, title, subtitle, useRightDrawer, rightDrawerOpen } =
|
||||
storeToRefs(appStore);
|
||||
const actions = ref(null);
|
||||
|
@ -82,7 +82,7 @@ const logoutSupplantedUser = async () => {
|
|||
</QToolbar>
|
||||
<div class="user-info">
|
||||
<div>
|
||||
<span id="user-name">{{ user?.nickname }}</span>
|
||||
<span id="user-name">{{ mainUser?.nickname }}</span>
|
||||
<QBtn flat icon="logout" alt="_Exit" @click="logout()" />
|
||||
</div>
|
||||
<div v-if="supplantedUser" id="supplant" class="supplant">
|
||||
|
|
|
@ -68,7 +68,6 @@ export const useAppStore = defineStore('hedera', {
|
|||
},
|
||||
|
||||
async init() {
|
||||
// this.router.push({ name: 'login' });
|
||||
this.getBasketOrderId();
|
||||
this.getLocaleDates();
|
||||
},
|
||||
|
@ -155,6 +154,10 @@ export const useAppStore = defineStore('hedera', {
|
|||
isTablet() {
|
||||
const $q = useQuasar();
|
||||
return $q?.screen?.width <= 1024;
|
||||
},
|
||||
isDesktop() {
|
||||
const $q = useQuasar();
|
||||
return $q?.screen?.width > 1024;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { api, jApi } from 'boot/axios';
|
||||
import { i18n } from 'src/boot/i18n';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
@ -7,254 +8,308 @@ import { useAppStore } from 'src/stores/app.js';
|
|||
const { t } = i18n.global;
|
||||
const { notify } = useNotify();
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => {
|
||||
return {
|
||||
token: '',
|
||||
isGuest: false,
|
||||
user: null,
|
||||
supplantedUser: null,
|
||||
localeOptions: [
|
||||
{ label: t('langs.en'), lang: 'en-US', value: 'en' },
|
||||
{ label: t('langs.es'), lang: 'es-ES', value: 'es' },
|
||||
{ label: t('langs.ca'), lang: 'ca-ES', value: 'ca' },
|
||||
{ label: t('langs.fr'), lang: 'fr-FR', value: 'fr' },
|
||||
{ label: t('langs.pt'), lang: 'pt-PT', value: 'pt' }
|
||||
],
|
||||
keepLogin: false,
|
||||
intervalId: null,
|
||||
isCheckingToken: false,
|
||||
tokenConfig: null
|
||||
};
|
||||
},
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const token = ref('');
|
||||
const isGuest = ref(false);
|
||||
const user = ref(null); // Usuario en uso => supplantedUser || mainUser
|
||||
const supplantedUser = ref(null); // Usuario suplantado
|
||||
const mainUser = ref(null); // Usuario principal logueado
|
||||
const localeOptions = ref([
|
||||
{ label: t('langs.en'), lang: 'en-US', value: 'en' },
|
||||
{ label: t('langs.es'), lang: 'es-ES', value: 'es' },
|
||||
{ label: t('langs.ca'), lang: 'ca-ES', value: 'ca' },
|
||||
{ label: t('langs.fr'), lang: 'fr-FR', value: 'fr' },
|
||||
{ label: t('langs.pt'), lang: 'pt-PT', value: 'pt' }
|
||||
]);
|
||||
const keepLogin = ref(false);
|
||||
const intervalId = ref(null);
|
||||
const isCheckingToken = ref(false);
|
||||
const tokenConfig = ref(null);
|
||||
let router;
|
||||
|
||||
getters: {
|
||||
loggedIn: state => !!state.token,
|
||||
userLocaleOption: state =>
|
||||
state.localeOptions?.find(l => l.value === state?.user?.lang),
|
||||
storage: state => (state.keepLogin ? localStorage : sessionStorage)
|
||||
},
|
||||
const loggedIn = computed(() => !!token.value);
|
||||
const userLocaleOption = computed(() =>
|
||||
localeOptions.value?.find(l => l.value === user.value?.lang)
|
||||
);
|
||||
const storage = computed(() =>
|
||||
keepLogin.value ? localStorage : sessionStorage
|
||||
);
|
||||
|
||||
actions: {
|
||||
async init() {
|
||||
this.isGuest = localStorage.getItem('hederaGuest') || false;
|
||||
await this.getToken();
|
||||
if (!this.loggedIn) {
|
||||
const autoLoginStatus = await this.tryAutoLogin();
|
||||
if (!autoLoginStatus) {
|
||||
this.router.push({ name: 'login' });
|
||||
}
|
||||
return;
|
||||
const init = async _router => {
|
||||
router = _router;
|
||||
isGuest.value = localStorage.getItem('hederaGuest') || false;
|
||||
console.log('isGuest.value', isGuest.value);
|
||||
await getToken();
|
||||
if (!loggedIn.value) {
|
||||
const autoLoginStatus = await tryAutoLogin();
|
||||
if (!autoLoginStatus) {
|
||||
router.push({ name: 'login' });
|
||||
}
|
||||
await this.fetchTokenConfig();
|
||||
await this.fetchUser();
|
||||
await this.supplantInit();
|
||||
this.updateSiteLocale();
|
||||
this.startInterval();
|
||||
},
|
||||
|
||||
getToken() {
|
||||
const token =
|
||||
sessionStorage.getItem('vnToken') ||
|
||||
localStorage.getItem('vnToken');
|
||||
this.token = token;
|
||||
return token;
|
||||
},
|
||||
|
||||
setToken(token) {
|
||||
this.storage.setItem('vnToken', token);
|
||||
this.token = token;
|
||||
},
|
||||
|
||||
async destroyToken(url, storage, key) {
|
||||
if (storage.getItem(key)) {
|
||||
try {
|
||||
await api.post(url, null, {
|
||||
headers: { Authorization: storage.getItem(key) }
|
||||
});
|
||||
} catch (error) {
|
||||
notify('errors.statusUnauthorized', 'negative');
|
||||
} finally {
|
||||
storage.removeItem(key);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async destroy(destroyTokens = true) {
|
||||
const tokens = {
|
||||
tokenMultimedia: 'Accounts/logout',
|
||||
token: 'VnUsers/logout'
|
||||
};
|
||||
let destroyTokenPromises = [];
|
||||
try {
|
||||
if (destroyTokens) {
|
||||
const { data: isValidToken } = await api.get(
|
||||
'VnUsers/validateToken'
|
||||
);
|
||||
if (isValidToken)
|
||||
destroyTokenPromises = Object.entries(tokens).map(
|
||||
([key, url]) =>
|
||||
this.destroyToken(url, this.storage, key)
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
await Promise.allSettled(destroyTokenPromises);
|
||||
this.user = null;
|
||||
this.stopRenewer();
|
||||
}
|
||||
},
|
||||
|
||||
isLoggedIn() {
|
||||
const token = this.getToken();
|
||||
return !!token;
|
||||
},
|
||||
|
||||
setSession(data) {
|
||||
this.storage.setItem('created', data.created);
|
||||
this.storage.setItem('ttl', data.ttl);
|
||||
localStorage.setItem('keepLogin', this.keepLogin);
|
||||
},
|
||||
|
||||
async login(user, password, remember) {
|
||||
const params = { user, password };
|
||||
const { data } = await api.post('Accounts/login', params);
|
||||
this.name = user;
|
||||
this.keepLogin = remember;
|
||||
this.setToken(data.token);
|
||||
this.setSession({ created: Date.now(), ...data });
|
||||
await this.fetchTokenConfig();
|
||||
this.startInterval();
|
||||
},
|
||||
|
||||
async tryAutoLogin() {
|
||||
const guest = localStorage.getItem('hederaGuest');
|
||||
|
||||
if (this.isGuest || guest) {
|
||||
localStorage.setItem('hederaGuest', true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.token) this.getToken();
|
||||
|
||||
if (this.token) return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
await api.post('Accounts/logout');
|
||||
} catch (e) {}
|
||||
this.destroy();
|
||||
this.$reset();
|
||||
useAppStore().onLogout();
|
||||
},
|
||||
|
||||
async fetchTokenConfig() {
|
||||
try {
|
||||
const { data } = await api.get('AccessTokenConfigs/findOne', {
|
||||
filter: { fields: ['renewInterval', 'renewPeriod'] }
|
||||
});
|
||||
if (!data) return;
|
||||
this.tokenConfig = data;
|
||||
this.storage.setItem('renewPeriod', data.renewPeriod);
|
||||
return data;
|
||||
} catch (error) {
|
||||
notify('errors.tokenConfig', 'negative');
|
||||
console.error('Error fetching token config:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async renewToken() {
|
||||
const _token = this.getToken();
|
||||
const token = await api.post('VnUsers/renewToken', {
|
||||
headers: { Authorization: _token }
|
||||
});
|
||||
|
||||
this.setToken(token.data.id);
|
||||
},
|
||||
|
||||
async checkValidity() {
|
||||
const created = +this.storage.getItem('created');
|
||||
const ttl = +this.storage.getItem('ttl');
|
||||
|
||||
if (this.isCheckingToken || !created) return;
|
||||
this.isCheckingToken = true;
|
||||
|
||||
const renewPeriodInSeconds =
|
||||
Math.min(ttl, this.tokenConfig?.renewPeriod) * 1000;
|
||||
const maxDate = created + renewPeriodInSeconds;
|
||||
const now = new Date().getTime();
|
||||
|
||||
if (isNaN(renewPeriodInSeconds) || now <= maxDate) {
|
||||
return (this.isCheckingToken = false);
|
||||
}
|
||||
|
||||
await this.renewToken();
|
||||
this.isCheckingToken = false;
|
||||
},
|
||||
|
||||
stopRenewer() {
|
||||
clearInterval(this.intervalId);
|
||||
},
|
||||
|
||||
startInterval() {
|
||||
this.stopRenewer();
|
||||
const renewPeriod = +this.storage.getItem('renewPeriod');
|
||||
if (!renewPeriod) return;
|
||||
this.intervalId = setInterval(
|
||||
() => this.checkValidity(),
|
||||
renewPeriod * 1000
|
||||
);
|
||||
},
|
||||
|
||||
async fetchUser(userType = 'user') {
|
||||
try {
|
||||
const userData = await jApi.getObject(
|
||||
'SELECT id, nickname, name, lang FROM account.myUser'
|
||||
);
|
||||
this.$patch({ [userType]: userData });
|
||||
} catch (error) {
|
||||
console.error('Error fetching user: ', error);
|
||||
}
|
||||
},
|
||||
|
||||
async supplantUser(supplantUser) {
|
||||
const json = await jApi.send('client/supplant', {
|
||||
supplantUser
|
||||
});
|
||||
this.token = json;
|
||||
sessionStorage.setItem('supplantUser', supplantUser);
|
||||
await this.fetchUser('supplantedUser');
|
||||
},
|
||||
|
||||
async supplantInit() {
|
||||
const user = sessionStorage.getItem('supplantUser');
|
||||
if (user == null) return;
|
||||
await this.supplantUser(user);
|
||||
},
|
||||
|
||||
async logoutSupplantedUser() {
|
||||
sessionStorage.removeItem('supplantUser');
|
||||
this.supplantedUser = null;
|
||||
await api.post('Accounts/logout');
|
||||
this.getToken();
|
||||
await this.fetchUser();
|
||||
},
|
||||
|
||||
updateSiteLocale(locale = null) {
|
||||
i18n.global.locale.value =
|
||||
locale || this.userLocaleOption.lang || 'en-US';
|
||||
},
|
||||
|
||||
async updateUserLang(lang) {
|
||||
if (!this.user || this.user.lang === lang) return;
|
||||
|
||||
this.user.lang = lang;
|
||||
this.updateSiteLocale();
|
||||
notify(t('dataSaved'), 'positive');
|
||||
}
|
||||
}
|
||||
await fetchTokenConfig();
|
||||
await fetchUser();
|
||||
await supplantInit();
|
||||
updateSiteLocale();
|
||||
startInterval();
|
||||
};
|
||||
|
||||
const getToken = () => {
|
||||
const tokenValue =
|
||||
sessionStorage.getItem('vnToken') ||
|
||||
localStorage.getItem('vnToken');
|
||||
token.value = tokenValue;
|
||||
return tokenValue;
|
||||
};
|
||||
|
||||
const setToken = _token => {
|
||||
storage.value.setItem('vnToken', _token);
|
||||
token.value = _token;
|
||||
};
|
||||
|
||||
const destroyToken = async (url, storageType, key) => {
|
||||
if (storageType.getItem(key)) {
|
||||
try {
|
||||
await api.post(url, null, {
|
||||
headers: { Authorization: storageType.getItem(key) }
|
||||
});
|
||||
} catch (error) {
|
||||
notify('errors.statusUnauthorized', 'negative');
|
||||
} finally {
|
||||
storageType.removeItem(key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const destroy = async (destroyTokens = true) => {
|
||||
const tokens = {
|
||||
tokenMultimedia: 'Accounts/logout',
|
||||
token: 'VnUsers/logout'
|
||||
};
|
||||
let destroyTokenPromises = [];
|
||||
try {
|
||||
if (destroyTokens) {
|
||||
const { data: isValidToken } = await api.get(
|
||||
'VnUsers/validateToken'
|
||||
);
|
||||
if (isValidToken) {
|
||||
destroyTokenPromises = Object.entries(tokens).map(
|
||||
([key, url]) => destroyToken(url, storage.value, key)
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
await Promise.allSettled(destroyTokenPromises);
|
||||
user.value = null;
|
||||
stopRenewer();
|
||||
}
|
||||
};
|
||||
|
||||
const setSession = data => {
|
||||
storage.value.setItem('created', data.created);
|
||||
storage.value.setItem('ttl', data.ttl);
|
||||
localStorage.setItem('keepLogin', keepLogin.value);
|
||||
};
|
||||
|
||||
const login = async (username, password, remember) => {
|
||||
const params = { user: username, password };
|
||||
const { data } = await api.post('Accounts/login', params);
|
||||
keepLogin.value = remember;
|
||||
storage.value.setItem('hederaLastUser', username);
|
||||
setToken(data.token);
|
||||
setSession({ created: Date.now(), ...data });
|
||||
await fetchTokenConfig();
|
||||
startInterval();
|
||||
};
|
||||
|
||||
const tryAutoLogin = async () => {
|
||||
if (isGuest.value) {
|
||||
localStorage.setItem('hederaGuest', true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!token.value) getToken();
|
||||
|
||||
if (token.value) return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
try {
|
||||
await api.post('Accounts/logout');
|
||||
} catch (e) {}
|
||||
destroy();
|
||||
$reset();
|
||||
useAppStore().onLogout();
|
||||
};
|
||||
|
||||
const fetchTokenConfig = async () => {
|
||||
try {
|
||||
const { data } = await api.get('AccessTokenConfigs/findOne', {
|
||||
filter: { fields: ['renewInterval', 'renewPeriod'] }
|
||||
});
|
||||
if (!data) return;
|
||||
tokenConfig.value = data;
|
||||
storage.value.setItem('renewPeriod', data.renewPeriod);
|
||||
return data;
|
||||
} catch (error) {
|
||||
notify('errors.tokenConfig', 'negative');
|
||||
console.error('Error fetching token config:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const renewToken = async () => {
|
||||
const _token = getToken();
|
||||
const tokenData = await api.post('VnUsers/renewToken', {
|
||||
headers: { Authorization: _token }
|
||||
});
|
||||
setToken(tokenData.data.id);
|
||||
};
|
||||
|
||||
const checkValidity = async () => {
|
||||
const created = +storage.value.getItem('created');
|
||||
const ttl = +storage.value.getItem('ttl');
|
||||
|
||||
if (isCheckingToken.value || !created) return;
|
||||
isCheckingToken.value = true;
|
||||
|
||||
const renewPeriodInSeconds =
|
||||
Math.min(ttl, tokenConfig.value?.renewPeriod) * 1000;
|
||||
const maxDate = created + renewPeriodInSeconds;
|
||||
const now = new Date().getTime();
|
||||
console.log('renewPeriodInSeconds', renewPeriodInSeconds);
|
||||
console.log('maxDate', maxDate);
|
||||
console.log('now', now);
|
||||
|
||||
if (isNaN(renewPeriodInSeconds) || now <= maxDate) {
|
||||
isCheckingToken.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await renewToken();
|
||||
isCheckingToken.value = false;
|
||||
};
|
||||
|
||||
const stopRenewer = () => {
|
||||
clearInterval(intervalId.value);
|
||||
};
|
||||
|
||||
const startInterval = () => {
|
||||
stopRenewer();
|
||||
// const renewPeriod = +storage.value.getItem('renewPeriod');
|
||||
const renewPeriod = 5;
|
||||
if (!renewPeriod) return;
|
||||
intervalId.value = setInterval(
|
||||
() => checkValidity(),
|
||||
renewPeriod * 1000
|
||||
);
|
||||
};
|
||||
|
||||
const fetchUser = async (userType = 'user') => {
|
||||
try {
|
||||
const userData = await jApi.getObject(
|
||||
'SELECT id, nickname, name, lang FROM account.myUser'
|
||||
);
|
||||
if (userType === 'user') mainUser.value = userData;
|
||||
else supplantedUser.value = userData;
|
||||
} catch (error) {
|
||||
console.error('Error fetching user: ', error);
|
||||
}
|
||||
};
|
||||
|
||||
const supplantUser = async supplantUser => {
|
||||
const json = await jApi.send('client/supplant', { supplantUser });
|
||||
token.value = json;
|
||||
sessionStorage.setItem('supplantUser', supplantUser);
|
||||
await fetchUser('supplantedUser');
|
||||
};
|
||||
|
||||
const supplantInit = async () => {
|
||||
const user = sessionStorage.getItem('supplantUser');
|
||||
if (!user) return;
|
||||
await supplantUser(user);
|
||||
};
|
||||
|
||||
const logoutSupplantedUser = async () => {
|
||||
sessionStorage.removeItem('supplantUser');
|
||||
supplantedUser.value = null;
|
||||
await api.post('Accounts/logout');
|
||||
getToken();
|
||||
await fetchUser();
|
||||
};
|
||||
|
||||
const updateSiteLocale = (locale = null) => {
|
||||
i18n.global.locale.value =
|
||||
locale || userLocaleOption.value?.lang || 'en-US';
|
||||
};
|
||||
|
||||
const updateUserLang = async lang => {
|
||||
if (!user.value || user.value.lang === lang) return;
|
||||
|
||||
user.value.lang = lang;
|
||||
updateSiteLocale();
|
||||
notify(t('dataSaved'), 'positive');
|
||||
};
|
||||
|
||||
const $reset = () => {
|
||||
token.value = '';
|
||||
isGuest.value = false;
|
||||
user.value = null;
|
||||
supplantedUser.value = null;
|
||||
mainUser.value = null;
|
||||
keepLogin.value = false;
|
||||
intervalId.value = null;
|
||||
isCheckingToken.value = false;
|
||||
tokenConfig.value = null;
|
||||
};
|
||||
|
||||
watch(
|
||||
[mainUser, supplantedUser],
|
||||
() => {
|
||||
user.value = supplantedUser.value || mainUser.value;
|
||||
console.log('mainUser.value', mainUser.value);
|
||||
console.log('supplantedUser.value', supplantedUser.value);
|
||||
console.log('user.value', user.value);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
return {
|
||||
token,
|
||||
isGuest,
|
||||
user,
|
||||
supplantedUser,
|
||||
mainUser,
|
||||
localeOptions,
|
||||
keepLogin,
|
||||
intervalId,
|
||||
isCheckingToken,
|
||||
tokenConfig,
|
||||
loggedIn,
|
||||
userLocaleOption,
|
||||
storage,
|
||||
getToken,
|
||||
setToken,
|
||||
destroyToken,
|
||||
destroy,
|
||||
setSession,
|
||||
login,
|
||||
tryAutoLogin,
|
||||
logout,
|
||||
fetchTokenConfig,
|
||||
renewToken,
|
||||
checkValidity,
|
||||
stopRenewer,
|
||||
startInterval,
|
||||
fetchUser,
|
||||
supplantUser,
|
||||
supplantInit,
|
||||
logoutSupplantedUser,
|
||||
updateSiteLocale,
|
||||
updateUserLang,
|
||||
init,
|
||||
$reset
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue