Fix supplant users

This commit is contained in:
William Buezas 2024-10-02 18:40:06 -03:00
parent 0246e39f0f
commit a97219ad59
4 changed files with 311 additions and 250 deletions

View File

@ -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>

View File

@ -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">

View File

@ -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;
}
}
});

View File

@ -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
};
});