gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 01/02: anastasis-webui: updated challenge feedback


From: gnunet
Subject: [taler-wallet-core] 01/02: anastasis-webui: updated challenge feedback
Date: Wed, 13 Apr 2022 23:46:38 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit 4e1fe5eb10a5db44c86becbcef66daacc408239d
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Apr 13 21:40:56 2022 +0200

    anastasis-webui: updated challenge feedback
---
 .../anastasis-core/src/challenge-feedback-types.ts | 109 ++++++++--------
 packages/anastasis-core/src/index.ts               | 139 ++++++++++++++++-----
 packages/anastasis-core/src/provider-types.ts      |  90 +++++++++++++
 packages/anastasis-core/src/reducer-types.ts       |   2 -
 packages/anastasis-webui/package.json              |   3 +-
 .../src/hooks/use-anastasis-reducer.ts             |  20 ++-
 .../pages/home/AddingProviderScreen.stories.tsx    |   8 --
 .../pages/home/ChallengeOverviewScreen.stories.tsx |  15 +--
 .../src/pages/home/ChallengeOverviewScreen.tsx     |  20 +--
 .../anastasis-webui/src/pages/home/SolveScreen.tsx |  35 +-----
 .../authMethod/AuthMethodEmailSolve.stories.tsx    |   2 +-
 .../pages/home/authMethod/AuthMethodEmailSolve.tsx |   9 +-
 .../pages/home/authMethod/AuthMethodIbanSolve.tsx  |  10 +-
 .../pages/home/authMethod/AuthMethodPostSolve.tsx  |   9 +-
 .../authMethod/AuthMethodQuestionSolve.stories.tsx |  77 ++----------
 .../home/authMethod/AuthMethodQuestionSolve.tsx    |   9 +-
 .../pages/home/authMethod/AuthMethodSmsSolve.tsx   |   9 +-
 .../pages/home/authMethod/AuthMethodTotpSolve.tsx  |   9 +-
 .../authMethod/AuthMethodVideoSetup.stories.tsx    |  83 ------------
 .../pages/home/authMethod/AuthMethodVideoSetup.tsx |  92 --------------
 .../authMethod/AuthMethodVideoSolve.stories.tsx    |  63 ----------
 .../pages/home/authMethod/AuthMethodVideoSolve.tsx | 114 -----------------
 .../src/pages/home/authMethod/helpers.ts           |  12 ++
 .../src/pages/home/authMethod/index.tsx            |  21 +---
 packages/taler-util/src/payto.ts                   |  86 +++++++------
 pnpm-lock.yaml                                     |  11 ++
 26 files changed, 372 insertions(+), 685 deletions(-)

