anastasis-webui: make it compile again

This commit is contained in:
Florian Dold 2021-11-03 18:26:57 +01:00
parent 04356cd23f
commit 7d24d2254b
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
5 changed files with 265 additions and 236 deletions

View File

@ -96,6 +96,7 @@ const { fetch } = fetchPonyfill({});
export * from "./reducer-types.js";
export * as validators from "./validators.js";
export * from "./challenge-feedback-types.js";
const logger = new Logger("anastasis-core:index.ts");

View File

@ -16,218 +16,201 @@
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { RecoveryStates, ReducerState } from 'anastasis-core';
import { createExample, reducerStatesExample } from '../../utils';
import { ChallengeOverviewScreen as TestedComponent } from './ChallengeOverviewScreen';
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { RecoveryStates, ReducerState } from "anastasis-core";
import { createExample, reducerStatesExample } from "../../utils";
import { ChallengeOverviewScreen as TestedComponent } from "./ChallengeOverviewScreen";
export default {
title: 'Pages/recovery/ChallengeOverviewScreen',
title: "Pages/recovery/ChallengeOverviewScreen",
component: TestedComponent,
args: {
order: 5,
},
argTypes: {
onUpdate: { action: 'onUpdate' },
onBack: { action: 'onBack' },
onUpdate: { action: "onUpdate" },
onBack: { action: "onBack" },
},
};
export const OneUnsolvedPolicy = createExample(TestedComponent, {
...reducerStatesExample.challengeSelecting,
recovery_information: {
policies: [[{ uuid: '1' }]],
challenges: [{
cost: 'USD:1',
instructions: 'just go for it',
type: 'question',
uuid: '1',
}]
policies: [[{ uuid: "1" }]],
challenges: [
{
cost: "USD:1",
instructions: "just go for it",
type: "question",
uuid: "1",
},
],
},
} as ReducerState);
export const SomePoliciesOneSolved = createExample(TestedComponent, {
...reducerStatesExample.challengeSelecting,
recovery_information: {
policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]],
challenges: [{
cost: 'USD:1',
instructions: 'this question cost 1 USD',
type: 'question',
uuid: '1',
}, {
cost: 'USD:0',
instructions: 'answering this question is free',
type: 'question',
uuid: '2',
}, {
cost: 'USD:1',
instructions: 'this question is already answered',
type: 'question',
uuid: 'uuid-3',
}]
policies: [[{ uuid: "1" }, { uuid: "2" }], [{ uuid: "uuid-3" }]],
challenges: [
{
cost: "USD:1",
instructions: "this question cost 1 USD",
type: "question",
uuid: "1",
},
{
cost: "USD:0",
instructions: "answering this question is free",
type: "question",
uuid: "2",
},
{
cost: "USD:1",
instructions: "this question is already answered",
type: "question",
uuid: "uuid-3",
},
],
},
challenge_feedback: {
'uuid-3': {
state: 'solved'
}
"uuid-3": {
state: "solved",
},
},
} as ReducerState);
export const OneBadConfiguredPolicy = createExample(TestedComponent, {
...reducerStatesExample.challengeSelecting,
recovery_information: {
policies: [[{ uuid: '1' }, { uuid: '2' }]],
challenges: [{
cost: 'USD:1',
instructions: 'this policy has a missing uuid (the other auth method)',
type: 'totp',
uuid: '1',
}],
policies: [[{ uuid: "1" }, { uuid: "2" }]],
challenges: [
{
cost: "USD:1",
instructions: "this policy has a missing uuid (the other auth method)",
type: "totp",
uuid: "1",
},
],
},
} as ReducerState);
export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
...reducerStatesExample.challengeSelecting,
recovery_information: {
policies: [[
{ uuid: '1' },
{ uuid: '2' },
{ uuid: '3' },
{ uuid: '4' },
{ uuid: '5' },
{ uuid: '6' },
{ uuid: '7' },
{ uuid: '8' },
]],
challenges: [{
cost: 'USD:1',
instructions: 'Does P equals NP?',
type: 'question',
uuid: '1',
},{
cost: 'USD:1',
instructions: 'SMS to 555-555',
type: 'sms',
uuid: '2',
},{
cost: 'USD:1',
instructions: 'Email to qwe@asd.com',
type: 'email',
uuid: '3',
},{
cost: 'USD:1',
instructions: 'Enter 8 digits code for "Anastasis"',
type: 'totp',
uuid: '4',
},{//
cost: 'USD:0',
instructions: 'Wire transfer from ASDXCVQWE123123 with holder Florian',
type: 'iban',
uuid: '5',
},{
cost: 'USD:1',
instructions: 'Join a video call',
type: 'video',//Enter 8 digits code for "Anastasis"
uuid: '7',
},{
},{
cost: 'USD:1',
instructions: 'Letter to address in postal code DE123123',
type: 'post',//Enter 8 digits code for "Anastasis"
uuid: '8',
},{
cost: 'USD:1',
instructions: 'instruction for an unknown type of challenge',
type: 'new-type-of-challenge',
uuid: '6',
}],
policies: [
[
{ uuid: "1" },
{ uuid: "2" },
{ uuid: "3" },
{ uuid: "4" },
{ uuid: "5" },
{ uuid: "6" },
{ uuid: "7" },
{ uuid: "8" },
],
],
challenges: [
{
cost: "USD:1",
instructions: "Does P equals NP?",
type: "question",
uuid: "1",
},
{
cost: "USD:1",
instructions: "SMS to 555-555",
type: "sms",
uuid: "2",
},
{
cost: "USD:1",
instructions: "Email to qwe@asd.com",
type: "email",
uuid: "3",
},
{
cost: "USD:1",
instructions: 'Enter 8 digits code for "Anastasis"',
type: "totp",
uuid: "4",
},
{
//
cost: "USD:0",
instructions: "Wire transfer from ASDXCVQWE123123 with holder Florian",
type: "iban",
uuid: "5",
},
{
cost: "USD:1",
instructions: "Join a video call",
type: "video", //Enter 8 digits code for "Anastasis"
uuid: "7",
},
{},
{
cost: "USD:1",
instructions: "Letter to address in postal code DE123123",
type: "post", //Enter 8 digits code for "Anastasis"
uuid: "8",
},
{
cost: "USD:1",
instructions: "instruction for an unknown type of challenge",
type: "new-type-of-challenge",
uuid: "6",
},
],
},
} as ReducerState);
export const OnePolicyWithAllTheChallengesInDifferentState = createExample(TestedComponent, {
...reducerStatesExample.challengeSelecting,
recovery_information: {
policies: [[
{ uuid: '1' },
{ uuid: '2' },
{ uuid: '3' },
{ uuid: '4' },
{ uuid: '5' },
{ uuid: '6' },
{ uuid: '7' },
{ uuid: '8' },
{ uuid: '9' },
{ uuid: '10' },
]],
challenges: [{
cost: 'USD:1',
instructions: 'in state "solved"',
type: 'question',
uuid: '1',
},{
cost: 'USD:1',
instructions: 'in state "hint"',
type: 'question',
uuid: '2',
},{
cost: 'USD:1',
instructions: 'in state "details"',
type: 'question',
uuid: '3',
},{
cost: 'USD:1',
instructions: 'in state "body"',
type: 'question',
uuid: '4',
},{
cost: 'USD:1',
instructions: 'in state "redirect"',
type: 'question',
uuid: '5',
},{
cost: 'USD:1',
instructions: 'in state "server-failure"',
type: 'question',
uuid: '6',
},{
cost: 'USD:1',
instructions: 'in state "truth-unknown"',
type: 'question',
uuid: '7',
},{
cost: 'USD:1',
instructions: 'in state "rate-limit-exceeded"',
type: 'question',
uuid: '8',
},{
cost: 'USD:1',
instructions: 'in state "authentication-timeout"',
type: 'question',
uuid: '9',
},{
cost: 'USD:1',
instructions: 'in state "external-instructions"',
type: 'question',
uuid: '10',
}],
},
challenge_feedback: {
1: { state: 'solved' },
2: { state: 'hint' },
3: { state: 'details' },
4: { state: 'body' },
5: { state: 'redirect' },
6: { state: 'server-failure' },
7: { state: 'truth-unknown' },
8: { state: 'rate-limit-exceeded' },
9: { state: 'authentication-timeout' },
10: { state: 'external-instructions' },
}
} as ReducerState);
export const NoPolicies = createExample(TestedComponent, reducerStatesExample.challengeSelecting);
export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
TestedComponent,
{
...reducerStatesExample.challengeSelecting,
recovery_state: RecoveryStates.ChallengeSelecting,
recovery_information: {
policies: [
[
{ uuid: "1" },
{ uuid: "2" },
{ uuid: "3" },
{ uuid: "4" },
{ uuid: "5" },
{ uuid: "6" },
{ uuid: "7" },
{ uuid: "8" },
{ uuid: "9" },
{ uuid: "10" },
],
],
challenges: [
{
cost: "USD:1",
instructions: 'in state "solved"',
type: "question",
uuid: "1",
},
{
cost: "USD:1",
instructions: 'in state "message"',
type: "question",
uuid: "2",
},
],
},
challenge_feedback: {
1: { state: "solved" },
2: { state: "message", message: "Security question was not solved correctly" },
// FIXME: add missing feedback states here!
},
} as ReducerState,
);
export const NoPolicies = createExample(
TestedComponent,
reducerStatesExample.challengeSelecting,
);

