2025-01-01 22:54:40 +08:00
|
|
|
import axios, { AxiosInstance } from 'axios'
|
2025-01-01 22:44:35 +08:00
|
|
|
import applyCaseMiddleware from 'axios-case-converter'
|
2025-01-01 22:54:40 +08:00
|
|
|
import { hasCookie, getCookie, setCookie } from 'cookies-next/client'
|
2025-01-01 22:44:35 +08:00
|
|
|
|
2025-01-01 23:05:19 +08:00
|
|
|
const baseURL = 'https://api.sn.solsynth.dev'
|
2025-01-01 22:54:40 +08:00
|
|
|
|
2025-01-04 18:31:20 +08:00
|
|
|
export const sni: AxiosInstance = (() => {
|
2025-01-01 22:54:40 +08:00
|
|
|
const inst = axios.create({
|
|
|
|
baseURL,
|
|
|
|
})
|
|
|
|
|
|
|
|
inst.interceptors.request.use(
|
|
|
|
async (config) => {
|
|
|
|
const tk = await refreshToken()
|
|
|
|
if (tk) config.headers['Authorization'] = `Bearer ${tk}`
|
|
|
|
return config
|
|
|
|
},
|
|
|
|
(error) => error,
|
|
|
|
)
|
|
|
|
|
|
|
|
applyCaseMiddleware(inst, {
|
2025-01-01 22:44:35 +08:00
|
|
|
ignoreParams: true,
|
|
|
|
ignoreHeaders: true,
|
2025-01-01 22:54:40 +08:00
|
|
|
})
|
|
|
|
return inst
|
|
|
|
})()
|
|
|
|
|
|
|
|
async function refreshToken(): Promise<string | undefined> {
|
|
|
|
if (!hasCookie('nex_user_atk') || !hasCookie('nex_user_rtk')) return
|
|
|
|
|
|
|
|
const ogTk: string = getCookie('nex_user_atk')!
|
2025-01-01 23:05:19 +08:00
|
|
|
if (!isTokenExpired(ogTk)) return ogTk
|
2025-01-01 22:54:40 +08:00
|
|
|
|
2025-01-01 23:05:19 +08:00
|
|
|
const resp = await axios.post(
|
|
|
|
'/cgi/id/auth/token',
|
|
|
|
{
|
|
|
|
refresh_token: getCookie('nex_user_rtk')!,
|
|
|
|
grant_type: 'refresh_token',
|
|
|
|
},
|
|
|
|
{ baseURL },
|
|
|
|
)
|
2025-01-01 23:37:15 +08:00
|
|
|
const atk: string = resp.data['access_token']
|
|
|
|
const rtk: string = resp.data['refresh_token']
|
2025-01-01 22:54:40 +08:00
|
|
|
setCookie('nex_user_atk', atk, { path: '/', maxAge: 2592000 })
|
|
|
|
setCookie('nex_user_rtk', rtk, { path: '/', maxAge: 2592000 })
|
|
|
|
|
|
|
|
console.log('[Authenticator] Refreshed token...')
|
|
|
|
|
|
|
|
return atk
|
|
|
|
}
|
|
|
|
|
|
|
|
function isTokenExpired(token: string): boolean {
|
|
|
|
try {
|
|
|
|
const parts = token.split('.')
|
|
|
|
if (parts.length !== 3) {
|
|
|
|
throw new Error('Invalid JWT format')
|
|
|
|
}
|
|
|
|
|
|
|
|
const payload = JSON.parse(atob(parts[1]))
|
|
|
|
|
|
|
|
if (!payload.exp) {
|
|
|
|
throw new Error("'exp' claim is missing in the JWT payload")
|
|
|
|
}
|
|
|
|
|
|
|
|
const now = Math.floor(Date.now() / 1000)
|
|
|
|
|
|
|
|
return now >= payload.exp
|
|
|
|
} catch (error) {
|
|
|
|
console.error('[Authenticator] Something went wrong with token: ', error)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2025-01-01 23:37:15 +08:00
|
|
|
|
|
|
|
export function getAttachmentUrl(identifer: string): string {
|
|
|
|
if (identifer.startsWith('http')) return identifer
|
|
|
|
return `${baseURL}/cgi/uc/attachments/${identifer}`
|
|
|
|
}
|