Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(console): prevent extra interceptors in strict mode #1122

Merged
merged 3 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 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,49 @@ 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
const winLocation = 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) => winLocation.pathname.includes(path))
.length > 0
const search = qs.parse(winLocation.search, { ignoreQueryPrefix: true })
let { redirect } = search
if (redirect && typeof redirect === 'string') {
redirect = decodeURI(redirect)
} else if (!withUnAuthRoute) {
redirect = `${winLocation.pathname}${winLocation.search}`
} else {
redirect = '/projects'
}

if (!withUnAuthRoute) {
winLocation.href = `${winLocation.protocol}//${
winLocation.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 +95,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