refactoring challenge overview to look more like policy reviewing
This commit is contained in:
parent
aa78c1105e
commit
1fd337f4fe
@ -3,7 +3,7 @@ import { AuthMethod } from "anastasis-core";
|
|||||||
import { ComponentChildren, h, VNode } from "preact";
|
import { ComponentChildren, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { authMethods, KnownAuthMethods } from "./authMethodSetup";
|
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,17 +56,17 @@ export const SomePoliciesOneSolved = createExample(TestedComponent, {
|
|||||||
policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]],
|
policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]],
|
||||||
challenges: [{
|
challenges: [{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'just go for it',
|
instructions: 'this question cost 1 USD',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '1',
|
uuid: '1',
|
||||||
}, {
|
}, {
|
||||||
cost: 'USD:1',
|
cost: 'USD:0',
|
||||||
instructions: 'just go for it',
|
instructions: 'answering this question is free',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '2',
|
uuid: '2',
|
||||||
}, {
|
}, {
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'just go for it',
|
instructions: 'this question is already answered',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: 'uuid-3',
|
uuid: 'uuid-3',
|
||||||
}]
|
}]
|
||||||
@ -84,8 +84,8 @@ export const OneBadConfiguredPolicy = createExample(TestedComponent, {
|
|||||||
policies: [[{ uuid: '1' }, { uuid: '2' }]],
|
policies: [[{ uuid: '1' }, { uuid: '2' }]],
|
||||||
challenges: [{
|
challenges: [{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'just go for it',
|
instructions: 'this policy has a missing uuid (the other auth method)',
|
||||||
type: 'sasd',
|
type: 'totp',
|
||||||
uuid: '1',
|
uuid: '1',
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
@ -101,35 +101,48 @@ export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
|
|||||||
{ uuid: '4' },
|
{ uuid: '4' },
|
||||||
{ uuid: '5' },
|
{ uuid: '5' },
|
||||||
{ uuid: '6' },
|
{ uuid: '6' },
|
||||||
|
{ uuid: '7' },
|
||||||
|
{ uuid: '8' },
|
||||||
]],
|
]],
|
||||||
challenges: [{
|
challenges: [{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'Does P equals NP?',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '1',
|
uuid: '1',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'enter a text received by a sms',
|
instructions: 'SMS to 555-555',
|
||||||
type: 'sms',
|
type: 'sms',
|
||||||
uuid: '2',
|
uuid: '2',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'enter a text received by a email',
|
instructions: 'Email to qwe@asd.com',
|
||||||
type: 'email',
|
type: 'email',
|
||||||
uuid: '3',
|
uuid: '3',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'enter a code based on a time-based one-time password',
|
instructions: 'Enter 8 digits code for "Anastasis"',
|
||||||
type: 'totp',
|
type: 'totp',
|
||||||
uuid: '4',
|
uuid: '4',
|
||||||
},{
|
},{//
|
||||||
cost: 'USD:1',
|
cost: 'USD:0',
|
||||||
instructions: 'send a wire transfer to an account',
|
instructions: 'Wire transfer from ASDXCVQWE123123 with holder Florian',
|
||||||
type: 'iban',
|
type: 'iban',
|
||||||
uuid: '5',
|
uuid: '5',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'just go for it',
|
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',
|
type: 'new-type-of-challenge',
|
||||||
uuid: '6',
|
uuid: '6',
|
||||||
}],
|
}],
|
||||||
@ -154,52 +167,52 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(Teste
|
|||||||
]],
|
]],
|
||||||
challenges: [{
|
challenges: [{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "solved"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '1',
|
uuid: '1',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "hint"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '2',
|
uuid: '2',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "details"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '3',
|
uuid: '3',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "body"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '4',
|
uuid: '4',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "redirect"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '5',
|
uuid: '5',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "server-failure"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '6',
|
uuid: '6',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "truth-unknown"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '7',
|
uuid: '7',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "rate-limit-exceeded"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '8',
|
uuid: '8',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "authentication-timeout"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '9',
|
uuid: '9',
|
||||||
},{
|
},{
|
||||||
cost: 'USD:1',
|
cost: 'USD:1',
|
||||||
instructions: 'answer the a question correctly',
|
instructions: 'in state "external-instructions"',
|
||||||
type: 'question',
|
type: 'question',
|
||||||
uuid: '10',
|
uuid: '10',
|
||||||
}],
|
}],
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/camelcase */
|
||||||
import { ChallengeFeedback } from "anastasis-core";
|
import { ChallengeFeedback } from "anastasis-core";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
|
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||||
|
|
||||||
export function ChallengeOverviewScreen(): VNode {
|
export function ChallengeOverviewScreen(): VNode {
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext()
|
||||||
@ -50,59 +52,61 @@ export function ChallengeOverviewScreen(): VNode {
|
|||||||
const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined;
|
const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined;
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
|
<AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
|
||||||
{!policies.length ? <p>
|
{!policies.length ? <p class="block">
|
||||||
No policies found, try with another version of the secret
|
No policies found, try with another version of the secret
|
||||||
</p> : (policies.length === 1 ? <p>
|
</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.
|
One policy found for this secret. You need to solve all the challenges in order to recover your secret.
|
||||||
</p> : <p>
|
</p> : <p class="block">
|
||||||
We have found {policies.length} polices. You need to solve all the challenges from one policy in order
|
We have found {policies.length} polices. You need to solve all the challenges from one policy in order
|
||||||
to recover your secret.
|
to recover your secret.
|
||||||
</p>)}
|
</p>)}
|
||||||
{policiesWithInfo.map((row, i) => {
|
{policiesWithInfo.map((policy, policy_index) => {
|
||||||
const tableBody = row.challenges.map(({ info, uuid }) => {
|
const tableBody = policy.challenges.map(({ info, uuid }) => {
|
||||||
|
const isFree = !info.cost || info.cost.endsWith(':0')
|
||||||
|
const method = authMethods[info.type as KnownAuthMethods]
|
||||||
return (
|
return (
|
||||||
<tr key={uuid}>
|
<div key={uuid} class="block" style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<td>{info.type}</td>
|
<div style={{display:'flex', alignItems:'center'}}>
|
||||||
<td>
|
<span class="icon">
|
||||||
{info.instructions}
|
{method?.icon}
|
||||||
</td>
|
</span>
|
||||||
<td>{info.feedback?.state ?? "unknown"}</td>
|
<span>
|
||||||
<td>{info.cost}</td>
|
{info.instructions}
|
||||||
<td>
|
</span>
|
||||||
{info.feedback?.state !== "solved" ? (
|
</div>
|
||||||
<a onClick={() => reducer.transition("select_challenge", { uuid })}>
|
<div>
|
||||||
Solve
|
{method && info.feedback?.state !== "solved" ? (
|
||||||
|
<a class="button" onClick={() => reducer.transition("select_challenge", { uuid })}>
|
||||||
|
{isFree ? "Solve" : `Pay and Solve`}
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
</td>
|
{info.feedback?.state === "solved" ? (
|
||||||
</tr>
|
<a class="button is-success"> Solved </a>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const policyName = policy.challenges.map(x => x.info.type).join(" + ");
|
||||||
|
const opa = !atLeastThereIsOnePolicySolved ? undefined : ( policy.isPolicySolved ? undefined : '0.6')
|
||||||
return (
|
return (
|
||||||
<div key={i}>
|
<div key={policy_index} class="box" style={{
|
||||||
<b>Policy #{i + 1}</b>
|
opacity: opa
|
||||||
{row.challenges.length === 0 && <p>
|
}}>
|
||||||
This policy doesn't have challenges
|
<h3 class="subtitle">
|
||||||
|
Policy #{policy_index + 1}: {policyName}
|
||||||
|
</h3>
|
||||||
|
{policy.challenges.length === 0 && <p>
|
||||||
|
This policy doesn't have challenges.
|
||||||
</p>}
|
</p>}
|
||||||
{row.challenges.length === 1 && <p>
|
{policy.challenges.length === 1 && <p>
|
||||||
This policy just have one challenge to be solved
|
This policy just have one challenge.
|
||||||
</p>}
|
</p>}
|
||||||
{row.challenges.length > 1 && <p>
|
{policy.challenges.length > 1 && <p>
|
||||||
This policy have {row.challenges.length} challenges
|
This policy have {policy.challenges.length} challenges.
|
||||||
</p>}
|
</p>}
|
||||||
<table class="table">
|
{tableBody}
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td>Challenge type</td>
|
|
||||||
<td>Description</td>
|
|
||||||
<td>Status</td>
|
|
||||||
<td>Cost</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{tableBody}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
import { authMethods, KnownAuthMethods } from "./authMethodSetup";
|
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||||
|
|
||||||
export function ReviewPoliciesScreen(): VNode {
|
export function ReviewPoliciesScreen(): VNode {
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext()
|
||||||
|
@ -51,7 +51,7 @@ export function AuthMethodEmailSetup({ cancel, addAuthMethod, configured }: Auth
|
|||||||
</div></section>}
|
</div></section>}
|
||||||
<div>
|
<div>
|
||||||
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<button class="button" onClick={cancel}>Canceul</button>
|
<button class="button" onClick={cancel}>Cancel</button>
|
||||||
<span data-tooltip={errors}>
|
<span data-tooltip={errors}>
|
||||||
<button class="button is-info" disabled={errors !== undefined} onClick={addEmailAuth}>Add</button>
|
<button class="button is-info" disabled={errors !== undefined} onClick={addEmailAuth}>Add</button>
|
||||||
</span>
|
</span>
|
@ -25,7 +25,7 @@ export function AuthMethodTotpSetup({ addAuthMethod, cancel, configured }: AuthM
|
|||||||
const addTotpAuth = (): void => addAuthMethod({
|
const addTotpAuth = (): void => addAuthMethod({
|
||||||
authentication_method: {
|
authentication_method: {
|
||||||
type: "totp",
|
type: "totp",
|
||||||
instructions: `Enter ${digits} digits code for ${name}`,
|
instructions: `Enter ${digits} digits code for "${name}"`,
|
||||||
challenge: encodeCrock(stringToBytes(totpURL)),
|
challenge: encodeCrock(stringToBytes(totpURL)),
|
||||||
},
|
},
|
||||||
});
|
});
|
@ -15,7 +15,7 @@ export function AuthMethodVideoSetup({cancel, addAuthMethod, configured}: AuthMe
|
|||||||
addAuthMethod({
|
addAuthMethod({
|
||||||
authentication_method: {
|
authentication_method: {
|
||||||
type: "video",
|
type: "video",
|
||||||
instructions: image,
|
instructions: 'Join a video call',
|
||||||
challenge: encodeCrock(stringToBytes(image)),
|
challenge: encodeCrock(stringToBytes(image)),
|
||||||
},
|
},
|
||||||
})
|
})
|
Loading…
Reference in New Issue
Block a user