Ensure sessions and tokens are synced between tabs (#2498)

* Ensure sessions and tokens are synced between tabs

* Send clear account to sentry for monitoring
zio/stable
Eric Bailey 2024-01-12 12:39:21 -06:00 committed by GitHub
parent c0261fc940
commit 11f6ff7cbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 37 additions and 23 deletions

View File

@ -193,11 +193,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
) )
const clearCurrentAccount = React.useCallback(() => { const clearCurrentAccount = React.useCallback(() => {
logger.debug( logger.warn(`session: clear current account`)
`session: clear current account`,
{},
logger.DebugContext.session,
)
__globalAgent = PUBLIC_BSKY_AGENT __globalAgent = PUBLIC_BSKY_AGENT
queryClient.clear() queryClient.clear()
setStateAndPersist(s => ({ setStateAndPersist(s => ({
@ -322,8 +318,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
) )
const logout = React.useCallback<ApiContext['logout']>(async () => { const logout = React.useCallback<ApiContext['logout']>(async () => {
logger.info(`session: logout`)
clearCurrentAccount() clearCurrentAccount()
logger.debug(`session: logout`, {}, logger.DebugContext.session)
setStateAndPersist(s => { setStateAndPersist(s => {
return { return {
...s, ...s,
@ -551,30 +547,36 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
return persisted.onUpdate(() => { return persisted.onUpdate(() => {
const session = persisted.get('session') const session = persisted.get('session')
logger.debug(`session: onUpdate`, {}, logger.DebugContext.session) logger.info(`session: persisted onUpdate`, {})
if (session.currentAccount) { if (session.currentAccount && session.currentAccount.refreshJwt) {
if (session.currentAccount?.did !== state.currentAccount?.did) { if (session.currentAccount?.did !== state.currentAccount?.did) {
logger.debug( logger.info(`session: persisted onUpdate, switching accounts`, {
`session: switching account`, from: {
{ did: state.currentAccount?.did,
from: { handle: state.currentAccount?.handle,
did: state.currentAccount?.did,
handle: state.currentAccount?.handle,
},
to: {
did: session.currentAccount.did,
handle: session.currentAccount.handle,
},
}, },
logger.DebugContext.session, to: {
) did: session.currentAccount.did,
handle: session.currentAccount.handle,
},
})
initSession(session.currentAccount) initSession(session.currentAccount)
} else {
logger.info(`session: persisted onUpdate, updating session`, {})
/*
* Use updated session in this tab's agent. Do not call
* upsertAccount, since that will only persist the session that's
* already persisted, and we'll get a loop between tabs.
*/
// @ts-ignore we checked for `refreshJwt` above
__globalAgent.session = session.currentAccount
} }
} else if (!session.currentAccount && state.currentAccount) { } else if (!session.currentAccount && state.currentAccount) {
logger.debug( logger.debug(
`session: logging out`, `session: persisted onUpdate, logging out`,
{ {
did: state.currentAccount?.did, did: state.currentAccount?.did,
handle: state.currentAccount?.handle, handle: state.currentAccount?.handle,
@ -582,10 +584,22 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
logger.DebugContext.session, logger.DebugContext.session,
) )
/*
* No need to do a hard logout here. If we reach this, tokens for this
* account have already been cleared either by an `expired` event
* handled by `persistSession` (which nukes this accounts tokens only),
* or by a `logout` call which nukes all accounts tokens)
*/
clearCurrentAccount() clearCurrentAccount()
} }
setState(s => ({
...s,
accounts: session.accounts,
currentAccount: session.currentAccount,
}))
}) })
}, [state, clearCurrentAccount, initSession]) }, [state, setState, clearCurrentAccount, initSession])
const stateContext = React.useMemo( const stateContext = React.useMemo(
() => ({ () => ({