import { ChallengeFeedback, ChallengeFeedbackStatus, } from "@gnu-taler/anastasis-core"; import { h, VNode } from "preact"; import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisClientFrame } from "./index"; import { authMethods, KnownAuthMethods } from "./authMethod"; import { AsyncButton } from "../../components/AsyncButton"; function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) { const { feedback } = props; if (!feedback) { return null; } switch (feedback.state) { case ChallengeFeedbackStatus.Message: return
{feedback.message}
; case ChallengeFeedbackStatus.Solved: return
; case ChallengeFeedbackStatus.Pending: case ChallengeFeedbackStatus.AuthIban: return null; case ChallengeFeedbackStatus.ServerFailure: return
Server error.
; case ChallengeFeedbackStatus.RateLimitExceeded: return (
There were to many failed attempts.
); case ChallengeFeedbackStatus.Unsupported: return (
This client doesn't support solving this type of challenge. Use another version or contact the provider.
); case ChallengeFeedbackStatus.TruthUnknown: return (
Provider doesn't recognize the challenge of the policy. Contact the provider for further information.
); case ChallengeFeedbackStatus.Redirect: default: return
; } } export function ChallengeOverviewScreen(): VNode { const reducer = useAnastasisContext(); if (!reducer) { return
no reducer in context
; } if ( !reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined ) { return
invalid state
; } const policies = reducer.currentReducerState.recovery_information?.policies ?? []; const knownChallengesArray = reducer.currentReducerState.recovery_information?.challenges ?? []; const challengeFeedback = reducer.currentReducerState?.challenge_feedback ?? {}; const knownChallengesMap: { [uuid: string]: { type: string; instructions: string; cost: string; feedback: ChallengeFeedback | undefined; }; } = {}; for (const ch of knownChallengesArray) { knownChallengesMap[ch.uuid] = { type: ch.type, cost: ch.cost, instructions: ch.instructions, feedback: challengeFeedback[ch.uuid], }; } const policiesWithInfo = policies .map((row) => { let isPolicySolved = true; const challenges = row .map(({ uuid }) => { const info = knownChallengesMap[uuid]; const isChallengeSolved = info?.feedback?.state === "solved"; isPolicySolved = isPolicySolved && isChallengeSolved; return { info, uuid, isChallengeSolved }; }) .filter((ch) => ch.info !== undefined); return { isPolicySolved, challenges, corrupted: row.length > challenges.length, }; }) .filter((p) => !p.corrupted); const atLeastThereIsOnePolicySolved = policiesWithInfo.find((p) => p.isPolicySolved) !== undefined; const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined; return ( {!policiesWithInfo.length ? (

No policies found, try with another version of the secret

) : policiesWithInfo.length === 1 ? (

One policy found for this secret. You need to solve all the challenges in order to recover your secret.

) : (

We have found {policiesWithInfo.length} polices. You need to solve all the challenges from one policy in order to recover your secret.

)} {policiesWithInfo.map((policy, policy_index) => { const tableBody = policy.challenges.map(({ info, uuid }) => { const isFree = !info.cost || info.cost.endsWith(":0"); const method = authMethods[info.type as KnownAuthMethods]; if (!method) { return (
unknown challenge
); } function ChallengeButton({ id, feedback, }: { id: string; feedback?: ChallengeFeedback; }): VNode { async function selectChallenge(): Promise { if (reducer) { return reducer.transition("select_challenge", { uuid: id }); } } if (!feedback) { return (
Solve
); } switch (feedback.state) { case ChallengeFeedbackStatus.ServerFailure: case ChallengeFeedbackStatus.Unsupported: case ChallengeFeedbackStatus.TruthUnknown: case ChallengeFeedbackStatus.RateLimitExceeded: return
; case ChallengeFeedbackStatus.AuthIban: case ChallengeFeedbackStatus.Payment: return (
Pay
); case ChallengeFeedbackStatus.Redirect: return (
Go to {feedback.redirect_url}
); case ChallengeFeedbackStatus.Solved: return (
Solved
); default: return (
Solve
); } } return (
{method?.icon} {info.instructions}
); }); const policyName = policy.challenges .map((x) => x.info.type) .join(" + "); const opa = !atLeastThereIsOnePolicySolved ? undefined : policy.isPolicySolved ? undefined : "0.6"; return (

Policy #{policy_index + 1}: {policyName}

{policy.challenges.length === 0 && (

This policy doesn't have challenges.

)} {policy.challenges.length === 1 && (

This policy just have one challenge.

)} {policy.challenges.length > 1 && (

This policy have {policy.challenges.length} challenges.

)} {tableBody}
); })} ); }