diff --git a/packages/anastasis-core/src/challenge-feedback-types.ts b/packages/anastasis-core/src/challenge-feedback-types.ts
index 0770d9296..30f42288f 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
+ */
+
+/**
+ * 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 98aba2ce6..055f3fb62 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 72f2dc6e5..4da62fc04 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 =>
+ buildCodecForObject()
+ .property("method", codecForConstString("FILE_WRITTEN"))
+ .property("filename", codecForString())
+ .build("FileChallengeInstructionMessage");
+
+export const codecForPinChallengeInstructionMessage =
+ (): Codec =>
+ buildCodecForObject()
+ .property("method", codecForConstString("TAN_SENT"))
+ .property("tan_address_hint", codecForString())
+ .build("PinChallengeInstructionMessage");
+
+export const codecForIbanChallengeInstructionMessage =
+ (): Codec =>
+ buildCodecForObject()
+ .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 =>
+ buildCodecForUnion()
+ .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 5b5f40297..b7e3148cb 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 2327b5e12..a855ffa94 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 7274c3d03..434e5fb09 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
+ */
+
+/**
+ * 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 e26ba706f..49cddc8b7 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 3bd6a0c17..3d765aa86 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 c4047f0b3..6660e63de 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
{feedback.message}
;
case ChallengeFeedbackStatus.Solved:
return ;
- case ChallengeFeedbackStatus.Pending:
case ChallengeFeedbackStatus.AuthIban:
return null;
case ChallengeFeedbackStatus.ServerFailure:
@@ -43,7 +40,6 @@ function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
provider for further information.
);
- case ChallengeFeedbackStatus.Redirect:
default:
return ;
}
@@ -178,7 +174,7 @@ export function ChallengeOverviewScreen(): VNode {
case ChallengeFeedbackStatus.RateLimitExceeded:
return ;
case ChallengeFeedbackStatus.AuthIban:
- case ChallengeFeedbackStatus.Payment:
+ case ChallengeFeedbackStatus.TalerPayment:
return (
);
- case ChallengeFeedbackStatus.Redirect:
- return (
-
-
- Go to {feedback.redirect_url}
-
-
- );
case ChallengeFeedbackStatus.Solved:
return (
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index 1070cf8a9..3691d1416 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 ;
}
switch (feedback.state) {
- case ChallengeFeedbackStatus.Message:
- return (
-
- );
- case ChallengeFeedbackStatus.Payment:
+ case ChallengeFeedbackStatus.TalerPayment:
return (
@@ -80,22 +68,6 @@ export function SolveOverviewFeedbackDisplay(props: {
]}
/>
);
- case ChallengeFeedbackStatus.Redirect:
- return (
-
- Please visit this link: {feedback.redirect_url}
-
- ),
- },
- ]}
- />
- );
case ChallengeFeedbackStatus.Unsupported:
return (
);
default:
+ console.warn(
+ `unknown challenge feedback status ${JSON.stringify(feedback)}`,
+ );
return ;
}
}
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 1e7053df5..d82111979 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 4f7f21324..935b45a77 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 (
@@ -160,7 +155,7 @@ export function AuthMethodEmailSolve({ id }: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
index b58952feb..39788b538 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 (
@@ -101,7 +95,7 @@ export function AuthMethodIbanSolve({ id }: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
index fcff0b498..382ffa00a 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 (
@@ -130,7 +125,7 @@ export function AuthMethodPostSolve({ id }: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
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 c24ab0503..51d0a9993 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 058efe009..bc0b67dcb 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 (
@@ -110,7 +105,7 @@ export function AuthMethodQuestionSolve({ id }: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
index 3b00f6f2a..f3d304c74 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 (
@@ -160,7 +155,7 @@ export function AuthMethodSmsSolve({ id }: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
index ee4937441..6b98f8ece 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 (
@@ -108,7 +103,7 @@ export function AuthMethodTotpSolve(props: AuthMethodSolveProps): VNode {
- {!shouldHideConfirm && (
+ {!shouldHideConfirm(feedback) && (
Confirm
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 4aad0a097..000000000
--- 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
- */
-
-/**
- *
- * @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 04a129c4a..000000000
--- 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 (
-
-
- 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.
-
-
-
-
- {configured.length > 0 && (
-
-
Your photographs:
-
- {configured.map((c, i) => {
- return (
-
-
-
-
-
-
- );
- })}
-
-
- )}
-
-
-
-
-
-
-
- );
-}
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 0e454dd73..000000000
--- 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
- */
-
-/**
- *
- * @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 e0ebdce76..000000000
--- 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 (
-
-