diff options
Diffstat (limited to 'packages/anastasis-webui')
20 files changed, 71 insertions, 549 deletions
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 <http://www.gnu.org/licenses/> + */ + +/** + * Imports. + */  import { TalerErrorCode } from "@gnu-taler/taler-util";  import {    AggregatedPolicyMetaInfo, @@ -7,7 +26,6 @@ import {    getBackupStartState,    getRecoveryStartState,    mergeDiscoveryAggregate, -  PolicyMetaInfo,    RecoveryStates,    reduceAction,    ReducerState, diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx index 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 <div class="block has-text-danger">{feedback.message}</div>;      case ChallengeFeedbackStatus.Solved:        return <div />; -    case ChallengeFeedbackStatus.Pending:      case ChallengeFeedbackStatus.AuthIban:        return null;      case ChallengeFeedbackStatus.ServerFailure: @@ -43,7 +40,6 @@ function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {            provider for further information.          </div>        ); -    case ChallengeFeedbackStatus.Redirect:      default:        return <div />;    } @@ -178,7 +174,7 @@ export function ChallengeOverviewScreen(): VNode {                case ChallengeFeedbackStatus.RateLimitExceeded:                  return <div />;                case ChallengeFeedbackStatus.AuthIban: -              case ChallengeFeedbackStatus.Payment: +              case ChallengeFeedbackStatus.TalerPayment:                  return (                    <div>                      <AsyncButton @@ -192,20 +188,6 @@ export function ChallengeOverviewScreen(): VNode {                      </AsyncButton>                    </div>                  ); -              case ChallengeFeedbackStatus.Redirect: -                return ( -                  <div> -                    <AsyncButton -                      class="button" -                      disabled={ -                        atLeastThereIsOnePolicySolved && !policy.isPolicySolved -                      } -                      onClick={selectChallenge} -                    > -                      Go to {feedback.redirect_url} -                    </AsyncButton> -                  </div> -                );                case ChallengeFeedbackStatus.Solved:                  return (                    <div> diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx index 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 <div />;    }    switch (feedback.state) { -    case ChallengeFeedbackStatus.Message: -      return ( -        <Notifications -          notifications={[ -            { -              type: "INFO", -              message: `Message from provider`, -              description: feedback.message, -            }, -          ]} -        /> -      ); -    case ChallengeFeedbackStatus.Payment: +    case ChallengeFeedbackStatus.TalerPayment:        return (          <Notifications            notifications={[ @@ -51,7 +39,7 @@ export function SolveOverviewFeedbackDisplay(props: {              {                type: "INFO",                message: `Message from provider`, -              description: `Need to send a wire transfer to "${feedback.business_name}"`, +              description: `Need to send a wire transfer to "${feedback.target_business_name}"`,              },            ]}          /> @@ -80,22 +68,6 @@ export function SolveOverviewFeedbackDisplay(props: {            ]}          />        ); -    case ChallengeFeedbackStatus.Redirect: -      return ( -        <Notifications -          notifications={[ -            { -              type: "INFO", -              message: `Message from provider`, -              description: ( -                <span> -                  Please visit this link: <a>{feedback.redirect_url}</a> -                </span> -              ), -            }, -          ]} -        /> -      );      case ChallengeFeedbackStatus.Unsupported:        return (          <Notifications @@ -121,6 +93,9 @@ export function SolveOverviewFeedbackDisplay(props: {          />        );      default: +      console.warn( +        `unknown challenge feedback status ${JSON.stringify(feedback)}`, +      );        return <div />;    }  } diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx index 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 (      <AnastasisClientFrame hideNav title="Email challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -160,7 +155,7 @@ export function AuthMethodEmailSolve({ id }: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.tsx index 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 (      <AnastasisClientFrame hideNav title="IBAN Challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -101,7 +95,7 @@ export function AuthMethodIbanSolve({ id }: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.tsx index 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 (      <AnastasisClientFrame hideNav title="Postal Challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -130,7 +125,7 @@ export function AuthMethodPostSolve({ id }: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx index 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 (      <AnastasisClientFrame hideNav title="Question challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -110,7 +105,7 @@ export function AuthMethodQuestionSolve({ id }: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.tsx index 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 (      <AnastasisClientFrame hideNav title="SMS Challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -160,7 +155,7 @@ export function AuthMethodSmsSolve({ id }: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.tsx index 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 (      <AnastasisClientFrame hideNav title="TOTP Challenge">        <SolveOverviewFeedbackDisplay feedback={feedback} /> @@ -108,7 +103,7 @@ export function AuthMethodTotpSolve(props: AuthMethodSolveProps): VNode {          <button class="button" onClick={onCancel}>            Cancel          </button> -        {!shouldHideConfirm && ( +        {!shouldHideConfirm(feedback) && (            <AsyncButton class="button is-info" onClick={onNext}>              Confirm            </AsyncButton> diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx deleted file mode 100644 index 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 <http://www.gnu.org/licenses/> - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { createExample, reducerStatesExample } from "../../../utils"; -import { authMethods as TestedComponent, KnownAuthMethods } from "./index"; -import logoImage from "../../../assets/logo.jpeg"; - -export default { -  title: "Pages/backup/AuthorizationMethod/AuthMethods/Video", -  component: TestedComponent, -  args: { -    order: 5, -  }, -  argTypes: { -    onUpdate: { action: "onUpdate" }, -    onBack: { action: "onBack" }, -  }, -}; - -const type: KnownAuthMethods = "video"; - -export const Empty = createExample( -  TestedComponent[type].setup, -  reducerStatesExample.authEditing, -  { -    configured: [], -  }, -); - -export const WithOneExample = createExample( -  TestedComponent[type].setup, -  reducerStatesExample.authEditing, -  { -    configured: [ -      { -        challenge: "qwe", -        type, -        instructions: logoImage, -        remove: () => null, -      }, -    ], -  }, -); - -export const WithMoreExamples = createExample( -  TestedComponent[type].setup, -  reducerStatesExample.authEditing, -  { -    configured: [ -      { -        challenge: "qwe", -        type, -        instructions: logoImage, -        remove: () => null, -      }, -      { -        challenge: "qwe", -        type, -        instructions: logoImage, -        remove: () => null, -      }, -    ], -  }, -); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx deleted file mode 100644 index 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 ( -    <AnastasisClientFrame hideNav title="Add video authentication"> -      <p> -        For video identification, you need to provide a passport-style -        photograph. When recovering your secret, you will be asked to join a -        video call. During that call, a human will use the photograph to verify -        your identity. -      </p> -      <div style={{ textAlign: "center" }}> -        <ImageInput -          label="Choose photograph" -          grabFocus -          onConfirm={goNextIfNoErrors} -          bind={[image, setImage]} -        /> -      </div> -      {configured.length > 0 && ( -        <section class="section"> -          <div class="block">Your photographs:</div> -          <div class="block"> -            {configured.map((c, i) => { -              return ( -                <div -                  key={i} -                  class="box" -                  style={{ display: "flex", justifyContent: "space-between" }} -                > -                  <img -                    style={{ -                      marginTop: "auto", -                      marginBottom: "auto", -                      width: 100, -                      height: 100, -                      border: "solid 1px black", -                    }} -                    src={c.instructions} -                  /> -                  <div style={{ marginTop: "auto", marginBottom: "auto" }}> -                    <button class="button is-danger" onClick={c.remove}> -                      Delete -                    </button> -                  </div> -                </div> -              ); -            })} -          </div> -        </section> -      )} -      <div> -        <div -          style={{ -            marginTop: "2em", -            display: "flex", -            justifyContent: "space-between", -          }} -        > -          <button class="button" onClick={cancel}> -            Cancel -          </button> -          <button class="button is-info" onClick={addVideoAuth}> -            Add -          </button> -        </div> -      </div> -    </AnastasisClientFrame> -  ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.stories.tsx deleted file mode 100644 index 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 <http://www.gnu.org/licenses/> - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { -  ChallengeFeedbackStatus, -  ReducerState, -} from "@gnu-taler/anastasis-core"; -import { createExample, reducerStatesExample } from "../../../utils"; -import { authMethods as TestedComponent, KnownAuthMethods } from "./index"; - -export default { -  title: "Pages/recovery/SolveChallenge/AuthMethods/video", -  component: TestedComponent, -  args: { -    order: 5, -  }, -  argTypes: { -    onUpdate: { action: "onUpdate" }, -    onBack: { action: "onBack" }, -  }, -}; - -const type: KnownAuthMethods = "video"; - -export const WithoutFeedback = createExample( -  TestedComponent[type].solve, -  { -    ...reducerStatesExample.challengeSolving, -    recovery_information: { -      challenges: [ -        { -          cost: "USD:1", -          instructions: "does P equals NP?", -          type: "question", -          uuid: "uuid-1", -        }, -      ], -      policies: [], -    }, -    selected_challenge_uuid: "uuid-1", -  } as ReducerState, -  { -    id: "uuid-1", -  }, -); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSolve.tsx deleted file mode 100644 index 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 ( -      <AnastasisClientFrame hideNav title="Recovery problem"> -        <div>no reducer in context</div> -      </AnastasisClientFrame> -    ); -  } -  if ( -    reducer.currentReducerState?.reducer_type !== "recovery" -  ) { -    return ( -      <AnastasisClientFrame hideNav title="Recovery problem"> -        <div>invalid state</div> -      </AnastasisClientFrame> -    ); -  } - -  if (!reducer.currentReducerState.recovery_information) { -    return ( -      <AnastasisClientFrame -        hideNext="Recovery document not found" -        title="Recovery problem" -      > -        <div>no recovery information found</div> -      </AnastasisClientFrame> -    ); -  } -  if (!reducer.currentReducerState.selected_challenge_uuid) { -    return ( -      <AnastasisClientFrame hideNav title="Recovery problem"> -        <div>invalid state</div> -        <div -          style={{ -            marginTop: "2em", -            display: "flex", -            justifyContent: "space-between", -          }} -        > -          <button class="button" onClick={() => reducer.back()}> -            Back -          </button> -        </div> -      </AnastasisClientFrame> -    ); -  } - -  const chArr = reducer.currentReducerState.recovery_information.challenges; -  const challengeFeedback = -    reducer.currentReducerState.challenge_feedback ?? {}; -  const selectedUuid = reducer.currentReducerState.selected_challenge_uuid; -  const challenges: { -    [uuid: string]: ChallengeInfo; -  } = {}; -  for (const ch of chArr) { -    challenges[ch.uuid] = ch; -  } -  const selectedChallenge = challenges[selectedUuid]; -  const feedback = challengeFeedback[selectedUuid]; - -  async function onNext(): Promise<void> { -    return reducer?.transition("solve_challenge", { answer }); -  } -  function onCancel(): void { -    reducer?.back(); -  } - -  const shouldHideConfirm = -    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded || -    feedback?.state === ChallengeFeedbackStatus.Redirect || -    feedback?.state === ChallengeFeedbackStatus.Unsupported || -    feedback?.state === ChallengeFeedbackStatus.TruthUnknown; - -  return ( -    <AnastasisClientFrame hideNav title="Add email authentication"> -      <SolveOverviewFeedbackDisplay feedback={feedback} /> -      <p>You are gonna be called to check your identity</p> -      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} /> - -      <div -        style={{ -          marginTop: "2em", -          display: "flex", -          justifyContent: "space-between", -        }} -      > -        <button class="button" onClick={onCancel}> -          Cancel -        </button> -        {!shouldHideConfirm && ( -          <AsyncButton class="button is-info" onClick={onNext}> -            Confirm -          </AsyncButton> -        )} -      </div> -    </AnastasisClientFrame> -  ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts b/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts new file mode 100644 index 000000000..2f5e3773e --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/helpers.ts @@ -0,0 +1,12 @@ +import { +  ChallengeFeedback, +  ChallengeFeedbackStatus, +} from "@gnu-taler/anastasis-core"; + +export function shouldHideConfirm(feedback: ChallengeFeedback): boolean { +  return ( +    feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded || +    feedback?.state === ChallengeFeedbackStatus.Unsupported || +    feedback?.state === ChallengeFeedbackStatus.TruthUnknown +  ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx index 64cf07cd6..a1ab9cd28 100644 --- a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx +++ b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx @@ -3,22 +3,18 @@ import { h, VNode } from "preact";  import postalIcon from "../../../assets/icons/auth_method/postal.svg";  import questionIcon from "../../../assets/icons/auth_method/question.svg";  import smsIcon from "../../../assets/icons/auth_method/sms.svg"; -import videoIcon from "../../../assets/icons/auth_method/video.svg";  import { AuthMethodEmailSetup as EmailSetup } from "./AuthMethodEmailSetup";  import { AuthMethodEmailSolve as EmailSolve } from "./AuthMethodEmailSolve";  import { AuthMethodIbanSetup as IbanSetup } from "./AuthMethodIbanSetup"; -import { AuthMethodPostSetup as PostalSetup } from "./AuthMethodPostSetup"; -import { AuthMethodQuestionSetup as QuestionSetup } from "./AuthMethodQuestionSetup"; -import { AuthMethodSmsSetup as SmsSetup } from "./AuthMethodSmsSetup"; -import { AuthMethodTotpSetup as TotpSetup } from "./AuthMethodTotpSetup"; -import { AuthMethodVideoSetup as VideoSetup } from "./AuthMethodVideoSetup"; -  import { AuthMethodIbanSolve as IbanSolve } from "./AuthMethodIbanSolve"; +import { AuthMethodPostSetup as PostalSetup } from "./AuthMethodPostSetup";  import { AuthMethodPostSolve as PostalSolve } from "./AuthMethodPostSolve"; +import { AuthMethodQuestionSetup as QuestionSetup } from "./AuthMethodQuestionSetup";  import { AuthMethodQuestionSolve as QuestionSolve } from "./AuthMethodQuestionSolve"; +import { AuthMethodSmsSetup as SmsSetup } from "./AuthMethodSmsSetup";  import { AuthMethodSmsSolve as SmsSolve } from "./AuthMethodSmsSolve"; +import { AuthMethodTotpSetup as TotpSetup } from "./AuthMethodTotpSetup";  import { AuthMethodTotpSolve as TotpSolve } from "./AuthMethodTotpSolve"; -import { AuthMethodVideoSolve as VideoSolve } from "./AuthMethodVideoSolve";  export type AuthMethodWithRemove = AuthMethod & { remove: () => void }; @@ -40,14 +36,12 @@ interface AuthMethodConfiguration {    solve: (props: AuthMethodSolveProps) => VNode;    skip?: boolean;  } -// export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";  const ALL_METHODS = [    "sms",    "email",    "post",    "question", -  "video",    "totp",    "iban",  ] as const; @@ -97,11 +91,4 @@ export const authMethods: KnowMethodConfig = {      setup: TotpSetup,      solve: TotpSolve,    }, -  video: { -    icon: <img src={videoIcon} />, -    label: "Video", -    setup: VideoSetup, -    solve: VideoSolve, -    skip: true, -  },  };  | 
