From 842cc327541ebcfc761208f42bf5f74e22c6283c Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 5 Nov 2021 16:07:57 +0100 Subject: anastasis-core: support poll transition --- .../anastasis-core/src/challenge-feedback-types.ts | 19 ++++++++ packages/anastasis-core/src/index.ts | 57 +++++++++++++++++++++- packages/anastasis-core/src/provider-types.ts | 13 ++++- packages/anastasis-core/src/reducer-types.ts | 1 + 4 files changed, 87 insertions(+), 3 deletions(-) (limited to 'packages/anastasis-core/src') diff --git a/packages/anastasis-core/src/challenge-feedback-types.ts b/packages/anastasis-core/src/challenge-feedback-types.ts index d6a2e3e80..0770d9296 100644 --- a/packages/anastasis-core/src/challenge-feedback-types.ts +++ b/packages/anastasis-core/src/challenge-feedback-types.ts @@ -80,6 +80,25 @@ export interface ChallengeFeedbackAuthIban { * be contained in the bank transfer. */ wire_transfer_subject: string; + + /** + * FIXME: This field is only present for compatibility with + * the C reducer test suite. + */ + method: "iban"; + + answer_code: number; + + /** + * FIXME: This field is only present for compatibility with + * the C reducer test suite. + */ + details: { + challenge_amount: AmountString; + credit_iban: string; + business_name: string; + wire_transfer_subject: string; + }; } /** diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts index d3e938f0f..362ac3317 100644 --- a/packages/anastasis-core/src/index.ts +++ b/packages/anastasis-core/src/index.ts @@ -25,6 +25,7 @@ import { import { anastasisData } from "./anastasis-data.js"; import { EscrowConfigurationResponse, + IbanExternalAuthResponse, TruthUploadRequest, } from "./provider-types.js"; import { @@ -809,6 +810,39 @@ async function tryRecoverSecret( return { ...state }; } +/** + * Re-check the status of challenges that are solved asynchronously. + */ +async function pollChallenges( + state: ReducerStateRecovery, + args: void, +): Promise { + for (const truthUuid in state.challenge_feedback) { + if (state.recovery_state === RecoveryStates.RecoveryFinished) { + break; + } + const feedback = state.challenge_feedback[truthUuid]; + const truth = state.verbatim_recovery_document!.escrow_methods.find( + (x) => x.uuid === truthUuid, + ); + if (!truth) { + logger.warn( + "truth for challenge feedback entry not found in recovery document", + ); + continue; + } + if (feedback.state === ChallengeFeedbackStatus.AuthIban) { + const s2 = await requestTruth(state, truth, { + pin: feedback.answer_code, + }); + if (s2.recovery_state) { + state = s2; + } + } + } + return state; +} + /** * Request a truth, optionally with a challenge solution * provided by the user. @@ -839,6 +873,7 @@ async function requestTruth( case ChallengeType.Email: case ChallengeType.Sms: case ChallengeType.Post: + case ChallengeType.Iban: case ChallengeType.Totp: { if ("answer" in solveRequest) { const s = solveRequest.answer.trim().replace(/^A-/, ""); @@ -857,7 +892,7 @@ async function requestTruth( break; } default: - throw Error("unsupported challenge type"); + throw Error(`unsupported challenge type "${truth.escrow_type}""`); } url.searchParams.set("response", respHash); } @@ -934,7 +969,24 @@ async function requestTruth( const body = await resp.json(); logger.info(`got body ${j2s(body)}`); if (body.method === "iban") { - // FIXME: + const b = body as IbanExternalAuthResponse; + return { + ...state, + recovery_state: RecoveryStates.ChallengeSolving, + challenge_feedback: { + ...state.challenge_feedback, + [truth.uuid]: { + state: ChallengeFeedbackStatus.AuthIban, + answer_code: b.answer_code, + business_name: b.details.business_name, + challenge_amount: b.details.challenge_amount, + credit_iban: b.details.credit_iban, + wire_transfer_subject: b.details.wire_transfer_subject, + details: b.details, + method: "iban", + }, + }, + }; } else { return { code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED, @@ -1395,6 +1447,7 @@ const recoveryTransitions: Record< codecForActionArgsSelectChallenge(), selectChallenge, ), + ...transition("poll", codecForAny(), pollChallenges), ...transition("next", codecForAny(), nextFromChallengeSelecting), }, [RecoveryStates.ChallengeSolving]: { diff --git a/packages/anastasis-core/src/provider-types.ts b/packages/anastasis-core/src/provider-types.ts index b477c09b9..f4d998e0a 100644 --- a/packages/anastasis-core/src/provider-types.ts +++ b/packages/anastasis-core/src/provider-types.ts @@ -1,4 +1,4 @@ -import { AmountString } from "@gnu-taler/taler-util"; +import { Amounts, AmountString } from "@gnu-taler/taler-util"; export interface EscrowConfigurationResponse { // Protocol identifier, clarifies that this is an Anastasis provider. @@ -72,3 +72,14 @@ export interface TruthUploadRequest { // store the truth? storage_duration_years: number; } + +export interface IbanExternalAuthResponse { + method: "iban"; + answer_code: number; + details: { + challenge_amount: AmountString; + credit_iban: string; + business_name: string; + wire_transfer_subject: string; + }; +} diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts index 1a560b885..0f64be4eb 100644 --- a/packages/anastasis-core/src/reducer-types.ts +++ b/packages/anastasis-core/src/reducer-types.ts @@ -6,6 +6,7 @@ import { codecForNumber, codecForString, codecForTimestamp, + Duration, Timestamp, } from "@gnu-taler/taler-util"; import { ChallengeFeedback } from "./challenge-feedback-types.js"; -- cgit v1.2.3