Remove multi auth error checking (#2018)
* Simplify state of selected account * Remove multi auth error checking
This commit is contained in:
parent
eaa15b3b43
commit
d7e01d0186
@ -1,26 +1,21 @@
|
|||||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import * as cookie from 'cookie'
|
import * as cookie from 'cookie'
|
||||||
import { useMe } from '@/components/me'
|
|
||||||
import { USER_ID, SSR } from '@/lib/constants'
|
import { USER_ID, SSR } from '@/lib/constants'
|
||||||
import { USER } from '@/fragments/users'
|
import { USER } from '@/fragments/users'
|
||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import { UserListRow } from '@/components/user-list'
|
import { UserListRow } from '@/components/user-list'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import AddIcon from '@/svgs/add-fill.svg'
|
import AddIcon from '@/svgs/add-fill.svg'
|
||||||
import { MultiAuthErrorBanner } from '@/components/banners'
|
|
||||||
import { cookieOptions, MULTI_AUTH_ANON, MULTI_AUTH_LIST, MULTI_AUTH_POINTER } from '@/lib/auth'
|
import { cookieOptions, MULTI_AUTH_ANON, MULTI_AUTH_LIST, MULTI_AUTH_POINTER } from '@/lib/auth'
|
||||||
|
|
||||||
const AccountContext = createContext()
|
const AccountContext = createContext()
|
||||||
|
|
||||||
const CHECK_ERRORS_INTERVAL_MS = 5_000
|
|
||||||
|
|
||||||
const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8')
|
const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8')
|
||||||
|
|
||||||
export const AccountProvider = ({ children }) => {
|
export const AccountProvider = ({ children }) => {
|
||||||
const [accounts, setAccounts] = useState([])
|
const [accounts, setAccounts] = useState([])
|
||||||
const [meAnon, setMeAnon] = useState(true)
|
const [selected, setSelected] = useState(null)
|
||||||
const [errors, setErrors] = useState([])
|
|
||||||
|
|
||||||
const updateAccountsFromCookie = useCallback(() => {
|
const updateAccountsFromCookie = useCallback(() => {
|
||||||
const { [MULTI_AUTH_LIST]: listCookie } = cookie.parse(document.cookie)
|
const { [MULTI_AUTH_LIST]: listCookie } = cookie.parse(document.cookie)
|
||||||
@ -39,51 +34,29 @@ export const AccountProvider = ({ children }) => {
|
|||||||
return switchSuccess
|
return switchSuccess
|
||||||
}, [updateAccountsFromCookie])
|
}, [updateAccountsFromCookie])
|
||||||
|
|
||||||
const checkErrors = useCallback(() => {
|
|
||||||
const {
|
|
||||||
[MULTI_AUTH_LIST]: listCookie,
|
|
||||||
[MULTI_AUTH_POINTER]: pointerCookie
|
|
||||||
} = cookie.parse(document.cookie)
|
|
||||||
|
|
||||||
const errors = []
|
|
||||||
|
|
||||||
if (!listCookie) errors.push(`${MULTI_AUTH_LIST} cookie not found`)
|
|
||||||
if (!pointerCookie) errors.push(`${MULTI_AUTH_POINTER} cookie not found`)
|
|
||||||
|
|
||||||
setErrors(errors)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (SSR) return
|
if (SSR) return
|
||||||
|
|
||||||
updateAccountsFromCookie()
|
updateAccountsFromCookie()
|
||||||
|
|
||||||
const { [MULTI_AUTH_POINTER]: pointerCookie } = cookie.parse(document.cookie)
|
const { [MULTI_AUTH_POINTER]: pointerCookie } = cookie.parse(document.cookie)
|
||||||
setMeAnon(pointerCookie === 'anonymous')
|
setSelected(pointerCookie === MULTI_AUTH_ANON ? USER_ID.anon : Number(pointerCookie))
|
||||||
|
}, [updateAccountsFromCookie])
|
||||||
const interval = setInterval(checkErrors, CHECK_ERRORS_INTERVAL_MS)
|
|
||||||
return () => clearInterval(interval)
|
|
||||||
}, [updateAccountsFromCookie, checkErrors])
|
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
accounts,
|
accounts,
|
||||||
meAnon,
|
selected,
|
||||||
setMeAnon,
|
nextAccount
|
||||||
nextAccount,
|
|
||||||
multiAuthErrors: errors
|
|
||||||
}),
|
}),
|
||||||
[accounts, meAnon, setMeAnon, nextAccount])
|
[accounts, selected, nextAccount])
|
||||||
return <AccountContext.Provider value={value}>{children}</AccountContext.Provider>
|
return <AccountContext.Provider value={value}>{children}</AccountContext.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAccounts = () => useContext(AccountContext)
|
export const useAccounts = () => useContext(AccountContext)
|
||||||
|
|
||||||
const AccountListRow = ({ account, ...props }) => {
|
const AccountListRow = ({ account, ...props }) => {
|
||||||
const { meAnon, setMeAnon } = useAccounts()
|
const { selected } = useAccounts()
|
||||||
const { me, refreshMe } = useMe()
|
|
||||||
const anonRow = account.id === USER_ID.anon
|
|
||||||
const selected = (meAnon && anonRow) || Number(me?.id) === Number(account.id)
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// fetch updated names and photo ids since they might have changed since we were issued the JWTs
|
// fetch updated names and photo ids since they might have changed since we were issued the JWTs
|
||||||
@ -103,18 +76,8 @@ const AccountListRow = ({ account, ...props }) => {
|
|||||||
|
|
||||||
// update pointer cookie
|
// update pointer cookie
|
||||||
const options = cookieOptions({ httpOnly: false })
|
const options = cookieOptions({ httpOnly: false })
|
||||||
document.cookie = cookie.serialize(MULTI_AUTH_POINTER, anonRow ? MULTI_AUTH_ANON : account.id, options)
|
const anon = account.id === USER_ID.anon
|
||||||
|
document.cookie = cookie.serialize(MULTI_AUTH_POINTER, anon ? MULTI_AUTH_ANON : account.id, options)
|
||||||
// update state
|
|
||||||
if (anonRow) {
|
|
||||||
// order is important to prevent flashes of no session
|
|
||||||
setMeAnon(true)
|
|
||||||
await refreshMe()
|
|
||||||
} else {
|
|
||||||
await refreshMe()
|
|
||||||
// order is important to prevent flashes of inconsistent data in switch account dialog
|
|
||||||
setMeAnon(account.id === USER_ID.anon)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reload whatever page we're on to avoid any bugs due to missing authorization etc.
|
// reload whatever page we're on to avoid any bugs due to missing authorization etc.
|
||||||
router.reload()
|
router.reload()
|
||||||
@ -127,30 +90,16 @@ const AccountListRow = ({ account, ...props }) => {
|
|||||||
className='d-flex align-items-center me-2'
|
className='d-flex align-items-center me-2'
|
||||||
{...props}
|
{...props}
|
||||||
onNymClick={onClick}
|
onNymClick={onClick}
|
||||||
selected={selected}
|
selected={selected === account.id}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SwitchAccountList () {
|
export default function SwitchAccountList () {
|
||||||
const { accounts, multiAuthErrors } = useAccounts()
|
const { accounts } = useAccounts()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const hasError = multiAuthErrors.length > 0
|
|
||||||
|
|
||||||
if (hasError) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className='my-2'>
|
|
||||||
<div className='d-flex flex-column flex-wrap mt-2 mb-3'>
|
|
||||||
<MultiAuthErrorBanner errors={multiAuthErrors} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't show hat since the streak is not included in the JWT payload
|
// can't show hat since the streak is not included in the JWT payload
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -6,7 +6,6 @@ import { useMutation } from '@apollo/client'
|
|||||||
import { WELCOME_BANNER_MUTATION } from '@/fragments/users'
|
import { WELCOME_BANNER_MUTATION } from '@/fragments/users'
|
||||||
import { useToast } from '@/components/toast'
|
import { useToast } from '@/components/toast'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import AccordianItem from '@/components/accordian-item'
|
|
||||||
|
|
||||||
export function WelcomeBanner ({ Banner }) {
|
export function WelcomeBanner ({ Banner }) {
|
||||||
const { me } = useMe()
|
const { me } = useMe()
|
||||||
@ -124,24 +123,3 @@ export function AuthBanner () {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MultiAuthErrorBanner ({ errors }) {
|
|
||||||
return (
|
|
||||||
<Alert className={styles.banner} key='info' variant='danger'>
|
|
||||||
<div className='fw-bold mb-3'>Account switching is currently unavailable</div>
|
|
||||||
<AccordianItem
|
|
||||||
className='my-3'
|
|
||||||
header='We have detected the following issues:'
|
|
||||||
headerColor='var(--bs-danger-text-emphasis)'
|
|
||||||
body={
|
|
||||||
<ul>
|
|
||||||
{errors.map((err, i) => (
|
|
||||||
<li key={i}>{err}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<div className='mt-3'>To resolve these issues, please sign out and sign in again.</div>
|
|
||||||
</Alert>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user