@nitra/vite-boot
Version:
127 lines (106 loc) • 3.72 kB
JavaScript
import jwtDecode from '@nitra/jwt-decode'
import { apolloClient, wsClient } from './apollo.js'
import { defaultLogin } from './login.js'
import { setUser, unsetUser } from './user.js'
// @ts-ignore
const allowedRoles = import.meta.env.VITE_HASURA_ROLE.split(',')
/**
* Запам'ятовуємо поточну сторінку
* та перенаправляємо на сторінку входу
* @param {string} token - JWT токен
* @returns {{result: string, decoded?: {}}} - Повертає результат перевірки токена
*/
export function checkToken(token) {
const decoded = jwtDecode(token)
if (!decoded || !decoded['https://hasura.io/jwt/claims']) {
cleanToken()
return { result: 'cleaned' }
}
if (!decoded['https://hasura.io/jwt/claims']['x-hasura-allowed-roles'].some(x => allowedRoles.includes(x))) {
// Виходимо
return { result: 'broken-role' }
}
const isExpired = !decoded || Math.floor(Date.now() / 1000) > decoded.exp
if (isExpired) {
refreshToken()
return { result: 'expired' }
}
return { result: 'ok', decoded }
}
/**
* Токен з кукі
*/
export function getToken() {
// інакше з кукі
const cookieObj = new URLSearchParams(document.cookie.replaceAll('; ', '&'))
const token = cookieObj.get('__session')
if (token) {
return token
}
// Якщо задано що токен беремо з localStorage
return localStorage.getItem('__session')
}
/**
* Переводимо в анонімного користувача
*/
export function cleanToken() {
unsetUser()
// видаляємо з localStorage
localStorage.removeItem('__session')
// @ts-ignore
document.cookie = `__session=; Max-Age=0; path=/; domain=${import.meta.env.VITE_DOMAIN}` // eslint-disable-line unicorn/no-document-cookie
}
/**
*
*/
export async function refreshToken() {
try {
const token = getToken()
// Чекаємо, можливо це паралельний JWTExpired
// виходимо якщо вже пішов рефреш токена від іншого запиту
if (!token) {
return
}
// Прибираємо токен, щоб інші паралельні JWTExpired не виконувались
// cleanToken()
const response = await fetch('/auth/refresh-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ token })
})
const result = await response.json()
// Якщо НЕ успішно отримали токен
if (!result.token) {
// cleanToken()
return
}
const check = checkToken(result.token)
if (check.result !== 'ok') {
// cleanToken()
return
}
// Якщо запущений аполо
// допускаємо що ми всередині прикладення
if (window.location.pathname !== '/login' && apolloClient) {
setUser(check.decoded)
// перезавантажуємо щоб він вступив в дію
wsClient.restart()
} else {
await defaultLogin(check.decoded, result.token)
}
} catch (error) {
console.error('Error:', error)
// } finally {
// // Якщо невдача отримання токену
// if (!successToken) {
// // Якщо користувач не анонімний зараз
// // TODO: допрацювати
// if (Object.keys(connectionParam).length === 0) {
// // перезавантажуємо щоб він вступив в дію як анонімний
// wsClient.restart()
// }
// }
}
}