[Session] Call persist handler directly (#3828)
parent
b86c3b486f
commit
6405ad7cba
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {AtpPersistSessionHandler, BskyAgent} from '@atproto/api'
|
import {AtpSessionData, AtpSessionEvent, BskyAgent} from '@atproto/api'
|
||||||
|
|
||||||
import {track} from '#/lib/analytics/analytics'
|
import {track} from '#/lib/analytics/analytics'
|
||||||
import {networkRetry} from '#/lib/async/retry'
|
import {networkRetry} from '#/lib/async/retry'
|
||||||
|
@ -93,77 +93,65 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
}))
|
}))
|
||||||
}, [setState])
|
}, [setState])
|
||||||
|
|
||||||
const createPersistSessionHandler = React.useCallback(
|
const onAgentSessionChange = React.useCallback(
|
||||||
(
|
(
|
||||||
agent: BskyAgent,
|
agent: BskyAgent,
|
||||||
account: SessionAccount,
|
account: SessionAccount,
|
||||||
persistSessionCallback: (props: {
|
event: AtpSessionEvent,
|
||||||
expired: boolean
|
session: AtpSessionData | undefined,
|
||||||
refreshedAccount: SessionAccount
|
) => {
|
||||||
}) => void,
|
const expired = event === 'expired' || event === 'create-failed'
|
||||||
{
|
|
||||||
networkErrorCallback,
|
|
||||||
}: {
|
|
||||||
networkErrorCallback?: () => void
|
|
||||||
} = {},
|
|
||||||
): AtpPersistSessionHandler => {
|
|
||||||
return function persistSession(event, session) {
|
|
||||||
const expired = event === 'expired' || event === 'create-failed'
|
|
||||||
|
|
||||||
if (event === 'network-error') {
|
if (event === 'network-error') {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`session: persistSessionHandler received network-error event`,
|
`session: persistSessionHandler received network-error event`,
|
||||||
)
|
)
|
||||||
networkErrorCallback?.()
|
clearCurrentAccount()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use agentToSessionAccount for this too.
|
// TODO: use agentToSessionAccount for this too.
|
||||||
const refreshedAccount: SessionAccount = {
|
const refreshedAccount: SessionAccount = {
|
||||||
service: account.service,
|
service: account.service,
|
||||||
did: session?.did || account.did,
|
did: session?.did || account.did,
|
||||||
handle: session?.handle || account.handle,
|
handle: session?.handle || account.handle,
|
||||||
email: session?.email || account.email,
|
email: session?.email || account.email,
|
||||||
emailConfirmed: session?.emailConfirmed || account.emailConfirmed,
|
emailConfirmed: session?.emailConfirmed || account.emailConfirmed,
|
||||||
emailAuthFactor: session?.emailAuthFactor || account.emailAuthFactor,
|
emailAuthFactor: session?.emailAuthFactor || account.emailAuthFactor,
|
||||||
deactivated: isSessionDeactivated(session?.accessJwt),
|
deactivated: isSessionDeactivated(session?.accessJwt),
|
||||||
pdsUrl: agent.pdsUrl?.toString(),
|
pdsUrl: agent.pdsUrl?.toString(),
|
||||||
|
|
||||||
/*
|
|
||||||
* Tokens are undefined if the session expires, or if creation fails for
|
|
||||||
* any reason e.g. tokens are invalid, network error, etc.
|
|
||||||
*/
|
|
||||||
refreshJwt: session?.refreshJwt,
|
|
||||||
accessJwt: session?.accessJwt,
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(`session: persistSession`, {
|
|
||||||
event,
|
|
||||||
deactivated: refreshedAccount.deactivated,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (expired) {
|
|
||||||
logger.warn(`session: expired`)
|
|
||||||
emitSessionDropped()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the session expired, or it was successfully created/updated, we want
|
* Tokens are undefined if the session expires, or if creation fails for
|
||||||
* to update/persist the data.
|
* any reason e.g. tokens are invalid, network error, etc.
|
||||||
*
|
|
||||||
* If the session creation failed, it could be a network error, or it could
|
|
||||||
* be more serious like an invalid token(s). We can't differentiate, so in
|
|
||||||
* order to allow the user to get a fresh token (if they need it), we need
|
|
||||||
* to persist this data and wipe their tokens, effectively logging them
|
|
||||||
* out.
|
|
||||||
*/
|
*/
|
||||||
persistSessionCallback({
|
refreshJwt: session?.refreshJwt,
|
||||||
expired,
|
accessJwt: session?.accessJwt,
|
||||||
refreshedAccount,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug(`session: persistSession`, {
|
||||||
|
event,
|
||||||
|
deactivated: refreshedAccount.deactivated,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
logger.warn(`session: expired`)
|
||||||
|
emitSessionDropped()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the session expired, or it was successfully created/updated, we want
|
||||||
|
* to update/persist the data.
|
||||||
|
*
|
||||||
|
* If the session creation failed, it could be a network error, or it could
|
||||||
|
* be more serious like an invalid token(s). We can't differentiate, so in
|
||||||
|
* order to allow the user to get a fresh token (if they need it), we need
|
||||||
|
* to persist this data and wipe their tokens, effectively logging them
|
||||||
|
* out.
|
||||||
|
*/
|
||||||
|
upsertAccount(refreshedAccount, expired)
|
||||||
},
|
},
|
||||||
[],
|
[clearCurrentAccount, upsertAccount],
|
||||||
)
|
)
|
||||||
|
|
||||||
const createAccount = React.useCallback<SessionApiContext['createAccount']>(
|
const createAccount = React.useCallback<SessionApiContext['createAccount']>(
|
||||||
|
@ -191,16 +179,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
agent.setPersistSessionHandler(
|
agent.setPersistSessionHandler((event, session) => {
|
||||||
createPersistSessionHandler(
|
onAgentSessionChange(agent, account, event, session)
|
||||||
agent,
|
})
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount, expired)
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
__globalAgent = agent
|
__globalAgent = agent
|
||||||
await fetchingGates
|
await fetchingGates
|
||||||
|
@ -210,7 +191,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
track('Create Account')
|
track('Create Account')
|
||||||
logEvent('account:create:success', {})
|
logEvent('account:create:success', {})
|
||||||
},
|
},
|
||||||
[upsertAccount, clearCurrentAccount, createPersistSessionHandler],
|
[upsertAccount, onAgentSessionChange],
|
||||||
)
|
)
|
||||||
|
|
||||||
const login = React.useCallback<SessionApiContext['login']>(
|
const login = React.useCallback<SessionApiContext['login']>(
|
||||||
|
@ -223,16 +204,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
authFactorToken,
|
authFactorToken,
|
||||||
})
|
})
|
||||||
|
|
||||||
agent.setPersistSessionHandler(
|
agent.setPersistSessionHandler((event, session) => {
|
||||||
createPersistSessionHandler(
|
onAgentSessionChange(agent, account, event, session)
|
||||||
agent,
|
})
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount, expired)
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
__globalAgent = agent
|
__globalAgent = agent
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -245,7 +219,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
track('Sign In', {resumedSession: false})
|
track('Sign In', {resumedSession: false})
|
||||||
logEvent('account:loggedIn', {logContext, withPassword: true})
|
logEvent('account:loggedIn', {logContext, withPassword: true})
|
||||||
},
|
},
|
||||||
[upsertAccount, clearCurrentAccount, createPersistSessionHandler],
|
[upsertAccount, onAgentSessionChange],
|
||||||
)
|
)
|
||||||
|
|
||||||
const logout = React.useCallback<SessionApiContext['logout']>(
|
const logout = React.useCallback<SessionApiContext['logout']>(
|
||||||
|
@ -280,16 +254,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
agent.pdsUrl = agent.api.xrpc.uri = new URL(account.pdsUrl)
|
agent.pdsUrl = agent.api.xrpc.uri = new URL(account.pdsUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
agent.setPersistSessionHandler(
|
agent.setPersistSessionHandler((event, session) => {
|
||||||
createPersistSessionHandler(
|
onAgentSessionChange(agent, account, event, session)
|
||||||
agent,
|
})
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount, expired)
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (IS_DEV && isWeb) window.agent = agent
|
if (IS_DEV && isWeb) window.agent = agent
|
||||||
|
@ -380,7 +347,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
return sessionAccount
|
return sessionAccount
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[upsertAccount, clearCurrentAccount, createPersistSessionHandler],
|
[upsertAccount, onAgentSessionChange],
|
||||||
)
|
)
|
||||||
|
|
||||||
const removeAccount = React.useCallback<SessionApiContext['removeAccount']>(
|
const removeAccount = React.useCallback<SessionApiContext['removeAccount']>(
|
||||||
|
|
Loading…
Reference in New Issue