aboutsummaryrefslogtreecommitdiff
path: root/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
diff options
context:
space:
mode:
authorBoss Marco <bossm8@bfh.ch>2021-11-05 16:57:32 +0100
committerBoss Marco <bossm8@bfh.ch>2021-11-05 16:57:32 +0100
commit98064f0652d8e1dff661e3bb0d8791f4af04ad6f (patch)
tree5d278fd1fab17b0c4b03cc89bcea678edd3789d3 /packages/anastasis-webui/src/pages/home/SolveScreen.tsx
parent8d9386ac008e9d095867433bfc789d09bd93414d (diff)
parent842cc327541ebcfc761208f42bf5f74e22c6283c (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.tsx220
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>
+ );
+}