View File

@ -1,23 +1,29 @@
/* eslint-disable @typescript-eslint/camelcase */
import { ChallengeFeedback } from "anastasis-core";
import { ChallengeFeedback, ChallengeFeedbackStatus } from "anastasis-core";
import { h, VNode } from "preact";
import { useAnastasisContext } from "../../context/anastasis";
import { AnastasisClientFrame } from "./index";
import { authMethods, KnownAuthMethods } from "./authMethod";
export function ChallengeOverviewScreen(): VNode {
const reducer = useAnastasisContext()
const reducer = useAnastasisContext();
if (!reducer) {
return <div>no reducer in context</div>
return <div>no reducer in context</div>;
}
if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) {
return <div>invalid state</div>
if (
!reducer.currentReducerState ||
reducer.currentReducerState.recovery_state === undefined
) {
return <div>invalid state</div>;
}
const policies = reducer.currentReducerState.recovery_information?.policies ?? [];
const knownChallengesArray = reducer.currentReducerState.recovery_information?.challenges ?? [];
const challengeFeedback = reducer.currentReducerState?.challenge_feedback ?? {};
const policies =
reducer.currentReducerState.recovery_information?.policies ?? [];
const knownChallengesArray =
reducer.currentReducerState.recovery_information?.challenges ?? [];
const challengeFeedback =
reducer.currentReducerState?.challenge_feedback ?? {};
const knownChallengesMap: {
[uuid: string]: {
@ -32,51 +38,80 @@ export function ChallengeOverviewScreen(): VNode {
type: ch.type,
cost: ch.cost,
instructions: ch.instructions,
feedback: challengeFeedback[ch.uuid]
feedback: challengeFeedback[ch.uuid],
};
}
const policiesWithInfo = policies.map(row => {
let isPolicySolved = true
const challenges = row.map(({ uuid }) => {
const info = knownChallengesMap[uuid];
const isChallengeSolved = info?.feedback?.state === 'solved'
isPolicySolved = isPolicySolved && isChallengeSolved
return { info, uuid, isChallengeSolved }
}).filter(ch => ch.info !== undefined)
const policiesWithInfo = policies.map((row) => {
let isPolicySolved = true;
const challenges = row
.map(({ uuid }) => {
const info = knownChallengesMap[uuid];
const isChallengeSolved = info?.feedback?.state === "solved";
isPolicySolved = isPolicySolved && isChallengeSolved;
return { info, uuid, isChallengeSolved };
})
.filter((ch) => ch.info !== undefined);
return { isPolicySolved, challenges }
})
return { isPolicySolved, challenges };
});
const atLeastThereIsOnePolicySolved = policiesWithInfo.find(p => p.isPolicySolved) !== undefined
const atLeastThereIsOnePolicySolved =
policiesWithInfo.find((p) => p.isPolicySolved) !== undefined;
const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined;
const errors = !atLeastThereIsOnePolicySolved
? "Solve one policy before proceeding"
: undefined;
return (
<AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
{!policies.length ? <p class="block">
No policies found, try with another version of the secret
</p> : (policies.length === 1 ? <p class="block">
One policy found for this secret. You need to solve all the challenges in order to recover your secret.
</p> : <p class="block">
We have found {policies.length} polices. You need to solve all the challenges from one policy in order
to recover your secret.
</p>)}
{!policies.length ? (
<p class="block">
No policies found, try with another version of the secret
</p>
) : policies.length === 1 ? (
<p class="block">
One policy found for this secret. You need to solve all the challenges
in order to recover your secret.
</p>
) : (
<p class="block">
We have found {policies.length} polices. You need to solve all the
challenges from one policy in order to recover your secret.
</p>
)}
{policiesWithInfo.map((policy, policy_index) => {
const tableBody = policy.challenges.map(({ info, uuid }) => {
const isFree = !info.cost || info.cost.endsWith(':0')
const method = authMethods[info.type as KnownAuthMethods]
const isFree = !info.cost || info.cost.endsWith(":0");
const method = authMethods[info.type as KnownAuthMethods];
return (
<div key={uuid} class="block" style={{ display: 'flex', justifyContent: 'space-between' }}>
<div style={{display:'flex', alignItems:'center'}}>
<span class="icon">
{method?.icon}
</span>
<span>
{info.instructions}
</span>
<div
key={uuid}
class="block"
style={{ display: "flex", justifyContent: "space-between" }}
>
<div
style={{
display: "flex",
flexDirection: "column",
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
<span class="icon">{method?.icon}</span>
<span>{info.instructions}</span>
</div>
{info.feedback?.state === ChallengeFeedbackStatus.Message ? (
<div>
<p>{info.feedback.message}</p>
</div>
) : null}
</div>
<div>
{method && info.feedback?.state !== "solved" ? (
<a class="button" onClick={() => reducer.transition("select_challenge", { uuid })}>
<a
class="button"
onClick={() =>
reducer.transition("select_challenge", { uuid })
}
>
{isFree ? "Solve" : `Pay and Solve`}
</a>
) : null}
@ -86,26 +121,36 @@ export function ChallengeOverviewScreen(): VNode {
</div>
</div>
);
})
const policyName = policy.challenges.map(x => x.info.type).join(" + ");
const opa = !atLeastThereIsOnePolicySolved ? undefined : ( policy.isPolicySolved ? undefined : '0.6')
});
const policyName = policy.challenges
.map((x) => x.info.type)
.join(" + ");
const opa = !atLeastThereIsOnePolicySolved
? undefined
: policy.isPolicySolved
? undefined
: "0.6";
return (
<div key={policy_index} class="box" style={{
opacity: opa
}}>
<div
key={policy_index}
class="box"
style={{
opacity: opa,
}}
>
<h3 class="subtitle">
Policy #{policy_index + 1}: {policyName}
</h3>
{policy.challenges.length === 0 && <p>
This policy doesn't have challenges.
</p>}
{policy.challenges.length === 1 && <p>
This policy just have one challenge.
</p>}
{policy.challenges.length > 1 && <p>
This policy have {policy.challenges.length} challenges.
</p>}
{policy.challenges.length === 0 && (
<p>This policy doesn't have challenges.</p>
)}
{policy.challenges.length === 1 && (
<p>This policy just have one challenge.</p>
)}
{policy.challenges.length > 1 && (
<p>This policy have {policy.challenges.length} challenges.</p>
)}
{tableBody}
</div>
);

View File

@ -16,7 +16,7 @@ export function CountrySelectionScreen(): VNode {
currencies: [x.currency],
});
return (
<AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select Country")} >
<AnastasisClientFrame hideNext={"FIXME"} title={withProcessLabel(reducer, "Select Country")} >
<div style={{ display: 'flex', flexDirection: 'column' }}>
{reducer.currentReducerState.countries!.map((x: any) => (
<div key={x.name}>

View File

@ -13,7 +13,7 @@ export function TruthsPayingScreen(): VNode {
const payments = reducer.currentReducerState.payments ?? [];
return (
<AnastasisClientFrame
hideNext
hideNext={"FIXME"}
title="Backup: Truths Paying"
>
<p>