testing provider screen
This commit is contained in:
parent
c87be3707e
commit
4ac0b23793
@ -0,0 +1,50 @@
|
||||
/* 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 { ReducerState } from 'anastasis-core';
|
||||
import { createExample, reducerStatesExample } from '../../utils';
|
||||
import { AddingProviderScreen as TestedComponent } from './AddingProviderScreen';
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Pages/backup/AddingProviderScreen',
|
||||
component: TestedComponent,
|
||||
args: {
|
||||
order: 4,
|
||||
},
|
||||
argTypes: {
|
||||
onUpdate: { action: 'onUpdate' },
|
||||
onBack: { action: 'onBack' },
|
||||
},
|
||||
};
|
||||
|
||||
export const NewProvider = createExample(TestedComponent, {
|
||||
...reducerStatesExample.authEditing,
|
||||
} as ReducerState);
|
||||
|
||||
export const NewSMSProvider = createExample(TestedComponent, {
|
||||
...reducerStatesExample.authEditing,
|
||||
} as ReducerState, { providerType: 'sms'});
|
||||
|
||||
export const NewIBANProvider = createExample(TestedComponent, {
|
||||
...reducerStatesExample.authEditing,
|
||||
} as ReducerState, { providerType: 'iban' });
|
101
packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx
Normal file
101
packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import {
|
||||
encodeCrock,
|
||||
stringToBytes
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { h, VNode } from "preact";
|
||||
import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||
import { TextInput } from "../../components/fields/TextInput";
|
||||
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||
import { AnastasisClientFrame } from "./index";
|
||||
|
||||
interface Props {
|
||||
providerType?: KnownAuthMethods;
|
||||
cancel: () => void;
|
||||
}
|
||||
export function AddingProviderScreen({ providerType, cancel }: Props): VNode {
|
||||
const [providerURL, setProviderURL] = useState("");
|
||||
const [error, setError] = useState<string | undefined>()
|
||||
const providerLabel = providerType ? authMethods[providerType].label : undefined
|
||||
|
||||
function testProvider(): void {
|
||||
setError(undefined)
|
||||
|
||||
fetch(`${providerURL}/config`)
|
||||
.then(r => r.json().catch(d => ({})))
|
||||
.then(r => {
|
||||
if (!("methods" in r) || !Array.isArray(r.methods)) {
|
||||
setError("This provider doesn't have authentication method. Check the provider URL")
|
||||
return;
|
||||
}
|
||||
if (!providerLabel) {
|
||||
setError("")
|
||||
return
|
||||
}
|
||||
let found = false
|
||||
for (let i = 0; i < r.methods.length && !found; i++) {
|
||||
found = r.methods[i].type !== providerType
|
||||
}
|
||||
if (!found) {
|
||||
setError(`This provider does not support authentication method ${providerLabel}`)
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
setError(`There was an error testing this provider, try another one. ${e.message}`)
|
||||
})
|
||||
|
||||
}
|
||||
function addProvider(): void {
|
||||
// addAuthMethod({
|
||||
// authentication_method: {
|
||||
// type: "sms",
|
||||
// instructions: `SMS to ${providerURL}`,
|
||||
// challenge: encodeCrock(stringToBytes(providerURL)),
|
||||
// },
|
||||
// });
|
||||
}
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
inputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
let errors = !providerURL ? 'Add provider URL' : undefined
|
||||
try {
|
||||
new URL(providerURL)
|
||||
} catch {
|
||||
errors = 'Check the URL'
|
||||
}
|
||||
if (!!error && !errors) {
|
||||
errors = error
|
||||
}
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav
|
||||
title={!providerLabel ? `Backup: Adding a provider` : `Backup: Adding a ${providerLabel} provider`}
|
||||
hideNext={errors}>
|
||||
<div>
|
||||
<p>
|
||||
Add a provider url {errors}
|
||||
</p>
|
||||
<div class="container">
|
||||
<TextInput
|
||||
label="Provider URL"
|
||||
placeholder="https://provider.com"
|
||||
grabFocus
|
||||
bind={[providerURL, setProviderURL]} />
|
||||
</div>
|
||||
{!!error && <p class="block has-text-danger">{error}</p>}
|
||||
{error === "" && <p class="block has-text-success">This provider worked!</p>}
|
||||
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
||||
<button class="button" onClick={testProvider}>TEST</button>
|
||||
</div>
|
||||
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
||||
<button class="button" onClick={cancel}>Cancel</button>
|
||||
<span data-tooltip={errors}>
|
||||
<button class="button is-info" disabled={errors !== undefined} onClick={addProvider}>Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</AnastasisClientFrame>
|
||||
);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { AuthMethod } from "anastasis-core";
|
||||
import { ComponentChildren, h, VNode } from "preact";
|
||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { TextInput } from "../../components/fields/TextInput";
|
||||
import { useAnastasisContext } from "../../context/anastasis";
|
||||
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||
import { AnastasisClientFrame } from "./index";
|
||||
@ -13,6 +14,7 @@ const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>
|
||||
export function AuthenticationEditorScreen(): VNode {
|
||||
const [noProvidersAck, setNoProvidersAck] = useState(false)
|
||||
const [selectedMethod, setSelectedMethod] = useState<KnownAuthMethods | undefined>(undefined);
|
||||
const [addingProvider, setAddingProvider] = useState<string | undefined>(undefined)
|
||||
|
||||
const reducer = useAnastasisContext()
|
||||
if (!reducer) {
|
||||
@ -62,36 +64,58 @@ export function AuthenticationEditorScreen(): VNode {
|
||||
};
|
||||
|
||||
const AuthSetup = authMethods[selectedMethod].screen ?? AuthMethodNotImplemented;
|
||||
return (
|
||||
return (<Fragment>
|
||||
<AuthSetup
|
||||
cancel={cancel}
|
||||
configured={camByType[selectedMethod] || []}
|
||||
addAuthMethod={addMethod}
|
||||
method={selectedMethod} />
|
||||
|
||||
{!authAvailableSet.has(selectedMethod) && <ConfirmModal active
|
||||
onCancel={cancel} description="No providers founds" label="Add a provider manually"
|
||||
onConfirm={() => {
|
||||
null
|
||||
}}
|
||||
>
|
||||
We have found no trusted cloud providers for your recovery secret. You can add a provider manually.
|
||||
To add a provider you must know the provider URL (e.g. https://provider.com)
|
||||
<p>
|
||||
<a>More about cloud providers</a>
|
||||
</p>
|
||||
</ConfirmModal>}
|
||||
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
if (addingProvider !== undefined) {
|
||||
return <div />
|
||||
}
|
||||
|
||||
function MethodButton(props: { method: KnownAuthMethods }): VNode {
|
||||
if (authMethods[props.method].skip) return <div />
|
||||
|
||||
return (
|
||||
<div class="block">
|
||||
<button
|
||||
style={{ justifyContent: 'space-between' }}
|
||||
class="button is-fullwidth"
|
||||
onClick={() => {
|
||||
if (!authAvailableSet.has(props.method)) {
|
||||
//open add sms dialog
|
||||
} else {
|
||||
setSelectedMethod(props.method);
|
||||
}
|
||||
if (reducer) reducer.dismissError();
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<span class="icon ">
|
||||
{authMethods[props.method].icon}
|
||||
</span>
|
||||
{authAvailableSet.has(props.method) ?
|
||||
<span>
|
||||
{authMethods[props.method].label}
|
||||
Add a {authMethods[props.method].label} challenge
|
||||
</span> :
|
||||
<span>
|
||||
Add a {authMethods[props.method].label} provider
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
{!authAvailableSet.has(props.method) &&
|
||||
<span class="icon has-text-danger" >
|
||||
@ -111,41 +135,34 @@ export function AuthenticationEditorScreen(): VNode {
|
||||
return (
|
||||
<AnastasisClientFrame title="Backup: Configure Authentication Methods" hideNext={errors}>
|
||||
<div class="columns">
|
||||
<div class="column is-half">
|
||||
<div class="column one-third">
|
||||
<div>
|
||||
{getKeys(authMethods).map(method => <MethodButton key={method} method={method} />)}
|
||||
</div>
|
||||
{authAvailableSet.size === 0 && <ConfirmModal active={!noProvidersAck} onCancel={() => setNoProvidersAck(true)} description="No providers founds" label="Add a provider manually">
|
||||
{authAvailableSet.size === 0 && <ConfirmModal active={!noProvidersAck}
|
||||
onCancel={() => setNoProvidersAck(true)} description="No providers founds" label="Add a provider manually"
|
||||
onConfirm={() => {
|
||||
null
|
||||
}}
|
||||
>
|
||||
We have found no trusted cloud providers for your recovery secret. You can add a provider manually.
|
||||
To add a provider you must know the provider URL (e.g. https://provider.com)
|
||||
<p>
|
||||
<a>More about cloud providers</a>
|
||||
</p>
|
||||
</ConfirmModal>}
|
||||
|
||||
{/* {haveMethodsConfigured && (
|
||||
configuredAuthMethods.map((x, i) => {
|
||||
return (
|
||||
<p key={i}>
|
||||
{x.type} ({x.instructions}){" "}
|
||||
<button class="button is-danger is-small"
|
||||
onClick={() => reducer.transition("delete_authentication", {
|
||||
authentication_method: i,
|
||||
})}
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</p>
|
||||
);
|
||||
})
|
||||
)} */}
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<div class="column two-third">
|
||||
<p class="block">
|
||||
When recovering your wallet, you will be asked to verify your identity via the methods you configure here.
|
||||
|
||||
<b>Explain the exclamation marks</b>
|
||||
|
||||
<a>Explain how to add providers</a>
|
||||
The list of authentication method is defined by the backup provider list.
|
||||
</p>
|
||||
<p class="block">
|
||||
<button class="button is-info">Manage the backup provider's list</button>
|
||||
</p>
|
||||
{authAvailableSet.size > 0 && <p class="block">
|
||||
We couldn't find provider for some of the authentication methods.
|
||||
</p>}
|
||||
</div>
|
||||
</div>
|
||||
</AnastasisClientFrame>
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { AuthMethod } from "anastasis-core";
|
||||
import { h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { useAnastasisContext } from "../../context/anastasis";
|
||||
@ -51,8 +50,8 @@ export function ReviewPoliciesScreen(): VNode {
|
||||
{policies.length < 1 && <p class="block">
|
||||
No policies had been created. Go back and add more authentication methods.
|
||||
</p>}
|
||||
<div class="block" onClick={() => setEditingPolicy(policies.length + 1)}>
|
||||
<button class="button is-success">Add new policy</button>
|
||||
<div class="block" style={{justifyContent:'flex-end'}} >
|
||||
<button class="button is-success" onClick={() => setEditingPolicy(policies.length + 1)}>Add new policy</button>
|
||||
</div>
|
||||
{policies.map((p, policy_index) => {
|
||||
const methods = p.methods
|
||||
|
@ -17,6 +17,7 @@ interface AuthMethodConfiguration {
|
||||
icon: VNode;
|
||||
label: string;
|
||||
screen: (props: AuthMethodSetupProps) => VNode;
|
||||
skip?: boolean;
|
||||
}
|
||||
export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";
|
||||
|
||||
@ -62,7 +63,7 @@ export const authMethods: KnowMethodConfig = {
|
||||
video: {
|
||||
icon: <img src={videoIcon} />,
|
||||
label: "Video",
|
||||
screen: VideScreen
|
||||
|
||||
screen: VideScreen,
|
||||
skip: true,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user