Skip to content

Commit

Permalink
add support for confirmation callback
Browse files Browse the repository at this point in the history
  • Loading branch information
patrislav committed Dec 12, 2024
1 parent b03d183 commit 9ab8f14
Showing 1 changed file with 50 additions and 8 deletions.
58 changes: 50 additions & 8 deletions packages/waas/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ export class SequenceWaaS {
private validationRequiredCallback: (() => void)[] = []
private emailConflictCallback: ((info: EmailConflictInfo, forceCreate: () => Promise<void>) => Promise<void>)[] = []
private emailAuthCodeRequiredCallback: ((respondWithCode: (code: string) => Promise<void>) => Promise<void>)[] = []
private confirmationRequiredCallback: ((respondWithCode: (code: string) => Promise<void>) => Promise<void>)[] = []
private validationRequiredSalt: string
private lastConfirmationAttemptAt: Date | undefined

public readonly config: Required<SequenceConfig> & Required<WaaSConfigKey> & ExtendedSequenceConfig

Expand Down Expand Up @@ -315,6 +317,13 @@ export class SequenceWaaS {
}
}

onConfirmationRequired(callback: (respondWithCode: (code: string) => Promise<void>) => Promise<void>) {
this.confirmationRequiredCallback.push(callback)
return () => {
this.confirmationRequiredCallback = this.confirmationRequiredCallback.filter(c => c !== callback)
}
}

private async handleValidationRequired({ onValidationRequired }: ValidationArgs = {}): Promise<boolean> {
const proceed = onValidationRequired ? onValidationRequired() : true
if (!proceed) {
Expand All @@ -336,8 +345,42 @@ export class SequenceWaaS {
}

private async handleConfirmationRequired(response: ConfirmationRequiredResponse) {
const intent2 = await this.waas.confirmIntent(response.data.salt, "111111")
return intent2
if (this.confirmationRequiredCallback.length === 0) {
throw new Error('Missing confirmationRequired callback')
}

return new Promise((resolve, reject) => {
const respondToChallenge = async (answer: string) => {
if (this.lastConfirmationAttemptAt) {
const timeSinceLastAttempt = new Date().getTime() - this.lastConfirmationAttemptAt.getTime()
if (timeSinceLastAttempt < 32000) {
console.info(`Waiting ${Math.ceil((32000 - timeSinceLastAttempt) / 1000)}s before retrying confirmation attempt`)
await new Promise(resolve => setTimeout(resolve, 32000 - timeSinceLastAttempt))
}
}

this.lastConfirmationAttemptAt = new Date()

const intent = await this.waas.confirmIntent(response.data.salt, answer)

try {
const response2 = await this.sendIntent(intent)
resolve(response2)
} catch (e) {
if (e instanceof AnswerIncorrectError) {
// This will NOT resolve NOR reject the top-level promise returned from signIn, it'll keep being pending
// It allows the caller to retry calling the respondToChallenge callback
throw e
} else {
reject(e)
}
}
}

for (const callback of this.confirmationRequiredCallback) {
callback(respondToChallenge)
}
})
}

private headers() {
Expand Down Expand Up @@ -783,12 +826,11 @@ export class SequenceWaaS {
}

if (isConfirmationRequiredResponse(response)) {
const intent2 = await this.handleConfirmationRequired(response)
if (intent2) {
const response2 = await this.sendIntent(intent2)
if (isExpectedResponse(response2)) {
return response2
}
const response2 = await this.handleConfirmationRequired(response)
if (isExpectedResponse(response2)) {
return response2
} else {
throw new Error(JSON.stringify(response2))
}
}

Expand Down

0 comments on commit 9ab8f14

Please sign in to comment.