aboutsummaryrefslogtreecommitdiff
path: root/packages/anastasis-webui/src/pages/home/authMethod
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-11-08 09:56:06 -0300
committerSebastian <sebasjm@gmail.com>2021-11-08 09:56:06 -0300
commit6ef5fd21fc365d780da42170ce85042f874ed1dc (patch)
treee9b86dc8949e1ad38d13f3b13814f3770de45675 /packages/anastasis-webui/src/pages/home/authMethod
parent292d647aa917ecef7fee3f1ebeee0411b4c9a0d6 (diff)
downloadwallet-core-6ef5fd21fc365d780da42170ce85042f874ed1dc.tar.xz
some solve challenge examples, WIP
Diffstat (limited to 'packages/anastasis-webui/src/pages/home/authMethod')
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx9
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx80
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx106
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx9
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx3
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx105
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx7
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx105
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx3
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx105
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx3
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx106
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx3
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx105
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx8
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx3
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx56
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx105
-rw-r--r--packages/anastasis-webui/src/pages/home/authMethod/index.tsx69
29 files changed, 1239 insertions, 71 deletions
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
index e178a4955..da87b7a8b 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
@@ -25,7 +24,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/email',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/email',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +37,11 @@ export default {
const type: KnownAuthMethods = 'email'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -51,7 +50,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx
index 1a6be1b61..27a0685b2 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx
@@ -1,14 +1,12 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
encodeCrock,
stringToBytes
} from "@gnu-taler/taler-util";
-import { Fragment, h, VNode } from "preact";
+import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
-import { AnastasisClientFrame } from "../index";
-import { TextInput } from "../../../components/fields/TextInput";
import { EmailInput } from "../../../components/fields/EmailInput";
+import { AnastasisClientFrame } from "../index";
+import { AuthMethodSetupProps } from "./index";
const EMAIL_PATTERN = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
new file mode 100644
index 000000000..525cd2b07
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
@@ -0,0 +1,80 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/email',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'email'
+
+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',
+});
+
+export const PaymentFeedback = 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',
+ challenge_feedback: {
+ 'uuid-1': {
+ state: ChallengeFeedbackStatus.Payment,
+ taler_pay_uri: "taler://pay/...",
+ provider: "https://localhost:8080/",
+ payment_secret: "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+ }
+ }
+} as ReducerState, {
+ id: 'uuid-1',
+});
+
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx
new file mode 100644
index 000000000..bd4f43740
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.tsx
@@ -0,0 +1,106 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodEmailSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ An email has been sent to "<b>{selectedChallenge.instructions}</b>". Type the
+ code below
+ </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/AuthMethodIbanSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
index 71f618646..be0a04847 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
@@ -25,7 +24,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/IBAN',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/IBAN',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +37,11 @@ export default {
const type: KnownAuthMethods = 'iban'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -50,7 +49,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
remove: () => null
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx
index c9edbfa07..87969ab27 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
canonicalJson,
encodeCrock,
@@ -6,8 +5,8 @@ import {
} from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
+import { AuthMethodSetupProps } from ".";
import { TextInput } from "../../../components/fields/TextInput";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
import { AnastasisClientFrame } from "../index";
export function AuthMethodIbanSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
new file mode 100644
index 000000000..df73a9214
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/Iban',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'iban'
+
+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/AuthMethodIbanSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
new file mode 100644
index 000000000..1e4353da6
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx
@@ -0,0 +1,105 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodIbanSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ Send a wire transfer to the address
+ </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/AuthMethodPostSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
index 0f1c17495..adc83d6fe 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
@@ -25,7 +25,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/Post',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/Post',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +38,11 @@ export default {
const type: KnownAuthMethods = 'post'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -51,7 +51,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx
index bfeaaa832..692421d74 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx
@@ -1,13 +1,12 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
canonicalJson, encodeCrock,
stringToBytes
} from "@gnu-taler/taler-util";
-import { Fragment, h, VNode } from "preact";
+import { h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
-import { TextInput } from "../../../components/fields/TextInput";
import { AnastasisClientFrame } from "..";
+import { TextInput } from "../../../components/fields/TextInput";
+import { AuthMethodSetupProps } from "./index";
export function AuthMethodPostSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
const [fullName, setFullName] = useState("");
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
new file mode 100644
index 000000000..99451090b
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/post',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'post'
+
+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/AuthMethodPostSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
new file mode 100644
index 000000000..7e3c45abe
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx
@@ -0,0 +1,105 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodPostSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ Wait for the answer
+ </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/AuthMethodQuestionSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
index 3ba4a84ca..0c3ee2b77 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
@@ -25,7 +25,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/Question',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/Question',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +38,11 @@ export default {
const type: KnownAuthMethods = 'question'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -51,7 +51,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx
index 04fa00d59..780bfcb82 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx
@@ -1,11 +1,10 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
encodeCrock,
stringToBytes
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AuthMethodSetupProps } from "./index";
import { AnastasisClientFrame } from "../index";
import { TextInput } from "../../../components/fields/TextInput";
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
new file mode 100644
index 000000000..a325b3843
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/question',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'question'
+
+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/AuthMethodQuestionSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
new file mode 100644
index 000000000..ee1c0028f
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.tsx
@@ -0,0 +1,105 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodQuestionSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ Answer the question please
+ </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/AuthMethodSmsSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
index ae8297ef7..da2087ce1 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
@@ -25,7 +25,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/Sms',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/Sms',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +38,11 @@ export default {
const type: KnownAuthMethods = 'sms'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -51,7 +51,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx
index 9e85af2b2..cd8782b0c 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx
@@ -1,12 +1,11 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
encodeCrock,
stringToBytes
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useLayoutEffect, useRef, useState } from "preact/hooks";
+import { AuthMethodSetupProps } from ".";
import { NumberInput } from "../../../components/fields/NumberInput";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
import { AnastasisClientFrame } from "../index";
export function AuthMethodSmsSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
new file mode 100644
index 000000000..76e769303
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/sms',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'sms'
+
+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/AuthMethodSmsSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
new file mode 100644
index 000000000..ce7159bd0
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx
@@ -0,0 +1,106 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodSmsSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ An sms has been sent to "<b>{selectedChallenge.instructions}</b>". Type the code
+ below
+ </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/AuthMethodTotpSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
index 4e46b600e..c0a52924c 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
@@ -25,7 +25,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
export default {
- title: 'Pages/backup/authMethods/TOTP',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/TOTP',
component: TestedComponent,
args: {
order: 5,
@@ -38,10 +38,10 @@ export default {
const type: KnownAuthMethods = 'totp'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -49,7 +49,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
remove: () => null
}]
});
-export const WithMoreExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx
index fd0bd0224..a8ac499b2 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx
@@ -1,11 +1,10 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
encodeCrock,
stringToBytes
} from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useMemo, useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AuthMethodSetupProps } from "./index";
import { AnastasisClientFrame } from "../index";
import { TextInput } from "../../../components/fields/TextInput";
import { QR } from "../../../components/QR";
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
new file mode 100644
index 000000000..a301931b2
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 'anastasis-core';
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+ title: 'Pages/recovery/SolveChallenge/AuthMethods/totp',
+ component: TestedComponent,
+ args: {
+ order: 5,
+ },
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+const type: KnownAuthMethods = 'totp'
+
+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/AuthMethodTotpSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
new file mode 100644
index 000000000..30fc44f0e
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx
@@ -0,0 +1,105 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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 AuthMethodTotpSolve({ 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.currentReducerState.recovery_state === undefined
+ ) {
+ 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>
+ enter the totp solution
+ </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/AuthMethodVideoSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
index 3c4c7bf39..52e897c60 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx
@@ -25,7 +25,7 @@ import { authMethods as TestedComponent, KnownAuthMethods } from './index';
import logoImage from '../../../assets/logo.jpeg'
export default {
- title: 'Pages/backup/authMethods/Video',
+ title: 'Pages/backup/AuthorizationMethod/AuthMethods/Video',
component: TestedComponent,
args: {
order: 5,
@@ -38,11 +38,11 @@ export default {
const type: KnownAuthMethods = 'video'
-export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const Empty = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: []
});
-export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithOneExample = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
@@ -51,7 +51,7 @@ export const WithOneExample = createExample(TestedComponent[type].screen, reduce
}]
});
-export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+export const WithMoreExamples = createExample(TestedComponent[type].setup, reducerStatesExample.authEditing, {
configured: [{
challenge: 'qwe',
type,
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx
index 8be999b3f..22abe4a49 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
import {
encodeCrock,
stringToBytes
@@ -6,7 +5,7 @@ import {
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { ImageInput } from "../../../components/fields/ImageInput";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AuthMethodSetupProps } from "./index";
import { AnastasisClientFrame } from "../index";
export function AuthMethodVideoSetup({cancel, addAuthMethod, configured}: AuthMethodSetupProps): VNode {
diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx
new file mode 100644
index 000000000..5c4976b87
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx
@@ -0,0 +1,56 @@
+/*
+ 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 '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
new file mode 100644
index 000000000..79401028a
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx
@@ -0,0 +1,105 @@
+import { ChallengeFeedbackStatus, ChallengeInfo } from "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.currentReducerState.recovery_state === undefined
+ ) {
+ 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/index.tsx b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
index 7b0cce883..07f6ec206 100644
--- a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
+++ b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx
@@ -1,22 +1,44 @@
+import { AuthMethod } from "anastasis-core";
import { h, VNode } from "preact";
-import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
-
-import { AuthMethodEmailSetup as EmailScreen } from "./AuthMethodEmailSetup";
-import { AuthMethodIbanSetup as IbanScreen } from "./AuthMethodIbanSetup";
-import { AuthMethodPostSetup as PostalScreen } from "./AuthMethodPostSetup";
-import { AuthMethodQuestionSetup as QuestionScreen } from "./AuthMethodQuestionSetup";
-import { AuthMethodSmsSetup as SmsScreen } from "./AuthMethodSmsSetup";
-import { AuthMethodTotpSetup as TotpScreen } from "./AuthMethodTotpSetup";
-import { AuthMethodVideoSetup as VideScreen } from "./AuthMethodVideoSetup";
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 { AuthMethodPostSolve as PostalSolve } from "./AuthMethodPostSolve";
+import { AuthMethodQuestionSolve as QuestionSolve } from "./AuthMethodQuestionSolve";
+import { AuthMethodSmsSolve as SmsSolve } from "./AuthMethodSmsSolve";
+import { AuthMethodTotpSolve as TotpSolve } from "./AuthMethodTotpSolve";
+import { AuthMethodVideoSolve as VideoSolve } from "./AuthMethodVideoSolve";
+
+
+export type AuthMethodWithRemove = AuthMethod & { remove: () => void }
+
+export interface AuthMethodSetupProps {
+ method: string;
+ addAuthMethod: (x: any) => void;
+ configured: AuthMethodWithRemove[];
+ cancel: () => void;
+}
+
+export interface AuthMethodSolveProps {
+ id: string;
+}
interface AuthMethodConfiguration {
icon: VNode;
label: string;
- screen: (props: AuthMethodSetupProps) => VNode;
+ setup: (props: AuthMethodSetupProps) => VNode;
+ solve: (props: AuthMethodSolveProps) => VNode;
skip?: boolean;
}
export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";
@@ -29,41 +51,44 @@ export const authMethods: KnowMethodConfig = {
question: {
icon: <img src={questionIcon} />,
label: "Question",
- screen: QuestionScreen
+ setup: QuestionSetup,
+ solve: QuestionSolve,
},
sms: {
icon: <img src={smsIcon} />,
label: "SMS",
- screen: SmsScreen
+ setup: SmsSetup,
+ solve: SmsSolve,
},
email: {
icon: <i class="mdi mdi-email" />,
label: "Email",
- screen: EmailScreen
-
+ setup: EmailSetup,
+ solve: EmailSolve,
},
iban: {
icon: <i class="mdi mdi-bank" />,
label: "IBAN",
- screen: IbanScreen
-
+ setup: IbanSetup,
+ solve: IbanSolve,
},
post: {
icon: <img src={postalIcon} />,
label: "Physical mail",
- screen: PostalScreen
-
+ setup: PostalSetup,
+ solve: PostalSolve,
},
totp: {
icon: <i class="mdi mdi-devices" />,
label: "TOTP",
- screen: TotpScreen
-
+ setup: TotpSetup,
+ solve: TotpSolve,
},
video: {
icon: <img src={videoIcon} />,
label: "Video",
- screen: VideScreen,
- skip: true,
+ setup: VideoSetup,
+ solve: VideoSolve,
+ skip: true,
}
} \ No newline at end of file