Skip to content

Commit

Permalink
fix: prevent extra interceptors in strict mode
Browse files Browse the repository at this point in the history
  • Loading branch information
waynelwz committed Sep 5, 2022
1 parent de6f4f2 commit d95f538
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 72 deletions.
47 changes: 42 additions & 5 deletions console/src/api/ApiHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { useQuery } from 'react-query'
import { useCurrentUser } from '@/hooks/useCurrentUser'
import axios from 'axios'
import { toaster } from 'baseui/toast'
import { getErrMsg } from '@/api'
import { getErrMsg, setToken } from '@/api'
import { useLocation } from 'react-router-dom'
import useTranslation from '@/hooks/useTranslation'
import { useCurrentUserRoles } from '@/hooks/useCurrentUserRoles'
import { useFirstRender } from '@/hooks/useFirstRender'
import { useProject } from '@project/hooks/useProject'
import { useFetchProject } from '@/domain/project/hooks/useFetchProject'
import qs from 'qs'

export default function ApiHeader() {
const location = useLocation()
Expand All @@ -27,12 +28,48 @@ export default function ApiHeader() {
const projectInfo = useFetchProject(projectId)
const { setProject } = useProject()

// console.log(projectId, location, location?.pathname.match(/^\/projects\/(\d*)\/?/))

useFirstRender(() => {
// @ts-ignore
if (axios.interceptors.response.handlers.length > 0) return

axios.interceptors.response.use(
(response) => response,
(response) => {
if (response.headers?.authorization) setToken(response.headers.authorization)
return response.data?.data ? response.data : response
},
(error) => {
// eslint-disable-next-line no-restricted-globals
// eslint-disable-next-line prefer-destructuring
if (error.response?.status === 401) {
setToken(undefined)
}

if (error.response?.status === 401 && error.config.method === 'get') {
const withUnAuthRoute =
['/login', '/signup', '/create-account', 'logout'].filter((path) =>
location.pathname.includes(path)
).length > 0
const search = qs.parse(location.search, { ignoreQueryPrefix: true })
let { redirect } = search
if (redirect && typeof redirect === 'string') {
redirect = decodeURI(redirect)
} else if (!withUnAuthRoute) {
redirect = `${location.pathname}${location.search}`
} else {
redirect = '/projects'
}

if (!withUnAuthRoute) {
location.href = `${location.protocol}//${location.host}/login?redirect=${encodeURIComponent(
redirect
)}`
}
}

// use user/current as default token auth, it will be triggered multi times, so slient here
const withSilentRoute = error.response.config.url.includes('/user/current')
if (withSilentRoute) return Promise.reject(error)

const errMsg = getErrMsg(error)
if (Date.now() - (lastErrMsgRef.current[errMsg] || 0) > errMsgExpireTimeSeconds * 1000) {
toaster.negative(
Expand All @@ -57,7 +94,7 @@ export default function ApiHeader() {
)
lastErrMsgRef.current[errMsg] = Date.now()
}
return error
return Promise.reject(error)
}
)
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
16 changes: 9 additions & 7 deletions console/src/api/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const location = window.location
export const AuthProvider = ({ children }: any) => {
const [currentToken, setCurrentToken] = React.useState(getToken())

const userInfo = useQuery('currentUser', fetchCurrentUser, { refetchOnWindowFocus: false })
const userInfo = useQuery('currentUser', fetchCurrentUser, { refetchOnWindowFocus: false, retry: 0 })

// eslint-disable-next-line react-hooks/exhaustive-deps
const { setCurrentUser } = useCurrentUser()
Expand All @@ -45,8 +45,14 @@ export const AuthProvider = ({ children }: any) => {
}, [userInfo, setCurrentUser])

const handleLogin = async (data: ILoginUserSchema) => {
await loginUser(data)
await userInfo.refetch()
try {
await loginUser(data)
await userInfo.refetch()
} catch (error) {
return ''
} finally {
if (getToken() !== currentToken) setCurrentToken(getToken())
}

const search = qs.parse(location.search, { ignoreQueryPrefix: true })
let { redirect } = search
Expand All @@ -56,18 +62,14 @@ export const AuthProvider = ({ children }: any) => {
redirect = '/'
}

setCurrentToken(getToken())
return redirect
}

const handleLogout = () => {
setToken(undefined)
// setCurrentToken(null)
simulationJump('/logout')
}

// console.log('raw:', !!getToken(), 'new:', !!currentToken, currentUser)

const value = {
token: currentToken,
onLogin: handleLogin,
Expand Down
46 changes: 5 additions & 41 deletions console/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable no-param-reassign */
import axios from 'axios'
import qs from 'qs'

const key = 'token'
const store = window.localStorage ?? {
Expand All @@ -10,6 +9,10 @@ const store = window.localStorage ?? {
getter: () => undefined,
}

export const getToken = () => {
return store?.token
}

export const setToken = (token: string | undefined) => {
if (!token) {
store.removeItem(key)
Expand All @@ -20,48 +23,9 @@ export const setToken = (token: string | undefined) => {

export function apiInit() {
axios.interceptors.request.use((config) => {
config.headers.Authorization = store?.token
config.headers.Authorization = getToken()
return config
})
axios.interceptors.response.use(
(response) => {
if (response.headers.authorization) setToken(response.headers.authorization)
return response.data?.data ? response.data : response
},
(error) => {
// eslint-disable-next-line no-restricted-globals
// eslint-disable-next-line prefer-destructuring
const location = window.location
if (error.response?.status === 401) {
setToken(undefined)
}
if (error.response?.status === 401 && error.config.method === 'get') {
const withUnAuthRoute =
['/login', '/signup', '/create-account'].filter((path) => location.pathname.includes(path)).length >
0
const search = qs.parse(location.search, { ignoreQueryPrefix: true })
let { redirect } = search
if (redirect && typeof redirect === 'string') {
redirect = decodeURI(redirect)
} else if (!withUnAuthRoute) {
redirect = `${location.pathname}${location.search}`
} else {
redirect = '/projects'
}

if (!withUnAuthRoute) {
location.href = `${location.protocol}//${location.host}/login?redirect=${encodeURIComponent(
redirect
)}`
}
}
return error
}
)
}

export const getToken = () => {
return store?.token
}

export function getErrMsg(err: any): string {
Expand Down
15 changes: 12 additions & 3 deletions console/src/domain/datastore/hooks/useFetchDatastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@ export function useQueryDatastore(query: any) {
}

export function useQueryDatasetList(tableName?: string, page?: IListQuerySchema, rawResult = false) {
const { start, limit } = React.useMemo(() => {
const { pageNum = 1, pageSize = 10 } = page || {}

return {
start: (pageNum - 1) * pageSize ?? 0,
limit: pageSize ?? 0,
}
}, [page])

const info = useQueryDatastore({
tableName,
start: page?.pageNum ?? 0,
limit: page?.pageSize ?? 0,
start,
limit,
rawResult,
})

Expand All @@ -33,7 +42,7 @@ export function useQueryDatasetList(tableName?: string, page?: IListQuerySchema,
info.refetch()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableName, page])
}, [tableName, start, limit])

return info
}
4 changes: 1 addition & 3 deletions console/src/pages/Dataset/DatasetVersionOverviewFiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export default function DatasetVersionFiles() {
start: page.pageNum,
count: page.pageSize,
total: rowCount,
afterPageChange: () => {
tables.refetch()
},
afterPageChange: () => {},
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [page, rowCount])
Expand Down
8 changes: 2 additions & 6 deletions console/src/pages/Home/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import Card from '@/components/Card'
import { createForm } from '@/components/Form'
import useTranslation from '@/hooks/useTranslation'
import { ILoginUserSchema } from '@user/schemas/user'
// import { loginUser } from '@user/services/user'
import { Input } from 'baseui/input'
// import qs from 'qs'
import React, { useCallback, useState } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { useHistory } from 'react-router-dom'
import Button from '@/components/Button'
import IconFont from '@/components/IconFont'
import { useAuth } from '@/api/Auth'
Expand All @@ -16,7 +14,6 @@ const { Form, FormItem } = createForm<ILoginUserSchema>()

export default function Login() {
const [t] = useTranslation()
const location = useLocation()
const history = useHistory()
const [isLoading, setIsLoading] = useState(false)
const { onLogin } = useAuth()
Expand All @@ -31,8 +28,7 @@ export default function Login() {
setIsLoading(false)
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[history, location.search, onLogin]
[history, onLogin]
)

return (
Expand Down
6 changes: 0 additions & 6 deletions console/src/pages/Project/ProjectSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ export default function ProjectSidebar({ style }: IComposedSidebarProps) {
activePathPattern: /\/(runtimes|new_runtime)\/?/,
icon: <IconFont type='runtime' size={16} />,
},
// {
// title: t('Job'),
// path: `/projects/${projectId}/jobs`,
// activePathPattern: /\/(jobs|new_job)\/?/,
// icon: <IconFont type='job' kind='white' size={20} />,
// },
]
}, [project, projectId, t])
return (
Expand Down
2 changes: 1 addition & 1 deletion console/src/pages/Runtime/RuntimeVersionListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function RuntimeVersionListCard() {
toaster.positive(t('runtime version reverted'), { autoHideDuration: 2000 })
await runtimesInfo.refetch()
},
[runtimesInfo, projectId, runtimeId]
[runtimesInfo, projectId, runtimeId, t]
)
return (
<Card title={t('runtime versions')}>
Expand Down

0 comments on commit d95f538

Please sign in to comment.