hedera-web/src/stores/user.js

342 lines
9.9 KiB
JavaScript

import { defineStore } from 'pinia';
import { ref, computed, watch } from 'vue';
import { api, jApi } from '@/boot/axios';
import useNotify from '@/composables/useNotify.js';
import { useAppStore } from '@/stores/app.js';
const { notify } = useNotify();
const TOKEN_MULTIMEDIA = 'tokenMultimedia';
const TOKEN = 'token';
export const useUserStore = defineStore('user', () => {
const token = ref('');
const tokenMultimedia = 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 keepLogin = ref(false);
const intervalId = ref(null);
const isCheckingToken = ref(false);
const tokenConfig = ref(null);
let router;
const storage = computed(() =>
keepLogin.value ? localStorage : sessionStorage
);
const isLoggedIn = computed(() => !!token.value);
const init = async _router => {
router = _router;
isGuest.value = localStorage.getItem('hederaGuest') || false;
await getToken();
if (!isLoggedIn.value) {
const autoLoginStatus = await tryAutoLogin();
if (!autoLoginStatus) {
router.push({ name: 'login' });
}
} else {
await fetchUser();
await fetchTokenConfig();
await supplantInit();
startInterval();
}
};
const getToken = () => {
const tokenValue =
sessionStorage.getItem(TOKEN) || localStorage.getItem(TOKEN);
token.value = tokenValue;
return tokenValue;
};
const getTokenMultimedia = () => {
const tokenMultimediaValue =
sessionStorage.getItem(TOKEN_MULTIMEDIA) ||
localStorage.getItem(TOKEN_MULTIMEDIA);
tokenMultimedia.value = tokenMultimediaValue;
return tokenMultimediaValue;
};
const setToken = ({ _token, _tokenMultimedia }) => {
storage.value.setItem(TOKEN, _token);
storage.value.setItem(TOKEN_MULTIMEDIA, _tokenMultimedia);
token.value = _token;
tokenMultimedia.value = _tokenMultimedia;
};
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 response = await api.get('VnUsers/validateToken');
const isValidToken = response?.data;
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;
$reset();
stopRenewer();
}
};
const setSession = data => {
setToken({
_token: data.token,
_tokenMultimedia: data.tokenMultimedia
});
storage.value.setItem('hederaLastUser', data.username);
storage.value.setItem('created', data.created);
storage.value.setItem('ttl', data.ttl);
localStorage.setItem('keepLogin', keepLogin.value);
};
const fetchMultimediaToken = async data => {
try {
const response = await api.get('VnUsers/ShareToken', {
headers: { Authorization: data.token }
});
const multimediaToken = response?.data?.multimediaToken;
return multimediaToken;
} catch (error) {
throw new Error('Error fetching multimedia token');
}
};
const onLogin = async () => {
await fetchUser();
router.push({ name: 'home' });
};
const login = async (username, password, remember) => {
try {
const params = { user: username, password };
const { data } = await api.post('Accounts/login', params);
const multimediaToken = await fetchMultimediaToken(data);
if (!multimediaToken) return;
keepLogin.value = remember;
setSession({
created: Date.now(),
tokenMultimedia: multimediaToken.id,
username,
...data
});
await fetchTokenConfig();
startInterval();
await onLogin();
} catch (error) {
throw new Error('Error logging in');
}
};
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 destroy();
} catch (e) {}
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 }
});
const _tokenMultimedia = getTokenMultimedia();
const tokenMultimedia = await api.post('VnUsers/renewToken', {
headers: { Authorization: _tokenMultimedia }
});
setToken({
_token: tokenData?.data?.id || '',
_tokenMultimedia: tokenMultimedia?.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();
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');
if (!renewPeriod) return;
intervalId.value = setInterval(
() => checkValidity(),
renewPeriod * 1000
);
};
const fetchUser = async (userType = 'user') => {
try {
const userData = await api.get('VnUsers/getCurrentUserData');
if (userType === 'user') mainUser.value = userData.data;
else supplantedUser.value = userData.data;
} 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 updateUserLang = async lang => {
if (!user.value || user.value.lang === lang) return;
user.value.lang = lang;
};
const $reset = () => {
token.value = '';
tokenMultimedia.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),
{ immediate: true }
);
return {
token,
tokenMultimedia,
isGuest,
user,
supplantedUser,
mainUser,
keepLogin,
intervalId,
isCheckingToken,
tokenConfig,
isLoggedIn,
storage,
getToken,
getTokenMultimedia,
setToken,
destroyToken,
destroy,
setSession,
login,
tryAutoLogin,
logout,
fetchTokenConfig,
renewToken,
checkValidity,
stopRenewer,
startInterval,
fetchUser,
supplantUser,
supplantInit,
logoutSupplantedUser,
updateUserLang,
init,
$reset,
onLogin
};
});