123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- import type { CosyError } from './types'
- import { http, useAxios } from '@uozi-admin/request'
- import JSEncrypt from 'jsencrypt'
- import { storeToRefs } from 'pinia'
- import use2FAModal from '@/components/TwoFA/use2FAModal'
- import { useNProgress } from '@/lib/nprogress/nprogress'
- import { useSettingsStore, useUserStore } from '@/pinia'
- import router from '@/routes'
- import { handleApiError, useMessageDedupe } from './error'
- const { setRequestInterceptor, setResponseInterceptor } = useAxios()
- const nprogress = useNProgress()
- const dedupe = useMessageDedupe()
- // Helper function for encrypting JSON data
- // eslint-disable-next-line ts/no-explicit-any
- async function encryptJsonData(data: any): Promise<string> {
- const cryptoParams = await http.get('/crypto/public_key')
- const { public_key } = await cryptoParams
- // Encrypt data with RSA public key
- const encrypt = new JSEncrypt()
- encrypt.setPublicKey(public_key)
- return JSON.stringify({
- encrypted_params: encrypt.encrypt(JSON.stringify(data)),
- })
- }
- // Helper function for handling encrypted form data
- async function handleEncryptedFormData(formData: FormData): Promise<FormData> {
- const cryptoParams = await http.get('/crypto/public_key')
- const { public_key } = await cryptoParams
- // Extract form parameters that are not files
- // eslint-disable-next-line ts/no-explicit-any
- const formParams: Record<string, any> = {}
- const newFormData = new FormData()
- // Copy all files to new FormData
- for (const [key, value] of formData.entries()) {
- // Check if value is a File or Blob
- // eslint-disable-next-line ts/no-explicit-any
- if (typeof value !== 'string' && ((value as any) instanceof File || (value as any) instanceof Blob)) {
- newFormData.append(key, value)
- }
- else {
- // Collect non-file fields to encrypt
- formParams[key] = value
- }
- }
- // Encrypt the form parameters
- const encrypt = new JSEncrypt()
- encrypt.setPublicKey(public_key)
- // Add encrypted params to form data
- const encryptedData = encrypt.encrypt(JSON.stringify(formParams))
- if (encryptedData) {
- newFormData.append('encrypted_params', encryptedData)
- }
- return newFormData
- }
- // Setup request interceptor
- export function setupRequestInterceptor() {
- // Setup stores and refs
- const user = useUserStore()
- const settings = useSettingsStore()
- const { token, secureSessionId } = storeToRefs(user)
- setRequestInterceptor(
- async config => {
- nprogress.start()
- if (token.value) {
- config.headers.Authorization = token.value
- }
- if (settings.environment.id) {
- config.headers['X-Node-ID'] = settings.environment.id
- }
- if (secureSessionId.value) {
- config.headers['X-Secure-Session-ID'] = secureSessionId.value
- }
- // Handle JSON encryption
- if (config.headers?.['Content-Type'] !== 'multipart/form-data;charset=UTF-8') {
- config.headers['Content-Type'] = 'application/json'
- if (config.crypto) {
- config.data = await encryptJsonData(config.data)
- }
- }
- // Handle form data with encryption
- else if (config.crypto && config.data instanceof FormData) {
- config.data = await handleEncryptedFormData(config.data)
- }
- return config
- },
- err => {
- return Promise.reject(err)
- },
- )
- }
- // Setup response interceptor
- export function setupResponseInterceptor() {
- setResponseInterceptor(
- response => {
- nprogress.done()
- // Check if full response is requested in config
- if (response?.config?.returnFullResponse) {
- return Promise.resolve(response)
- }
- return Promise.resolve(response.data)
- },
- async error => {
- // Setup stores and refs
- const user = useUserStore()
- const { secureSessionId } = storeToRefs(user)
- nprogress.done()
- const otpModal = use2FAModal()
- // Handle authentication errors
- if (error?.response) {
- switch (error.response.status) {
- case 401:
- secureSessionId.value = ''
- await otpModal.open()
- break
- case 403:
- user.logout()
- await router.push('/login')
- return
- }
- }
- // Handle JSON error that comes back as Blob for blob request type
- if (error?.response?.data instanceof Blob && error?.response?.data?.type === 'application/json') {
- try {
- const text = await error.response.data.text()
- error.response.data = JSON.parse(text)
- }
- catch (e) {
- // If parsing fails, we'll continue with the original error.response.data
- console.error('Failed to parse blob error response as JSON', e)
- }
- }
- const err = error.response?.data as CosyError
- await handleApiError(err, dedupe)
- return Promise.reject(error.response?.data)
- },
- )
- }
- export function setupInterceptors() {
- setupRequestInterceptor()
- setupResponseInterceptor()
- }
|