Clean up persistSession
This commit is contained in:
+78
-107
@@ -124,11 +124,6 @@ function agentToSessionAccount(agent: BskyAgent): SessionAccount | undefined {
|
|||||||
email: agent.session.email,
|
email: agent.session.email,
|
||||||
emailConfirmed: agent.session.emailConfirmed,
|
emailConfirmed: agent.session.emailConfirmed,
|
||||||
deactivated: isSessionDeactivated(agent.session.accessJwt),
|
deactivated: isSessionDeactivated(agent.session.accessJwt),
|
||||||
|
|
||||||
/*
|
|
||||||
* Tokens are undefined if the session expires, or if creation fails for
|
|
||||||
* any reason e.g. tokens are invalid, network error, etc.
|
|
||||||
*/
|
|
||||||
refreshJwt: agent.session.refreshJwt,
|
refreshJwt: agent.session.refreshJwt,
|
||||||
accessJwt: agent.session.accessJwt,
|
accessJwt: agent.session.accessJwt,
|
||||||
}
|
}
|
||||||
@@ -147,70 +142,6 @@ function sessionAccountToAgentSession(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPersistSessionHandler(
|
|
||||||
account: SessionAccount,
|
|
||||||
persistSessionCallback: (props: {
|
|
||||||
expired: boolean
|
|
||||||
refreshedAccount: SessionAccount
|
|
||||||
}) => void,
|
|
||||||
{
|
|
||||||
networkErrorCallback,
|
|
||||||
}: {
|
|
||||||
networkErrorCallback?: () => void
|
|
||||||
} = {},
|
|
||||||
): AtpPersistSessionHandler {
|
|
||||||
return function persistSession(event, session) {
|
|
||||||
const expired = event === 'expired' || event === 'create-failed'
|
|
||||||
|
|
||||||
if (event === 'network-error') {
|
|
||||||
logger.warn(`session: persistSessionHandler received network-error event`)
|
|
||||||
networkErrorCallback?.()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const refreshedAccount: SessionAccount = {
|
|
||||||
service: account.service,
|
|
||||||
did: session?.did || account.did,
|
|
||||||
handle: session?.handle || account.handle,
|
|
||||||
email: session?.email || account.email,
|
|
||||||
emailConfirmed: session?.emailConfirmed || account.emailConfirmed,
|
|
||||||
deactivated: isSessionDeactivated(session?.accessJwt),
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
persistSessionCallback({
|
|
||||||
expired,
|
|
||||||
refreshedAccount,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const isDirty = React.useRef(false)
|
const isDirty = React.useRef(false)
|
||||||
const [agent, setAgent] = React.useState<BskyAgent>(PUBLIC_BSKY_AGENT)
|
const [agent, setAgent] = React.useState<BskyAgent>(PUBLIC_BSKY_AGENT)
|
||||||
@@ -248,6 +179,62 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
BskyAgent.configure({appLabelers: [BSKY_LABELER_DID]})
|
BskyAgent.configure({appLabelers: [BSKY_LABELER_DID]})
|
||||||
}, [persistNextUpdate, setAgent])
|
}, [persistNextUpdate, setAgent])
|
||||||
|
|
||||||
|
const persistSession = React.useCallback<
|
||||||
|
(agent: BskyAgent) => AtpPersistSessionHandler
|
||||||
|
>(
|
||||||
|
agent => {
|
||||||
|
return (event, session) => {
|
||||||
|
logger.debug(
|
||||||
|
`session: persistSession`,
|
||||||
|
{event},
|
||||||
|
logger.DebugContext.session,
|
||||||
|
)
|
||||||
|
|
||||||
|
const expired = event === 'expired' || event === 'create-failed'
|
||||||
|
|
||||||
|
if (event === 'network-error') {
|
||||||
|
logger.warn(
|
||||||
|
`session: persistSessionHandler received network-error event`,
|
||||||
|
)
|
||||||
|
emitSessionDropped()
|
||||||
|
clearCurrentAccount()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
agent.session = session
|
||||||
|
const refreshedAccount = agentToSessionAccount(agent)
|
||||||
|
|
||||||
|
if (!refreshedAccount) {
|
||||||
|
logger.error(
|
||||||
|
`session: persistSession failed to get refreshed account`,
|
||||||
|
)
|
||||||
|
emitSessionDropped()
|
||||||
|
clearCurrentAccount()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
logger.warn(`session: expired`)
|
||||||
|
emitSessionDropped()
|
||||||
|
clearCurrentAccount()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[clearCurrentAccount, upsertAccount],
|
||||||
|
)
|
||||||
|
|
||||||
const createAccount = React.useCallback<ApiContext['createAccount']>(
|
const createAccount = React.useCallback<ApiContext['createAccount']>(
|
||||||
async ({
|
async ({
|
||||||
service,
|
service,
|
||||||
@@ -296,16 +283,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
await configureModeration(agent, account)
|
await configureModeration(agent, account)
|
||||||
|
|
||||||
agent.setPersistSessionHandler(
|
agent.setPersistSessionHandler(persistSession(agent))
|
||||||
createPersistSessionHandler(
|
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount)
|
|
||||||
if (expired) clearCurrentAccount()
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
setAgent(agent)
|
setAgent(agent)
|
||||||
upsertAccount(account)
|
upsertAccount(account)
|
||||||
@@ -314,7 +292,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
track('Create Account')
|
track('Create Account')
|
||||||
logEvent('account:create:success', {})
|
logEvent('account:create:success', {})
|
||||||
},
|
},
|
||||||
[upsertAccount, clearCurrentAccount],
|
[upsertAccount, persistSession],
|
||||||
)
|
)
|
||||||
|
|
||||||
const login = React.useCallback<ApiContext['login']>(
|
const login = React.useCallback<ApiContext['login']>(
|
||||||
@@ -331,16 +309,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
const account = agentToSessionAccount(agent)!
|
const account = agentToSessionAccount(agent)!
|
||||||
await configureModeration(agent, account)
|
await configureModeration(agent, account)
|
||||||
|
|
||||||
agent.setPersistSessionHandler(
|
agent.setPersistSessionHandler(persistSession(agent))
|
||||||
createPersistSessionHandler(
|
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount)
|
|
||||||
if (expired) clearCurrentAccount()
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
setAgent(agent)
|
setAgent(agent)
|
||||||
upsertAccount(account)
|
upsertAccount(account)
|
||||||
@@ -350,7 +319,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],
|
[upsertAccount, persistSession],
|
||||||
)
|
)
|
||||||
|
|
||||||
const logout = React.useCallback<ApiContext['logout']>(
|
const logout = React.useCallback<ApiContext['logout']>(
|
||||||
@@ -378,15 +347,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
const agent = new BskyAgent({
|
const agent = new BskyAgent({
|
||||||
service: account.service,
|
service: account.service,
|
||||||
persistSession: createPersistSessionHandler(
|
|
||||||
account,
|
|
||||||
({expired, refreshedAccount}) => {
|
|
||||||
upsertAccount(refreshedAccount)
|
|
||||||
if (expired) clearCurrentAccount()
|
|
||||||
},
|
|
||||||
{networkErrorCallback: clearCurrentAccount},
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
|
agent.setPersistSessionHandler(persistSession(agent))
|
||||||
|
|
||||||
const prevSession = {
|
const prevSession = {
|
||||||
...account,
|
...account,
|
||||||
@@ -437,7 +399,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[upsertAccount, clearCurrentAccount],
|
[upsertAccount, clearCurrentAccount, persistSession],
|
||||||
)
|
)
|
||||||
|
|
||||||
const resumeSession = React.useCallback<ApiContext['resumeSession']>(
|
const resumeSession = React.useCallback<ApiContext['resumeSession']>(
|
||||||
@@ -504,10 +466,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
return persisted.onUpdate(async () => {
|
return persisted.onUpdate(async () => {
|
||||||
const persistedSession = persisted.get('session')
|
const persistedSession = persisted.get('session')
|
||||||
|
|
||||||
logger.debug(`session: persisted onUpdate`, {
|
logger.debug(
|
||||||
persistedCurrentAccount: persistedSession.currentAccount,
|
`session: persisted onUpdate`,
|
||||||
currentAccount,
|
{},
|
||||||
})
|
logger.DebugContext.session,
|
||||||
|
)
|
||||||
|
|
||||||
setAccounts(persistedSession.accounts)
|
setAccounts(persistedSession.accounts)
|
||||||
|
|
||||||
@@ -516,7 +479,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
persistedSession.currentAccount.refreshJwt
|
persistedSession.currentAccount.refreshJwt
|
||||||
) {
|
) {
|
||||||
if (persistedSession.currentAccount?.did !== currentAccount?.did) {
|
if (persistedSession.currentAccount?.did !== currentAccount?.did) {
|
||||||
logger.debug(`session: persisted onUpdate, switching accounts`, {
|
logger.debug(
|
||||||
|
`session: persisted onUpdate, switching accounts`,
|
||||||
|
{
|
||||||
from: {
|
from: {
|
||||||
did: currentAccount?.did,
|
did: currentAccount?.did,
|
||||||
handle: currentAccount?.handle,
|
handle: currentAccount?.handle,
|
||||||
@@ -525,11 +490,17 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
did: persistedSession.currentAccount.did,
|
did: persistedSession.currentAccount.did,
|
||||||
handle: persistedSession.currentAccount.handle,
|
handle: persistedSession.currentAccount.handle,
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
logger.DebugContext.session,
|
||||||
|
)
|
||||||
|
|
||||||
await initSession(persistedSession.currentAccount)
|
await initSession(persistedSession.currentAccount)
|
||||||
} else {
|
} else {
|
||||||
logger.debug(`session: persisted onUpdate, updating session`, {})
|
logger.debug(
|
||||||
|
`session: persisted onUpdate, updating session`,
|
||||||
|
{},
|
||||||
|
logger.DebugContext.session,
|
||||||
|
)
|
||||||
agent.session = sessionAccountToAgentSession(
|
agent.session = sessionAccountToAgentSession(
|
||||||
persistedSession.currentAccount,
|
persistedSession.currentAccount,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user