99 lines
3.1 KiB
JavaScript
99 lines
3.1 KiB
JavaScript
import { useRouter } from 'next/router'
|
|
import { USER_ID } from '@/lib/constants'
|
|
import { USER } from '@/fragments/users'
|
|
import { useQuery } from '@apollo/client'
|
|
import { UserListRow } from '@/components/user-list'
|
|
import useCookie from '@/components/use-cookie'
|
|
import Link from 'next/link'
|
|
import AddIcon from '@/svgs/add-fill.svg'
|
|
import { cookieOptions, MULTI_AUTH_ANON, MULTI_AUTH_LIST, MULTI_AUTH_POINTER } from '@/lib/auth'
|
|
|
|
const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8')
|
|
|
|
export const nextAccount = async () => {
|
|
const { status } = await fetch('/api/next-account', { credentials: 'include' })
|
|
// if status is 302, this means the server was able to switch us to the next available account
|
|
return status === 302
|
|
}
|
|
|
|
export default function SwitchAccountList () {
|
|
const router = useRouter()
|
|
const accounts = useAccounts()
|
|
const [pointerCookie] = useCookie(MULTI_AUTH_POINTER)
|
|
|
|
return (
|
|
<>
|
|
<div className='my-2'>
|
|
<div className='d-flex flex-column flex-wrap mt-2 mb-3'>
|
|
<h4 className='text-muted'>Accounts</h4>
|
|
<AccountListRow
|
|
account={{ id: USER_ID.anon, name: 'anon' }}
|
|
selected={pointerCookie === MULTI_AUTH_ANON}
|
|
showHat={false}
|
|
/>
|
|
{
|
|
accounts.map((account) =>
|
|
<AccountListRow
|
|
key={account.id}
|
|
account={account}
|
|
selected={Number(pointerCookie) === account.id}
|
|
showHat={false}
|
|
/>)
|
|
}
|
|
</div>
|
|
<Link
|
|
href={{
|
|
pathname: '/login',
|
|
query: { callbackUrl: window.location.origin + router.asPath, multiAuth: true }
|
|
}}
|
|
className='text-reset fw-bold'
|
|
>
|
|
<AddIcon height={20} width={20} /> another account
|
|
</Link>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
const AccountListRow = ({ account, selected, ...props }) => {
|
|
const router = useRouter()
|
|
const [, setPointerCookie] = useCookie(MULTI_AUTH_POINTER)
|
|
|
|
// fetch updated names and photo ids since they might have changed since we were issued the JWTs
|
|
const { data, error } = useQuery(USER, { variables: { id: account.id } })
|
|
if (error) console.error(`query for user ${account.id} failed:`, error)
|
|
|
|
const name = data?.user?.name || account.name
|
|
const photoId = data?.user?.photoId || account.photoId
|
|
|
|
const onClick = async (e) => {
|
|
// prevent navigation
|
|
e.preventDefault()
|
|
|
|
// update pointer cookie
|
|
const options = cookieOptions({ httpOnly: false })
|
|
const anon = account.id === USER_ID.anon
|
|
setPointerCookie(anon ? MULTI_AUTH_ANON : account.id, options)
|
|
|
|
// reload whatever page we're on to avoid any bugs due to missing authorization etc.
|
|
router.reload()
|
|
}
|
|
|
|
return (
|
|
<div className='d-flex flex-row'>
|
|
<UserListRow
|
|
user={{ ...account, photoId, name }}
|
|
className='d-flex align-items-center me-2'
|
|
selected={selected}
|
|
{...props}
|
|
onNymClick={onClick}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const useAccounts = () => {
|
|
const [listCookie] = useCookie(MULTI_AUTH_LIST)
|
|
return listCookie ? JSON.parse(b64Decode(listCookie)) : []
|
|
}
|