diff --git a/packages/anastasis-core/src/challenge-feedback-types.ts 
b/packages/anastasis-core/src/challenge-feedback-types.ts
index 0770d929..30f42288 100644
--- a/packages/anastasis-core/src/challenge-feedback-types.ts
+++ b/packages/anastasis-core/src/challenge-feedback-types.ts
@@ -1,29 +1,48 @@
+/*
+ This file is part of GNU Anastasis
+ (C) 2021-2022 Anastasis SARL
+
+ GNU Anastasis is free software; you can redistribute it and/or modify it 
under the
+ terms of the GNU Affero General Public License as published by the Free 
Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT 
ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more 
details.
+
+ You should have received a copy of the GNU Affero General Public License 
along with
+ GNU Anastasis; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
 import { AmountString, HttpStatusCode } from "@gnu-taler/taler-util";
 
 export enum ChallengeFeedbackStatus {
   Solved = "solved",
+  CodeInFile = "code-in-file",
+  CodeSent = "code-sent",
   ServerFailure = "server-failure",
   TruthUnknown = "truth-unknown",
-  Redirect = "redirect",
-  Payment = "payment",
-  Pending = "pending",
-  Message = "message",
+  TalerPayment = "taler-payment",
   Unsupported = "unsupported",
   RateLimitExceeded = "rate-limit-exceeded",
   AuthIban = "auth-iban",
+  IncorrectAnswer = "incorrect-answer",
 }
 
 export type ChallengeFeedback =
   | ChallengeFeedbackSolved
-  | ChallengeFeedbackPending
-  | ChallengeFeedbackPayment
+  | ChallengeFeedbackCodeInFile
+  | ChallengeFeedbackCodeSent
+  | ChallengeFeedbackIncorrectAnswer
+  | ChallengeFeedbackTalerPaymentRequired
   | ChallengeFeedbackServerFailure
   | ChallengeFeedbackRateLimitExceeded
   | ChallengeFeedbackTruthUnknown
-  | ChallengeFeedbackRedirect
-  | ChallengeFeedbackMessage
   | ChallengeFeedbackUnsupported
-  | ChallengeFeedbackAuthIban;
+  | ChallengeFeedbackBankTransferRequired;
 
 /**
  * Challenge has been solved and the key share has
@@ -33,13 +52,29 @@ export interface ChallengeFeedbackSolved {
   state: ChallengeFeedbackStatus.Solved;
 }
 
+export interface ChallengeFeedbackIncorrectAnswer {
+  state: ChallengeFeedbackStatus.IncorrectAnswer;
+}
+
+export interface ChallengeFeedbackCodeInFile {
+  state: ChallengeFeedbackStatus.CodeInFile;
+  filename: string;
+  display_hint: string;
+}
+
+export interface ChallengeFeedbackCodeSent {
+  state: ChallengeFeedbackStatus.CodeSent;
+  display_hint: string;
+  address_hint: string;
+}
+
 /**
  * The challenge given by the server is unsupported
  * by the current anastasis client.
  */
 export interface ChallengeFeedbackUnsupported {
   state: ChallengeFeedbackStatus.Unsupported;
-  http_status: HttpStatusCode;
+
   /**
    * Human-readable identifier of the unsupported method.
    */
@@ -57,7 +92,7 @@ export interface ChallengeFeedbackRateLimitExceeded {
  * Instructions for performing authentication via an
  * IBAN bank transfer.
  */
-export interface ChallengeFeedbackAuthIban {
+export interface ChallengeFeedbackBankTransferRequired {
   state: ChallengeFeedbackStatus.AuthIban;
 
   /**
@@ -68,12 +103,12 @@ export interface ChallengeFeedbackAuthIban {
   /**
    * Account that should be credited.
    */
-  credit_iban: string;
+  target_iban: string;
 
   /**
    * Creditor name.
    */
-  business_name: string;
+  target_business_name: string;
 
   /**
    * Unstructured remittance information that should
@@ -81,41 +116,7 @@ export interface ChallengeFeedbackAuthIban {
    */
   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;
-  };
-}
-
-/**
- * Challenge still needs to be solved.
- */
-export interface ChallengeFeedbackPending {
-  state: ChallengeFeedbackStatus.Pending;
-}
-
-/**
- * Human-readable response from the provider
- * after the user failed to solve the challenge
- * correctly.
- */
-export interface ChallengeFeedbackMessage {
-  state: ChallengeFeedbackStatus.Message;
-  message: string;
 }
 
 /**
@@ -140,22 +141,12 @@ export interface ChallengeFeedbackTruthUnknown {
   state: ChallengeFeedbackStatus.TruthUnknown;
 }
 
-/**
- * The user should be asked to go to a URL
- * to complete the authentication there.
- */
-export interface ChallengeFeedbackRedirect {
-  state: ChallengeFeedbackStatus.Redirect;
-  http_status: number;
-  redirect_url: string;
-}
-
 /**
  * A payment is required before the user can
  * even attempt to solve the challenge.
  */
-export interface ChallengeFeedbackPayment {
-  state: ChallengeFeedbackStatus.Payment;
+export interface ChallengeFeedbackTalerPaymentRequired {
+  state: ChallengeFeedbackStatus.TalerPayment;
 
   taler_pay_uri: string;
 
diff --git a/packages/anastasis-core/src/index.ts 
b/packages/anastasis-core/src/index.ts
index 98aba2ce..055f3fb6 100644
--- a/packages/anastasis-core/src/index.ts
+++ b/packages/anastasis-core/src/index.ts
@@ -25,6 +25,7 @@ import {
 } from "@gnu-taler/taler-util";
 import { anastasisData } from "./anastasis-data.js";
 import {
+  codecForChallengeInstructionMessage,
   EscrowConfigurationResponse,
   RecoveryMetaResponse,
   TruthUploadRequest,
@@ -363,9 +364,10 @@ async function getTruthValue(
     case "email":
     case "totp":
     case "iban":
+    case "post":
       return authMethod.challenge;
     default:
-      throw Error("unknown auth type");
+      throw Error(`unknown auth type '${authMethod.type}'`);
   }
 }
 
@@ -947,17 +949,27 @@ async function requestTruth(
 
   const hresp = await getResponseHash(truth, solveRequest);
 
-  const resp = await fetch(url.href, {
-    method: "POST",
-    headers: {
-      Accept: "application/json",
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify({
-      truth_decryption_key: truth.truth_key,
-      h_response: hresp,
-    }),
-  });
+  let resp: Response;
+
+  try {
+    resp = await fetch(url.href, {
+      method: "POST",
+      headers: {
+        Accept: "application/json",
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({
+        truth_decryption_key: truth.truth_key,
+        h_response: hresp,
+      }),
+    });
+  } catch (e) {
+    return {
+      reducer_type: "error",
+      code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED,
+      hint: "network error",
+    } as ReducerStateError;
+  }
 
   logger.info(
     `got POST /truth/.../solve response from ${truth.url}, http status 
${resp.status}`,
@@ -1007,6 +1019,19 @@ async function requestTruth(
     return tryRecoverSecret(newState);
   }
 
+  if (resp.status === HttpStatusCode.Forbidden) {
+    const challengeFeedback: { [x: string]: ChallengeFeedback } = {
+      ...state.challenge_feedback,
+      [truth.uuid]: {
+        state: ChallengeFeedbackStatus.IncorrectAnswer,
+      },
+    };
+    return {
+      ...state,
+      challenge_feedback: challengeFeedback,
+    };
+  }
+
   return {
     reducer_type: "error",
     code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED,
@@ -1072,6 +1097,9 @@ async function selectChallenge(
 
   const url = new URL(`/truth/${truth.uuid}/challenge`, truth.url);
 
+  const newFeedback = { ...state.challenge_feedback };
+  delete newFeedback[truth.uuid];
+
   switch (truth.escrow_type) {
     case ChallengeType.Question:
     case ChallengeType.Totp: {
@@ -1079,51 +1107,93 @@ async function selectChallenge(
         ...state,
         recovery_state: RecoveryStates.ChallengeSolving,
         selected_challenge_uuid: truth.uuid,
-        challenge_feedback: {
-          ...state.challenge_feedback,
-          [truth.uuid]: {
-            state: ChallengeFeedbackStatus.Pending,
-          },
-        },
+        challenge_feedback: newFeedback,
       };
     }
   }
 
-  const resp = await fetch(url.href, {
-    method: "POST",
-    headers: {
-      Accept: "application/json",
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify({
-      truth_decryption_key: truth.truth_key,
-    }),
-  });
+  let resp: Response;
+
+  try {
+    resp = await fetch(url.href, {
+      method: "POST",
+      headers: {
+        Accept: "application/json",
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({
+        truth_decryption_key: truth.truth_key,
+      }),
+    });
+  } catch (e) {
+    const feedback: ChallengeFeedback = {
+      state: ChallengeFeedbackStatus.ServerFailure,
+      http_status: 0,
+    };
+    return {
+      ...state,
+      recovery_state: RecoveryStates.ChallengeSelecting,
+      selected_challenge_uuid: truth.uuid,
+      challenge_feedback: {
+        ...state.challenge_feedback,
+        [truth.uuid]: feedback,
+      },
+    };
+  }
 
   logger.info(
     `got GET /truth/.../challenge response from ${truth.url}, http status 
${resp.status}`,
   );
 
   if (resp.status === HttpStatusCode.Ok) {
+    const respBodyJson = await resp.json();
+    const instr = codecForChallengeInstructionMessage().decode(respBodyJson);
+    let feedback: ChallengeFeedback;
+    switch (instr.method) {
+      case "FILE_WRITTEN": {
+        feedback = {
+          state: ChallengeFeedbackStatus.CodeInFile,
+          display_hint: "TAN code is in file (for debugging)",
+          filename: instr.filename,
+        };
+        break;
+      }
+      case "IBAN_WIRE": {
+        feedback = {
+          state: ChallengeFeedbackStatus.AuthIban,
+          answer_code: instr.answer_code,
+          target_business_name: instr.business_name,
+          challenge_amount: instr.amount,
+          target_iban: instr.credit_iban,
+          wire_transfer_subject: instr.wire_transfer_subject,
+        };
+        break;
+      }
+      case "TAN_SENT": {
+        feedback = {
+          state: ChallengeFeedbackStatus.CodeSent,
+          address_hint: instr.tan_address_hint,
+          display_hint: "Code sent to address",
+        };
+      }
+    }
     return {
       ...state,
       recovery_state: RecoveryStates.ChallengeSolving,
       selected_challenge_uuid: truth.uuid,
       challenge_feedback: {
         ...state.challenge_feedback,
-        [truth.uuid]: {
-          state: ChallengeFeedbackStatus.Pending,
-        },
+        [truth.uuid]: feedback,
       },
     };
   }
 
-  // FIXME: look at response, include in challenge_feedback!
+  // FIXME: look at more error codes in response
 
   return {
     reducer_type: "error",
     code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED,
-    hint: "got unexpected /truth/.../challenge response status",
+    hint: `got unexpected /truth/.../challenge response status 
(${resp.status})`,
     http_status: resp.status,
   } as ReducerStateError;
 }
@@ -1727,8 +1797,9 @@ export async function reduceAction(
   }
   try {
     return await h.handler(state, parsedArgs);
-  } catch (e) {
+  } catch (e: any) {
     logger.error("action handler failed");
+    logger.error(`${e?.stack ?? e}`);
     if (e instanceof ReducerError) {
       return {
         reducer_type: "error",
diff --git a/packages/anastasis-core/src/provider-types.ts 
b/packages/anastasis-core/src/provider-types.ts
index 72f2dc6e..4da62fc0 100644
--- a/packages/anastasis-core/src/provider-types.ts
+++ b/packages/anastasis-core/src/provider-types.ts
@@ -16,6 +16,13 @@
 
 import {
   AmountString,
+  buildCodecForObject,
+  buildCodecForUnion,
+  Codec,
+  codecForAmountString,
+  codecForConstString,
+  codecForNumber,
+  codecForString,
   TalerProtocolTimestamp,
 } from "@gnu-taler/taler-util";
 
@@ -122,3 +129,86 @@ export interface RecoveryMetaDataItem {
   // document was uploaded.
   upload_time: TalerProtocolTimestamp;
 }
+
+export type ChallengeInstructionMessage =
+  | FileChallengeInstructionMessage
+  | IbanChallengeInstructionMessage
+  | PinChallengeInstructionMessage;
+
+export interface IbanChallengeInstructionMessage {
+  // What kind of challenge is this?
+  method: "IBAN_WIRE";
+
+  // How much should be wired?
+  amount: AmountString;
+
+  // What is the target IBAN?
+  credit_iban: string;
+
+  // What is the receiver name?
+  business_name: string;
+
+  // What is the expected wire transfer subject?
+  wire_transfer_subject: string;
+
+  // What is the numeric code (also part of the
+  // wire transfer subject) to be hashed when
+  // solving the challenge?
+  answer_code: number;
+
+  // Hint about the origin account that must be used.
+  debit_account_hint: string;
+}
+
+export interface PinChallengeInstructionMessage {
+  // What kind of challenge is this?
+  method: "TAN_SENT";
+
+  // Where was the PIN code sent? Note that this
+  // address will most likely have been obscured
+  // to improve privacy.
+  tan_address_hint: string;
+}
+
+export interface FileChallengeInstructionMessage {
+  // What kind of challenge is this?
+  method: "FILE_WRITTEN";
+
+  // Name of the file where the PIN code was written.
+  filename: string;
+}
+
+export const codecForFileChallengeInstructionMessage =
+  (): Codec<FileChallengeInstructionMessage> =>
+    buildCodecForObject<FileChallengeInstructionMessage>()
+      .property("method", codecForConstString("FILE_WRITTEN"))
+      .property("filename", codecForString())
+      .build("FileChallengeInstructionMessage");
+
+export const codecForPinChallengeInstructionMessage =
+  (): Codec<PinChallengeInstructionMessage> =>
+    buildCodecForObject<PinChallengeInstructionMessage>()
+      .property("method", codecForConstString("TAN_SENT"))
+      .property("tan_address_hint", codecForString())
+      .build("PinChallengeInstructionMessage");
+
+export const codecForIbanChallengeInstructionMessage =
+  (): Codec<IbanChallengeInstructionMessage> =>
+    buildCodecForObject<IbanChallengeInstructionMessage>()
+      .property("method", codecForConstString("IBAN_WIRE"))
+      .property("amount", codecForAmountString())
+      .property("business_name", codecForString())
+      .property("credit_iban", codecForString())
+      .property("wire_transfer_subject", codecForString())
+      .property("answer_code", codecForNumber())
+      .property("debit_account_hint", codecForString())
+      .build("IbanChallengeInstructionMessage");
+
+export const codecForChallengeInstructionMessage =
+  (): Codec<ChallengeInstructionMessage> =>
+    buildCodecForUnion<ChallengeInstructionMessage>()
+      .discriminateOn("method")
+      .alternative("FILE_WRITTEN", codecForFileChallengeInstructionMessage())
+      .alternative("IBAN_WIRE", codecForIbanChallengeInstructionMessage())
+      .alternative("TAN_SENT", codecForPinChallengeInstructionMessage())
+      .build("ChallengeInstructionMessage");
diff --git a/packages/anastasis-core/src/reducer-types.ts 
b/packages/anastasis-core/src/reducer-types.ts
index 5b5f4029..b7e3148c 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -220,8 +220,6 @@ export interface ReducerStateRecovery {
 
   /**
    * Explicitly selected version by the user.
-   * FIXME: In the C reducer this is called "version".
-   * FIXME: rename to selected_secret / selected_policy?
    */
   selected_version?: AggregatedPolicyMetaInfo;
 
diff --git a/packages/anastasis-webui/package.json 
b/packages/anastasis-webui/package.json
index 2327b5e1..a855ffa9 100644
--- a/packages/anastasis-webui/package.json
+++ b/packages/anastasis-webui/package.json
@@ -15,7 +15,6 @@
     "pretty": "prettier --write src",
     "storybook": "start-storybook -p 6006"
   },
-  "type": "module",
   "eslintConfig": {
     "parser": "@typescript-eslint/parser",
     "extends": [
@@ -62,4 +61,4 @@
     "sirv-cli": "^1.0.14",
     "typescript": "^4.5.4"
   }
-}
\ No newline at end of file
+}
diff --git a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts 
b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
index 7274c3d0..434e5fb0 100644
--- a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
+++ b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
@@ -1,3 +1,22 @@
+/*
+ This file is part of GNU Anastasis
+ (C) 2021-2022 Anastasis SARL
+
+ GNU Anastasis is free software; you can redistribute it and/or modify it 
under the
+ terms of the GNU Affero General Public License as published by the Free 
Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT 
ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more 
details.
+
+ You should have received a copy of the GNU Affero General Public License 
along with
+ GNU Anastasis; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
 import { TalerErrorCode } from "@gnu-taler/taler-util";
 import {
   AggregatedPolicyMetaInfo,
@@ -7,7 +26,6 @@ import {
   getBackupStartState,
   getRecoveryStartState,
   mergeDiscoveryAggregate,
-  PolicyMetaInfo,
   RecoveryStates,
   reduceAction,
   ReducerState,
diff --git 
a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx
index e26ba706..49cddc8b 100644
--- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx
@@ -44,14 +44,6 @@ export const NewProviderWithoutProviderList = 
createExample(TestedComponent, {
   authentication_providers: {},
 } as ReducerState);
 
-export const NewVideoProvider = createExample(
-  TestedComponent,
-  {
-    ...reducerStatesExample.authEditing,
-  } as ReducerState,
-  { providerType: "video" },
-);
-
 export const NewSmsProvider = createExample(
   TestedComponent,
   {
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
index 3bd6a0c1..3d765aa8 100644
--- 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
@@ -249,19 +249,15 @@ export const 
OnePolicyWithAllTheChallengesInDifferentState = createExample(
     },
     challenge_feedback: {
       "uuid-1": { state: ChallengeFeedbackStatus.Solved.toString() },
-      "uuid-2": {
-        state: ChallengeFeedbackStatus.Message.toString(),
-        message: "Challenge should be solved",
-      },
       "uuid-3": {
         state: ChallengeFeedbackStatus.AuthIban.toString(),
         challenge_amount: "EUR:1",
-        credit_iban: "DE12345789000",
-        business_name: "Data Loss Incorporated",
+        target_iban: "DE12345789000",
+        target_business_name: "Data Loss Incorporated",
         wire_transfer_subject: "Anastasis 987654321",
       },
       "uuid-4": {
-        state: ChallengeFeedbackStatus.Payment.toString(),
+        state: ChallengeFeedbackStatus.TalerPayment.toString(),
         taler_pay_uri: "taler://pay/...",
         provider: "https://localhost:8080/";,
         payment_secret: "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG",
@@ -270,11 +266,6 @@ export const OnePolicyWithAllTheChallengesInDifferentState 
= createExample(
         state: ChallengeFeedbackStatus.RateLimitExceeded.toString(),
         // "error_code": 8121
       },
-      "uuid-6": {
-        state: ChallengeFeedbackStatus.Redirect.toString(),
-        redirect_url: "https://videoconf.example.com/";,
-        http_status: 303,
-      },
       "uuid-7": {
         state: ChallengeFeedbackStatus.ServerFailure.toString(),
         http_status: 500,
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
index c4047f0b..6660e63d 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
@@ -14,11 +14,8 @@ function OverviewFeedbackDisplay(props: { feedback?: 
ChallengeFeedback }) {
     return null;
   }
   switch (feedback.state) {
-    case ChallengeFeedbackStatus.Message:
-      return <div class="block has-text-danger">{feedback.message}</div>;
     case ChallengeFeedbackStatus.Solved:
       return <div />;
-    case ChallengeFeedbackStatus.Pending:
     case ChallengeFeedbackStatus.AuthIban:
       return null;
     case ChallengeFeedbackStatus.ServerFailure:
@@ -43,7 +40,6 @@ function OverviewFeedbackDisplay(props: { feedback?: 
ChallengeFeedback }) {
           provider for further information.
         </div>
       );
-    case ChallengeFeedbackStatus.Redirect:
     default:
       return <div />;
   }
@@ -178,7 +174,7 @@ export function ChallengeOverviewScreen(): VNode {
               case ChallengeFeedbackStatus.RateLimitExceeded:
                 return <div />;
               case ChallengeFeedbackStatus.AuthIban:
-              case ChallengeFeedbackStatus.Payment:
+              case ChallengeFeedbackStatus.TalerPayment:
                 return (
                   <div>
                     <AsyncButton
@@ -192,20 +188,6 @@ export function ChallengeOverviewScreen(): VNode {
                     </AsyncButton>
                   </div>
                 );
-              case ChallengeFeedbackStatus.Redirect:
-                return (
-                  <div>
-                    <AsyncButton
-                      class="button"
-                      disabled={
-                        atLeastThereIsOnePolicySolved && !policy.isPolicySolved
-                      }
-                      onClick={selectChallenge}
-                    >
-                      Go to {feedback.redirect_url}
-                    </AsyncButton>
-                  </div>
-                );
               case ChallengeFeedbackStatus.Solved:
                 return (
                   <div>
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx 
b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index 1070cf8a..3691d141 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -16,19 +16,7 @@ export function SolveOverviewFeedbackDisplay(props: {
     return <div />;
   }
   switch (feedback.state) {
-    case ChallengeFeedbackStatus.Message:
-      return (
-        <Notifications
-          notifications={[
-            {
-              type: "INFO",
-              message: `Message from provider`,
-              description: feedback.message,
-            },
-          ]}
-        />
-      );
-    case ChallengeFeedbackStatus.Payment:
+    case ChallengeFeedbackStatus.TalerPayment:
       return (
         <Notifications
           notifications={[
@@ -51,7 +39,7 @@ export function SolveOverviewFeedbackDisplay(props: {
             {
               type: "INFO",
               message: `Message from provider`,
-              description: `Need to send a wire transfer to 
"${feedback.business_name}"`,
+              description: `Need to send a wire transfer to 
"${feedback.target_business_name}"`,
             },
           ]}
         />
@@ -80,22 +68,6 @@ export function SolveOverviewFeedbackDisplay(props: {
           ]}
         />
       );
-    case ChallengeFeedbackStatus.Redirect:
-      return (
-        <Notifications
-          notifications={[
-            {
-              type: "INFO",
-              message: `Message from provider`,
-              description: (
-                <span>
-                  Please visit this link: <a>{feedback.redirect_url}</a>
-                </span>
-              ),
-            },
-          ]}
-        />
-      );
     case ChallengeFeedbackStatus.Unsupported:
       return (
         <Notifications
@@ -121,6 +93,9 @@ export function SolveOverviewFeedbackDisplay(props: {
         />
       );
     default:
+      console.warn(
+        `unknown challenge feedback status ${JSON.stringify(feedback)}`,
+      );
       return <div />;
   }
 }
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
index 1e7053df..d8211197 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
@@ -80,7 +80,7 @@ export const PaymentFeedback = createExample(
     selected_challenge_uuid: "uuid-1",
     challenge_feedback: {
       "uuid-1": {
-        state: ChallengeFeedbackStatus.Payment,
+        state: ChallengeFeedbackStatus.TalerPayment,
         taler_pay_uri: "taler://pay/...",
         provider: "https://localhost:8080/";,
         payment_secret: "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG",
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx
index 4f7f2132..935b45a7 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx
@@ -9,6 +9,7 @@ import { TextInput } from 
"../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodEmailSolve({ id }: AuthMethodSolveProps): VNode {
@@ -103,12 +104,6 @@ export function AuthMethodEmailSolve({ id }: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="Email challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -160,7 +155,7 @@ export function AuthMethodEmailSolve({ id }: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
index b58952fe..39788b53 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
@@ -5,10 +5,10 @@ import {
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { AsyncButton } from "../../../components/AsyncButton";
-import { TextInput } from "../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodIbanSolve({ id }: AuthMethodSolveProps): VNode {
@@ -79,12 +79,6 @@ export function AuthMethodIbanSolve({ id }: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="IBAN Challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -101,7 +95,7 @@ export function AuthMethodIbanSolve({ id }: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
index fcff0b49..382ffa00 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
@@ -9,6 +9,7 @@ import { TextInput } from 
"../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodPostSolve({ id }: AuthMethodSolveProps): VNode {
@@ -102,12 +103,6 @@ export function AuthMethodPostSolve({ id }: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="Postal Challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -130,7 +125,7 @@ export function AuthMethodPostSolve({ id }: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
index c24ab050..51d0a999 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
@@ -20,6 +20,7 @@
  */
 
 import {
+  ChallengeFeedbackBankTransferRequired,
   ChallengeFeedbackStatus,
   ReducerState,
 } from "@gnu-taler/anastasis-core";
@@ -62,28 +63,6 @@ export const WithoutFeedback = createExample(
   },
 );
 
-export const MessageFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information: {
-    challenges: [
-      {
-        cost: "USD:1",
-        instructions: "does P equals NP?",
-        type: "question",
-        uuid: "ASDASDSAD!1",
-      },
-    ],
-    policies: [],
-  },
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.Message,
-      message: "Challenge should be solved",
-    },
-  },
-} as ReducerState);
-
 export const ServerFailureFeedback = createExample(
   TestedComponent[type].solve,
   {
@@ -92,7 +71,7 @@ export const ServerFailureFeedback = createExample(
       challenges: [
         {
           cost: "USD:1",
-          instructions: "does P equals NP?",
+          instructions: "does P equal NP?",
           type: "question",
           uuid: "ASDASDSAD!1",
         },
@@ -110,29 +89,6 @@ export const ServerFailureFeedback = createExample(
   } as ReducerState,
 );
 
-export const RedirectFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information: {
-    challenges: [
-      {
-        cost: "USD:1",
-        instructions: "does P equals NP?",
-        type: "question",
-        uuid: "ASDASDSAD!1",
-      },
-    ],
-    policies: [],
-  },
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.Redirect,
-      http_status: 302,
-      redirect_url: "http://video.taler.net";,
-    },
-  },
-} as ReducerState);
-
 export const MessageRateLimitExceededFeedback = createExample(
   TestedComponent[type].solve,
   {
@@ -201,6 +157,15 @@ export const TruthUnknownFeedback = 
createExample(TestedComponent[type].solve, {
   },
 } as ReducerState);
 
+const ibanFeedback: ChallengeFeedbackBankTransferRequired = {
+  state: ChallengeFeedbackStatus.AuthIban,
+  challenge_amount: "EUR:1",
+  target_iban: "DE12345789000",
+  target_business_name: "Data Loss Incorporated",
+  wire_transfer_subject: "Anastasis 987654321",
+  answer_code: 987654321,
+};
+
 export const AuthIbanFeedback = createExample(TestedComponent[type].solve, {
   ...reducerStatesExample.challengeSolving,
   recovery_information: {
@@ -216,23 +181,7 @@ export const AuthIbanFeedback = 
createExample(TestedComponent[type].solve, {
   },
   selected_challenge_uuid: "ASDASDSAD!1",
   challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.AuthIban,
-      challenge_amount: "EUR:1",
-      credit_iban: "DE12345789000",
-      business_name: "Data Loss Incorporated",
-      wire_transfer_subject: "Anastasis 987654321",
-      answer_code: 987654321,
-      // Fields that follow are only for compatibility with C reducer,
-      // will be removed eventually,
-      details: {
-        business_name: "foo",
-        challenge_amount: "foo",
-        credit_iban: "foo",
-        wire_transfer_subject: "foo",
-      },
-      method: "iban",
-    },
+    "ASDASDSAD!1": ibanFeedback,
   },
 } as ReducerState);
 
@@ -252,7 +201,7 @@ export const PaymentFeedback = 
createExample(TestedComponent[type].solve, {
   selected_challenge_uuid: "ASDASDSAD!1",
   challenge_feedback: {
     "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.Payment,
+      state: ChallengeFeedbackStatus.TalerPayment,
       taler_pay_uri: "taler://pay/...",
       provider: "https://localhost:8080/";,
       payment_secret: "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG",
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
index 058efe00..bc0b67dc 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
@@ -9,6 +9,7 @@ import { TextInput } from 
"../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodQuestionSolve({ id }: AuthMethodSolveProps): VNode {
@@ -79,12 +80,6 @@ export function AuthMethodQuestionSolve({ id }: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="Question challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -110,7 +105,7 @@ export function AuthMethodQuestionSolve({ id }: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
index 3b00f6f2..f3d304c7 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
@@ -9,6 +9,7 @@ import { TextInput } from 
"../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodSmsSolve({ id }: AuthMethodSolveProps): VNode {
@@ -103,12 +104,6 @@ export function AuthMethodSmsSolve({ id }: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="SMS Challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -160,7 +155,7 @@ export function AuthMethodSmsSolve({ id }: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
index ee493744..6b98f8ec 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
@@ -9,6 +9,7 @@ import { TextInput } from 
"../../../components/fields/TextInput";
 import { useAnastasisContext } from "../../../context/anastasis";
 import { AnastasisClientFrame } from "../index";
 import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
+import { shouldHideConfirm } from "./helpers";
 import { AuthMethodSolveProps } from "./index";
 
 export function AuthMethodTotpSolve(props: AuthMethodSolveProps): VNode {
@@ -81,12 +82,6 @@ export function AuthMethodTotpSolve(props: 
AuthMethodSolveProps): VNode {
     reducer?.back();
   }
 
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
   return (
     <AnastasisClientFrame hideNav title="TOTP Challenge">
       <SolveOverviewFeedbackDisplay feedback={feedback} />
@@ -108,7 +103,7 @@ export function AuthMethodTotpSolve(props: 
AuthMethodSolveProps): VNode {
         <button class="button" onClick={onCancel}>
           Cancel
         </button>
-        {!shouldHideConfirm && (
+        {!shouldHideConfirm(feedback) && (
           <AsyncButton class="button is-info" onClick={onNext}>
             Confirm
           </AsyncButton>
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
deleted file mode 100644
index 4aad0a09..00000000
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createExample, reducerStatesExample } from "../../../utils";
-import { authMethods as TestedComponent, KnownAuthMethods } from "./index";
-import logoImage from "../../../assets/logo.jpeg";
-
-export default {
-  title: "Pages/backup/AuthorizationMethod/AuthMethods/Video",
-  component: TestedComponent,
-  args: {
-    order: 5,
-  },
-  argTypes: {
-    onUpdate: { action: "onUpdate" },
-    onBack: { action: "onBack" },
-  },
-};
-
-const type: KnownAuthMethods = "video";
-
-export const Empty = createExample(
-  TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
-  {
-    configured: [],
-  },
-);
-
-export const WithOneExample = createExample(
-  TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
-  {
-    configured: [
-      {
-        challenge: "qwe",
-        type,
-        instructions: logoImage,
-        remove: () => null,
-      },
-    ],
-  },
-);
-
-export const WithMoreExamples = createExample(
-  TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
-  {
-    configured: [
-      {
-        challenge: "qwe",
-        type,
-        instructions: logoImage,
-        remove: () => null,
-      },
-      {
-        challenge: "qwe",
-        type,
-        instructions: logoImage,
-        remove: () => null,
-      },
-    ],
-  },
-);
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx
deleted file mode 100644
index 04a129c4..00000000
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import { encodeCrock, stringToBytes } from "@gnu-taler/taler-util";
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { ImageInput } from "../../../components/fields/ImageInput";
-import { AuthMethodSetupProps } from "./index";
-import { AnastasisClientFrame } from "../index";
-
-export function AuthMethodVideoSetup({
-  cancel,
-  addAuthMethod,
-  configured,
-}: AuthMethodSetupProps): VNode {
-  const [image, setImage] = useState("");
-  const addVideoAuth = (): void => {
-    addAuthMethod({
-      authentication_method: {
-        type: "video",
-        instructions: "Join a video call",
-        challenge: encodeCrock(stringToBytes(image)),
-      },
-    });
-  };
-  function goNextIfNoErrors(): void {
-    addVideoAuth();
-  }
-  return (
-    <AnastasisClientFrame hideNav title="Add video authentication">
-      <p>
-        For video identification, you need to provide a passport-style
-        photograph. When recovering your secret, you will be asked to join a
-        video call. During that call, a human will use the photograph to verify
-        your identity.
-      </p>
-      <div style={{ textAlign: "center" }}>
-        <ImageInput
-          label="Choose photograph"
-          grabFocus
-          onConfirm={goNextIfNoErrors}
-          bind={[image, setImage]}
-        />
-      </div>
-      {configured.length > 0 && (
-        <section class="section">
-          <div class="block">Your photographs:</div>
-          <div class="block">
-            {configured.map((c, i) => {
-              return (
-                <div
-                  key={i}
-                  class="box"
-                  style={{ display: "flex", justifyContent: "space-between" }}
-                >
-                  <img
-                    style={{
-                      marginTop: "auto",
-                      marginBottom: "auto",
-                      width: 100,
-                      height: 100,
-                      border: "solid 1px black",
-                    }}
-                    src={c.instructions}
-                  />
-                  <div style={{ marginTop: "auto", marginBottom: "auto" }}>
-                    <button class="button is-danger" onClick={c.remove}>
-                      Delete
-                    </button>
-                  </div>
-                </div>
-              );
-            })}
-          </div>
-        </section>
-      )}
-      <div>
-        <div
-          style={{
-            marginTop: "2em",
-            display: "flex",
-            justifyContent: "space-between",
-          }}
-        >
-          <button class="button" onClick={cancel}>
-            Cancel
-          </button>
-          <button class="button is-info" onClick={addVideoAuth}>
-            Add
-          </button>
-        </div>
-      </div>
-    </AnastasisClientFrame>
-  );
-}
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx
deleted file mode 100644
index 0e454dd7..00000000
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import {
-  ChallengeFeedbackStatus,
-  ReducerState,
-} from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils";
-import { authMethods as TestedComponent, KnownAuthMethods } from "./index";
-
-export default {
-  title: "Pages/recovery/SolveChallenge/AuthMethods/video",
-  component: TestedComponent,
-  args: {
-    order: 5,
-  },
-  argTypes: {
-    onUpdate: { action: "onUpdate" },
-    onBack: { action: "onBack" },
-  },
-};
-
-const type: KnownAuthMethods = "video";
-
-export const WithoutFeedback = createExample(
-  TestedComponent[type].solve,
-  {
-    ...reducerStatesExample.challengeSolving,
-    recovery_information: {
-      challenges: [
-        {
-          cost: "USD:1",
-          instructions: "does P equals NP?",
-          type: "question",
-          uuid: "uuid-1",
-        },
-      ],
-      policies: [],
-    },
-    selected_challenge_uuid: "uuid-1",
-  } as ReducerState,
-  {
-    id: "uuid-1",
-  },
-);
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx
deleted file mode 100644
index e0ebdce7..00000000
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import {
-  ChallengeFeedbackStatus,
-  ChallengeInfo,
-} from "@gnu-taler/anastasis-core";
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AsyncButton } from "../../../components/AsyncButton";
-import { TextInput } from "../../../components/fields/TextInput";
-import { useAnastasisContext } from "../../../context/anastasis";
-import { AnastasisClientFrame } from "../index";
-import { SolveOverviewFeedbackDisplay } from "../SolveScreen";
-import { AuthMethodSolveProps } from "./index";
-
-export function AuthMethodVideoSolve({ id }: AuthMethodSolveProps): VNode {
-  const [answer, setAnswer] = useState("");
-
-  const reducer = useAnastasisContext();
-  if (!reducer) {
-    return (
-      <AnastasisClientFrame hideNav title="Recovery problem">
-        <div>no reducer in context</div>
-      </AnastasisClientFrame>
-    );
-  }
-  if (
-    reducer.currentReducerState?.reducer_type !== "recovery"
-  ) {
-    return (
-      <AnastasisClientFrame hideNav title="Recovery problem">
-        <div>invalid state</div>
-      </AnastasisClientFrame>
-    );
-  }
-
-  if (!reducer.currentReducerState.recovery_information) {
-    return (
-      <AnastasisClientFrame
-        hideNext="Recovery document not found"
-        title="Recovery problem"
-      >
-        <div>no recovery information found</div>
-      </AnastasisClientFrame>
-    );
-  }
-  if (!reducer.currentReducerState.selected_challenge_uuid) {
-    return (
-      <AnastasisClientFrame hideNav title="Recovery problem">
-        <div>invalid state</div>
-        <div
-          style={{
-            marginTop: "2em",
-            display: "flex",
-            justifyContent: "space-between",
-          }}
-        >
-          <button class="button" onClick={() => reducer.back()}>
-            Back
-          </button>
-        </div>
-      </AnastasisClientFrame>
-    );
-  }
-
-  const chArr = reducer.currentReducerState.recovery_information.challenges;
-  const challengeFeedback =
-    reducer.currentReducerState.challenge_feedback ?? {};
-  const selectedUuid = reducer.currentReducerState.selected_challenge_uuid;
-  const challenges: {
-    [uuid: string]: ChallengeInfo;
-  } = {};
-  for (const ch of chArr) {
-    challenges[ch.uuid] = ch;
-  }
-  const selectedChallenge = challenges[selectedUuid];
-  const feedback = challengeFeedback[selectedUuid];
-
-  async function onNext(): Promise<void> {
-    return reducer?.transition("solve_challenge", { answer });
-  }
-  function onCancel(): void {
-    reducer?.back();
-  }
-
-  const shouldHideConfirm =
-    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
-    feedback?.state === ChallengeFeedbackStatus.Redirect ||
-    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
-    feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
-
-  return (
-    <AnastasisClientFrame hideNav title="Add email authentication">
-      <SolveOverviewFeedbackDisplay feedback={feedback} />
-      <p>You are gonna be called to check your identity</p>
-      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
-
-      <div
-        style={{
-          marginTop: "2em",
-          display: "flex",
-          justifyContent: "space-between",
-        }}
-      >
-        <button class="button" onClick={onCancel}>
-          Cancel
-        </button>
-        {!shouldHideConfirm && (
-          <AsyncButton class="button is-info" onClick={onNext}>
-            Confirm
-          </AsyncButton>
-        )}
-      </div>
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts 
b/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts
new file mode 100644
index 00000000..2f5e3773
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts
@@ -0,0 +1,12 @@
+import {
+  ChallengeFeedback,
+  ChallengeFeedbackStatus,
+} from "@gnu-taler/anastasis-core";
+
+export function shouldHideConfirm(feedback: ChallengeFeedback): boolean {
+  return (
+    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded ||
+    feedback?.state === ChallengeFeedbackStatus.Unsupported ||
+    feedback?.state === ChallengeFeedbackStatus.TruthUnknown
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx 
b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
index 64cf07cd..a1ab9cd2 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
@@ -3,22 +3,18 @@ import { h, VNode } from "preact";
 import postalIcon from "../../../assets/icons/auth_method/postal.svg";
 import questionIcon from "../../../assets/icons/auth_method/question.svg";
 import smsIcon from "../../../assets/icons/auth_method/sms.svg";
-import videoIcon from "../../../assets/icons/auth_method/video.svg";
 import { AuthMethodEmailSetup as EmailSetup } from "./AuthMethodEmailSetup";
 import { AuthMethodEmailSolve as EmailSolve } from "./AuthMethodEmailSolve";
 import { AuthMethodIbanSetup as IbanSetup } from "./AuthMethodIbanSetup";
-import { AuthMethodPostSetup as PostalSetup } from "./AuthMethodPostSetup";
-import { AuthMethodQuestionSetup as QuestionSetup } from 
"./AuthMethodQuestionSetup";
-import { AuthMethodSmsSetup as SmsSetup } from "./AuthMethodSmsSetup";
-import { AuthMethodTotpSetup as TotpSetup } from "./AuthMethodTotpSetup";
-import { AuthMethodVideoSetup as VideoSetup } from "./AuthMethodVideoSetup";
-
 import { AuthMethodIbanSolve as IbanSolve } from "./AuthMethodIbanSolve";
+import { AuthMethodPostSetup as PostalSetup } from "./AuthMethodPostSetup";
 import { AuthMethodPostSolve as PostalSolve } from "./AuthMethodPostSolve";
+import { AuthMethodQuestionSetup as QuestionSetup } from 
"./AuthMethodQuestionSetup";
 import { AuthMethodQuestionSolve as QuestionSolve } from 
"./AuthMethodQuestionSolve";
+import { AuthMethodSmsSetup as SmsSetup } from "./AuthMethodSmsSetup";
 import { AuthMethodSmsSolve as SmsSolve } from "./AuthMethodSmsSolve";
+import { AuthMethodTotpSetup as TotpSetup } from "./AuthMethodTotpSetup";
 import { AuthMethodTotpSolve as TotpSolve } from "./AuthMethodTotpSolve";
-import { AuthMethodVideoSolve as VideoSolve } from "./AuthMethodVideoSolve";
 
 export type AuthMethodWithRemove = AuthMethod & { remove: () => void };
 
@@ -40,14 +36,12 @@ interface AuthMethodConfiguration {
   solve: (props: AuthMethodSolveProps) => VNode;
   skip?: boolean;
 }
-// export type KnownAuthMethods = "sms" | "email" | "post" | "question" | 
"video" | "totp" | "iban";
 
 const ALL_METHODS = [
   "sms",
   "email",
   "post",
   "question",
-  "video",
   "totp",
   "iban",
 ] as const;
@@ -97,11 +91,4 @@ export const authMethods: KnowMethodConfig = {
     setup: TotpSetup,
     solve: TotpSolve,
   },
-  video: {
-    icon: <img src={videoIcon} />,
-    label: "Video",
-    setup: VideoSetup,
-    solve: VideoSolve,
-    skip: true,
-  },
 };
diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts
index c9889160..09d6856c 100644
--- a/packages/taler-util/src/payto.ts
+++ b/packages/taler-util/src/payto.ts
@@ -14,10 +14,14 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { generateFakeSegwitAddress } from "./index.js";
+import { generateFakeSegwitAddress } from "./bitcoin.js";
 import { URLSearchParams } from "./url.js";
 
-export type PaytoUri = PaytoUriUnknown | PaytoUriIBAN | PaytoUriTalerBank | 
PaytoUriBitcoin;
+export type PaytoUri =
+  | PaytoUriUnknown
+  | PaytoUriIBAN
+  | PaytoUriTalerBank
+  | PaytoUriBitcoin;
 
 interface PaytoUriGeneric {
   targetType: string;
@@ -31,38 +35,41 @@ interface PaytoUriUnknown extends PaytoUriGeneric {
 
 interface PaytoUriIBAN extends PaytoUriGeneric {
   isKnown: true;
-  targetType: 'iban',
+  targetType: "iban";
   iban: string;
 }
 
 interface PaytoUriTalerBank extends PaytoUriGeneric {
   isKnown: true;
-  targetType: 'x-taler-bank',
+  targetType: "x-taler-bank";
   host: string;
   account: string;
 }
 
 interface PaytoUriBitcoin extends PaytoUriGeneric {
   isKnown: true;
-  targetType: 'bitcoin',
-  generateSegwitAddress: (r: string) => { addr1: string, addr2: string };
-  addr1?: string, addr2?: string,
+  targetType: "bitcoin";
+  generateSegwitAddress: (r: string) => { addr1: string; addr2: string };
+  addr1?: string;
+  addr2?: string;
 }
 
 const paytoPfx = "payto://";
 
-
-
 function buildSegwitGenerator(result: PaytoUriBitcoin, targetPath: string) {
   //generate segwit address just once, save addr in payto object
   //and use it as cache
-  return function generateSegwitAddress(reserve: string): { addr1: string, 
addr2: string } {
-    if (result.addr1 && result.addr2) return { addr1: result.addr1, addr2: 
result.addr2 };
-    const { addr1, addr2 } = generateFakeSegwitAddress(reserve, targetPath)
-    result.addr1 = addr1
-    result.addr2 = addr2
-    return { addr1, addr2 }
-  }
+  return function generateSegwitAddress(reserve: string): {
+    addr1: string;
+    addr2: string;
+  } {
+    if (result.addr1 && result.addr2)
+      return { addr1: result.addr1, addr2: result.addr2 };
+    const { addr1, addr2 } = generateFakeSegwitAddress(reserve, targetPath);
+    result.addr1 = addr1;
+    result.addr2 = addr2;
+    return { addr1, addr2 };
+  };
 }
 /**
  * Add query parameters to a payto URI
@@ -81,27 +88,27 @@ export function addPaytoQueryParams(
 
 /**
  * Serialize a PaytoURI into a valid payto:// string
- * 
- * @param p 
- * @returns 
+ *
+ * @param p
+ * @returns
  */
 export function stringifyPaytoUri(p: PaytoUri): string {
-  const url = `${paytoPfx}${p.targetType}//${p.targetPath}`
+  const url = `${paytoPfx}${p.targetType}//${p.targetPath}`;
   if (p.params) {
     const search = Object.entries(p.params)
       .map(([key, value]) => `${key}=${value}`)
       .join("&");
-    return `${url}?${search}`
+    return `${url}?${search}`;
   }
-  return url
+  return url;
 }
 
 /**
  * Parse a valid payto:// uri into a PaytoUri object
  * RFC 8905
- * 
- * @param s 
- * @returns 
+ *
+ * @param s
+ * @returns
  */
 export function parsePaytoUri(s: string): PaytoUri | undefined {
   if (!s.startsWith(paytoPfx)) {
@@ -127,47 +134,44 @@ export function parsePaytoUri(s: string): PaytoUri | 
undefined {
     params[v] = k;
   });
 
-  if (targetType === 'x-taler-bank') {
-    const parts = targetPath.split('/')
-    const host = parts[0]
-    const account = parts[1]
+  if (targetType === "x-taler-bank") {
+    const parts = targetPath.split("/");
+    const host = parts[0];
+    const account = parts[1];
     return {
       targetPath,
       targetType,
       params,
       isKnown: true,
-      host, account,
+      host,
+      account,
     };
-
   }
-  if (targetType === 'iban') {
+  if (targetType === "iban") {
     return {
       isKnown: true,
       targetPath,
       targetType,
       params,
-      iban: targetPath
+      iban: targetPath,
     };
-
   }
-  if (targetType === 'bitcoin') {
-
+  if (targetType === "bitcoin") {
     const result: PaytoUriBitcoin = {
       isKnown: true,
       targetPath,
       targetType,
       params,
-      generateSegwitAddress: (): any => null
-    }
+      generateSegwitAddress: (): any => null,
+    };
 
-    result.generateSegwitAddress = buildSegwitGenerator(result, targetPath)
+    result.generateSegwitAddress = buildSegwitGenerator(result, targetPath);
     return result;
-
   }
   return {
     targetPath,
     targetType,
     params,
-    isKnown: false
+    isKnown: false,
   };
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 89a87ff0..8f0d6745 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -65,6 +65,7 @@ importers:
       '@types/enzyme': ^3.10.11
       '@typescript-eslint/eslint-plugin': ^5.3.0
       '@typescript-eslint/parser': ^5.3.0
+      babel-plugin-add-import-extension: ^1.6.0
       base64-inline-loader: 1.1.1
       bulma: ^0.9.3
       bulma-checkbox: ^1.1.1
@@ -106,6 +107,7 @@ importers:
       '@types/enzyme': 3.10.11
       '@typescript-eslint/eslint-plugin': 
5.11.0_de5a1ddccd75ca1e499b8b8491d3dcba
       '@typescript-eslint/parser': 5.11.0_eslint@8.8.0+typescript@4.5.5
+      babel-plugin-add-import-extension: 1.6.0_@babel+core@7.13.16
       bulma: 0.9.3
       bulma-checkbox: 1.2.1
       bulma-radio: 1.2.0
@@ -7137,6 +7139,15 @@ packages:
       schema-utils: 2.7.1
     dev: true
 
+  /babel-plugin-add-import-extension/1.6.0_@babel+core@7.13.16:
+    resolution: {integrity: 
sha512-JVSQPMzNzN/S4wPRoKQ7+u8PlkV//BPUMnfWVbr63zcE+6yHdU2Mblz10Vf7qe+6Rmu4svF5jG7JxdcPi9VvKg==}
+    peerDependencies:
+      '@babel/core': '>=7.0.0'
+    dependencies:
+      '@babel/core': 7.13.16
+      '@babel/helper-plugin-utils': 7.16.7
+    dev: true
+
   /babel-plugin-apply-mdx-type-prop/1.6.22_@babel+core@7.12.9:
     resolution: {integrity: 
sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==}
     peerDependencies:

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]