diff options
author | Boss Marco <bossm8@bfh.ch> | 2021-11-05 16:57:32 +0100 |
---|---|---|
committer | Boss Marco <bossm8@bfh.ch> | 2021-11-05 16:57:32 +0100 |
commit | 98064f0652d8e1dff661e3bb0d8791f4af04ad6f (patch) | |
tree | 5d278fd1fab17b0c4b03cc89bcea678edd3789d3 /packages/anastasis-webui/src/pages/home/SolveScreen.tsx | |
parent | 8d9386ac008e9d095867433bfc789d09bd93414d (diff) | |
parent | 842cc327541ebcfc761208f42bf5f74e22c6283c (diff) |
added some logging messages
Diffstat (limited to 'packages/anastasis-webui/src/pages/home/SolveScreen.tsx')
-rw-r--r-- | packages/anastasis-webui/src/pages/home/SolveScreen.tsx | 220 |
1 files changed, 202 insertions, 18 deletions
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx index 05ae50b48..bc1a88db3 100644 --- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx @@ -1,30 +1,93 @@ -import { h, VNode } from "preact"; -import { ChallengeFeedback, ChallengeInfo } from "../../../../anastasis-core/lib"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { AnastasisClientFrame } from "."; +import { + ChallengeFeedback, + ChallengeFeedbackStatus, + ChallengeInfo, +} from "../../../../anastasis-core/lib"; +import { AsyncButton } from "../../components/AsyncButton"; +import { TextInput } from "../../components/fields/TextInput"; import { useAnastasisContext } from "../../context/anastasis"; -import { SolveEmailEntry } from "./SolveEmailEntry"; -import { SolvePostEntry } from "./SolvePostEntry"; -import { SolveQuestionEntry } from "./SolveQuestionEntry"; -import { SolveSmsEntry } from "./SolveSmsEntry"; -import { SolveUnsupportedEntry } from "./SolveUnsupportedEntry"; + +function SolveOverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) { + const { feedback } = props; + if (!feedback) { + return null; + } + switch (feedback.state) { + case ChallengeFeedbackStatus.Message: + return ( + <div> + <p>{feedback.message}</p> + </div> + ); + case ChallengeFeedbackStatus.Pending: + case ChallengeFeedbackStatus.AuthIban: + return null; + case ChallengeFeedbackStatus.RateLimitExceeded: + return <div>Rate limit exceeded.</div>; + case ChallengeFeedbackStatus.Redirect: + return <div>Redirect (FIXME: not supported)</div>; + case ChallengeFeedbackStatus.Unsupported: + return <div>Challenge not supported by client.</div>; + case ChallengeFeedbackStatus.TruthUnknown: + return <div>Truth unknown</div>; + default: + return ( + <div> + <pre>{JSON.stringify(feedback)}</pre> + </div> + ); + } +} export function SolveScreen(): VNode { - const reducer = useAnastasisContext() + const reducer = useAnastasisContext(); + const [answer, setAnswer] = useState(""); if (!reducer) { - return <div>no reducer in context</div> + return ( + <AnastasisClientFrame hideNav title="Recovery problem"> + <div>no reducer in context</div> + </AnastasisClientFrame> + ); } - if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) { - return <div>invalid state</div> + 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 <div>no recovery information found</div> + return ( + <AnastasisClientFrame + hideNext="Recovery document not found" + title="Recovery problem" + > + <div>no recovery information found</div> + </AnastasisClientFrame> + ); } if (!reducer.currentReducerState.selected_challenge_uuid) { - return <div>no selected uuid</div> + 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 challengeFeedback = + reducer.currentReducerState.challenge_feedback ?? {}; const selectedUuid = reducer.currentReducerState.selected_challenge_uuid; const challenges: { [uuid: string]: ChallengeInfo; @@ -39,16 +102,137 @@ export function SolveScreen(): VNode { email: SolveEmailEntry, post: SolvePostEntry, }; - const SolveDialog = dialogMap[selectedChallenge?.type] ?? SolveUnsupportedEntry; + const SolveDialog = + selectedChallenge === undefined + ? SolveUndefinedEntry + : dialogMap[selectedChallenge.type] ?? SolveUnsupportedEntry; + + async function onNext(): Promise<void> { + return reducer?.transition("solve_challenge", { answer }); + } + function onCancel(): void { + reducer?.back(); + } + return ( - <SolveDialog - challenge={selectedChallenge} - feedback={challengeFeedback[selectedUuid]} /> + <AnastasisClientFrame hideNav title="Recovery: Solve challenge"> + <SolveOverviewFeedbackDisplay + feedback={challengeFeedback[selectedUuid]} + /> + <SolveDialog + id={selectedUuid} + answer={answer} + setAnswer={setAnswer} + challenge={selectedChallenge} + feedback={challengeFeedback[selectedUuid]} + /> + + <div + style={{ + marginTop: "2em", + display: "flex", + justifyContent: "space-between", + }} + > + <button class="button" onClick={onCancel}> + Cancel + </button> + <AsyncButton class="button is-info" onClick={onNext}> + Confirm + </AsyncButton> + </div> + </AnastasisClientFrame> ); } export interface SolveEntryProps { + id: string; challenge: ChallengeInfo; feedback?: ChallengeFeedback; + answer: string; + setAnswer: (s: string) => void; } +function SolveSmsEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { + return ( + <Fragment> + <p> + An sms has been sent to "<b>{challenge.instructions}</b>". Type the code + below + </p> + <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} /> + </Fragment> + ); +} +function SolveQuestionEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { + return ( + <Fragment> + <p>Type the answer to the following question:</p> + <pre>{challenge.instructions}</pre> + <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} /> + </Fragment> + ); +} + +function SolvePostEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { + return ( + <Fragment> + <p> + instruction for post type challenge "<b>{challenge.instructions}</b>" + </p> + <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} /> + </Fragment> + ); +} + +function SolveEmailEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { + return ( + <Fragment> + <p> + An email has been sent to "<b>{challenge.instructions}</b>". Type the + code below + </p> + <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} /> + </Fragment> + ); +} + +function SolveUnsupportedEntry(props: SolveEntryProps): VNode { + return ( + <Fragment> + <p> + The challenge selected is not supported for this UI. Please update this + version or try using another policy. + </p> + <p> + <b>Challenge type:</b> {props.challenge.type} + </p> + </Fragment> + ); +} +function SolveUndefinedEntry(props: SolveEntryProps): VNode { + return ( + <Fragment> + <p> + There is no challenge information for id <b>"{props.id}"</b>. Try + resetting the recovery session. + </p> + </Fragment> + ); +} |