add provider/ remove provider
This commit is contained in:
parent
e369f26ec5
commit
7f6101a24d
@ -65,6 +65,8 @@ import {
|
|||||||
ActionArgsChangeVersion,
|
ActionArgsChangeVersion,
|
||||||
TruthMetaData,
|
TruthMetaData,
|
||||||
ActionArgsUpdatePolicy,
|
ActionArgsUpdatePolicy,
|
||||||
|
ActionArgsAddProvider,
|
||||||
|
ActionArgsDeleteProvider,
|
||||||
} from "./reducer-types.js";
|
} from "./reducer-types.js";
|
||||||
import fetchPonyfill from "fetch-ponyfill";
|
import fetchPonyfill from "fetch-ponyfill";
|
||||||
import {
|
import {
|
||||||
@ -1060,9 +1062,15 @@ async function recoveryEnterUserAttributes(
|
|||||||
args: ActionArgsEnterUserAttributes,
|
args: ActionArgsEnterUserAttributes,
|
||||||
): Promise<ReducerStateRecovery | ReducerStateError> {
|
): Promise<ReducerStateRecovery | ReducerStateError> {
|
||||||
// FIXME: validate attributes
|
// FIXME: validate attributes
|
||||||
|
const providerUrls = Object.keys(state.authentication_providers ?? {});
|
||||||
|
const newProviders = state.authentication_providers ?? {};
|
||||||
|
for (const url of providerUrls) {
|
||||||
|
newProviders[url] = await getProviderInfo(url);
|
||||||
|
}
|
||||||
const st: ReducerStateRecovery = {
|
const st: ReducerStateRecovery = {
|
||||||
...state,
|
...state,
|
||||||
identity_attributes: args.identity_attributes,
|
identity_attributes: args.identity_attributes,
|
||||||
|
authentication_providers: newProviders,
|
||||||
};
|
};
|
||||||
return downloadPolicy(st);
|
return downloadPolicy(st);
|
||||||
}
|
}
|
||||||
@ -1174,6 +1182,60 @@ function transitionRecoveryJump(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: doest the same that addProviderRecovery, but type are not generic enough
|
||||||
|
async function addProviderBackup(
|
||||||
|
state: ReducerStateBackup,
|
||||||
|
args: ActionArgsAddProvider,
|
||||||
|
): Promise<ReducerStateBackup> {
|
||||||
|
const info = await getProviderInfo(args.provider_url)
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
authentication_providers: {
|
||||||
|
...(state.authentication_providers ?? {}),
|
||||||
|
[args.provider_url]: info,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: doest the same that deleteProviderRecovery, but type are not generic enough
|
||||||
|
async function deleteProviderBackup(
|
||||||
|
state: ReducerStateBackup,
|
||||||
|
args: ActionArgsDeleteProvider,
|
||||||
|
): Promise<ReducerStateBackup> {
|
||||||
|
const authentication_providers = {... state.authentication_providers ?? {} }
|
||||||
|
delete authentication_providers[args.provider_url]
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
authentication_providers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addProviderRecovery(
|
||||||
|
state: ReducerStateRecovery,
|
||||||
|
args: ActionArgsAddProvider,
|
||||||
|
): Promise<ReducerStateRecovery> {
|
||||||
|
const info = await getProviderInfo(args.provider_url)
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
authentication_providers: {
|
||||||
|
...(state.authentication_providers ?? {}),
|
||||||
|
[args.provider_url]: info,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteProviderRecovery(
|
||||||
|
state: ReducerStateRecovery,
|
||||||
|
args: ActionArgsDeleteProvider,
|
||||||
|
): Promise<ReducerStateRecovery> {
|
||||||
|
const authentication_providers = {... state.authentication_providers ?? {} }
|
||||||
|
delete authentication_providers[args.provider_url]
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
authentication_providers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function addAuthentication(
|
async function addAuthentication(
|
||||||
state: ReducerStateBackup,
|
state: ReducerStateBackup,
|
||||||
args: ActionArgsAddAuthentication,
|
args: ActionArgsAddAuthentication,
|
||||||
@ -1408,6 +1470,8 @@ const backupTransitions: Record<
|
|||||||
...transitionBackupJump("back", BackupStates.UserAttributesCollecting),
|
...transitionBackupJump("back", BackupStates.UserAttributesCollecting),
|
||||||
...transition("add_authentication", codecForAny(), addAuthentication),
|
...transition("add_authentication", codecForAny(), addAuthentication),
|
||||||
...transition("delete_authentication", codecForAny(), deleteAuthentication),
|
...transition("delete_authentication", codecForAny(), deleteAuthentication),
|
||||||
|
...transition("add_provider", codecForAny(), addProviderBackup),
|
||||||
|
...transition("delete_provider", codecForAny(), deleteProviderBackup),
|
||||||
...transition("next", codecForAny(), nextFromAuthenticationsEditing),
|
...transition("next", codecForAny(), nextFromAuthenticationsEditing),
|
||||||
},
|
},
|
||||||
[BackupStates.PoliciesReviewing]: {
|
[BackupStates.PoliciesReviewing]: {
|
||||||
@ -1476,6 +1540,8 @@ const recoveryTransitions: Record<
|
|||||||
[RecoveryStates.SecretSelecting]: {
|
[RecoveryStates.SecretSelecting]: {
|
||||||
...transitionRecoveryJump("back", RecoveryStates.UserAttributesCollecting),
|
...transitionRecoveryJump("back", RecoveryStates.UserAttributesCollecting),
|
||||||
...transitionRecoveryJump("next", RecoveryStates.ChallengeSelecting),
|
...transitionRecoveryJump("next", RecoveryStates.ChallengeSelecting),
|
||||||
|
...transition("add_provider", codecForAny(), addProviderRecovery),
|
||||||
|
...transition("delete_provider", codecForAny(), deleteProviderRecovery),
|
||||||
...transition(
|
...transition(
|
||||||
"change_version",
|
"change_version",
|
||||||
codecForActionArgsChangeVersion(),
|
codecForActionArgsChangeVersion(),
|
||||||
|
@ -334,6 +334,14 @@ export const codecForActionArgsEnterUserAttributes = () =>
|
|||||||
.property("identity_attributes", codecForAny())
|
.property("identity_attributes", codecForAny())
|
||||||
.build("ActionArgsEnterUserAttributes");
|
.build("ActionArgsEnterUserAttributes");
|
||||||
|
|
||||||
|
export interface ActionArgsAddProvider {
|
||||||
|
provider_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ActionArgsDeleteProvider {
|
||||||
|
provider_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ActionArgsAddAuthentication {
|
export interface ActionArgsAddAuthentication {
|
||||||
authentication_method: {
|
authentication_method: {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -40,6 +40,12 @@ export const NewProvider = createExample(TestedComponent, {
|
|||||||
...reducerStatesExample.authEditing,
|
...reducerStatesExample.authEditing,
|
||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
|
|
||||||
|
export const NewProviderWithoutProviderList = createExample(TestedComponent, {
|
||||||
|
...reducerStatesExample.authEditing,
|
||||||
|
authentication_providers: {}
|
||||||
|
} as ReducerState);
|
||||||
|
|
||||||
export const NewVideoProvider = createExample(TestedComponent, {
|
export const NewVideoProvider = createExample(TestedComponent, {
|
||||||
...reducerStatesExample.authEditing,
|
...reducerStatesExample.authEditing,
|
||||||
} as ReducerState, { providerType: 'video'});
|
} as ReducerState, { providerType: 'video'});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { AuthenticationProviderStatusOk } from "anastasis-core";
|
import { AuthenticationProviderStatusOk } from "anastasis-core";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
import { TextInput } from "../../components/fields/TextInput";
|
import { TextInput } from "../../components/fields/TextInput";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { authMethods, KnownAuthMethods } from "./authMethod";
|
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||||
@ -8,13 +8,13 @@ import { AnastasisClientFrame } from "./index";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
providerType?: KnownAuthMethods;
|
providerType?: KnownAuthMethods;
|
||||||
cancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function testProvider(url: string, expectedMethodType?: string): Promise<void> {
|
async function testProvider(url: string, expectedMethodType?: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${url}/config`)
|
const response = await fetch(new URL("config", url).href)
|
||||||
const json = await (response.json().catch(d => ({})))
|
const json = await (response.json().catch(d => ({})))
|
||||||
if (!("methods" in json) || !Array.isArray(json.methods)) {
|
if (!("methods" in json) || !Array.isArray(json.methods)) {
|
||||||
throw Error("This provider doesn't have authentication method. Check the provider URL")
|
throw Error("This provider doesn't have authentication method. Check the provider URL")
|
||||||
@ -41,7 +41,7 @@ async function testProvider(url: string, expectedMethodType?: string): Promise<v
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddingProviderScreen({ providerType, cancel }: Props): VNode {
|
export function AddingProviderScreen({ providerType, onCancel }: Props): VNode {
|
||||||
const reducer = useAnastasisContext();
|
const reducer = useAnastasisContext();
|
||||||
|
|
||||||
const [providerURL, setProviderURL] = useState("");
|
const [providerURL, setProviderURL] = useState("");
|
||||||
@ -54,8 +54,8 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timeout) window.clearTimeout(timeout.current)
|
if (timeout) window.clearTimeout(timeout.current)
|
||||||
timeout.current = window.setTimeout(async () => {
|
timeout.current = window.setTimeout(async () => {
|
||||||
const url = providerURL.endsWith('/') ? providerURL.substring(0, providerURL.length - 1) : providerURL
|
const url = providerURL.endsWith('/') ? providerURL : (providerURL + '/')
|
||||||
if (!url) return;
|
if (!providerURL || authProviders.includes(url)) return;
|
||||||
try {
|
try {
|
||||||
setTesting(true)
|
setTesting(true)
|
||||||
await testProvider(url, providerType)
|
await testProvider(url, providerType)
|
||||||
@ -67,40 +67,50 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode {
|
|||||||
if (e instanceof Error) setError(e.message)
|
if (e instanceof Error) setError(e.message)
|
||||||
}
|
}
|
||||||
setTesting(false)
|
setTesting(false)
|
||||||
}, 1000);
|
}, 200);
|
||||||
}, [providerURL])
|
}, [providerURL, reducer])
|
||||||
|
|
||||||
|
|
||||||
if (!reducer) {
|
if (!reducer) {
|
||||||
return <div>no reducer in context</div>;
|
return <div>no reducer in context</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProvider(): void {
|
if (!reducer.currentReducerState || !("authentication_providers" in reducer.currentReducerState)) {
|
||||||
// addAuthMethod({
|
return <div>invalid state</div>
|
||||||
// authentication_method: {
|
|
||||||
// type: "sms",
|
|
||||||
// instructions: `SMS to ${providerURL}`,
|
|
||||||
// challenge: encodeCrock(stringToBytes(providerURL)),
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addProvider(provider_url: string): Promise<void> {
|
||||||
|
await reducer?.transition("add_provider", { provider_url })
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
|
function deleteProvider(provider_url: string): void {
|
||||||
|
reducer?.transition("delete_provider", { provider_url })
|
||||||
|
}
|
||||||
|
|
||||||
|
const allAuthProviders = reducer.currentReducerState.authentication_providers || {}
|
||||||
|
const authProviders = Object.keys(allAuthProviders).filter(provUrl => {
|
||||||
|
const p = allAuthProviders[provUrl];
|
||||||
|
if (!providerLabel) {
|
||||||
|
return p && ("currency" in p)
|
||||||
|
} else {
|
||||||
|
return p && ("currency" in p) && p.methods.findIndex(m => m.type === providerType) !== -1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
let errors = !providerURL ? 'Add provider URL' : undefined
|
let errors = !providerURL ? 'Add provider URL' : undefined
|
||||||
|
let url: string | undefined;
|
||||||
try {
|
try {
|
||||||
new URL(providerURL)
|
url = new URL("",providerURL).href
|
||||||
} catch {
|
} catch {
|
||||||
errors = 'Check the URL'
|
errors = 'Check the URL'
|
||||||
}
|
}
|
||||||
if (!!error && !errors) {
|
if (!!error && !errors) {
|
||||||
errors = error
|
errors = error
|
||||||
}
|
}
|
||||||
|
if (!errors && authProviders.includes(url!)) {
|
||||||
if (!reducer.currentReducerState || !("authentication_providers" in reducer.currentReducerState)) {
|
errors = 'That provider is already known'
|
||||||
return <div>invalid state</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const authProviders = reducer.currentReducerState.authentication_providers || {}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame hideNav
|
<AnastasisClientFrame hideNav
|
||||||
title="Backup: Manage providers"
|
title="Backup: Manage providers"
|
||||||
@ -119,40 +129,45 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode {
|
|||||||
label="Provider URL"
|
label="Provider URL"
|
||||||
placeholder="https://provider.com"
|
placeholder="https://provider.com"
|
||||||
grabFocus
|
grabFocus
|
||||||
|
error={errors}
|
||||||
bind={[providerURL, setProviderURL]} />
|
bind={[providerURL, setProviderURL]} />
|
||||||
</div>
|
</div>
|
||||||
<p class="block">
|
<p class="block">
|
||||||
Example: https://kudos.demo.anastasis.lu
|
Example: https://kudos.demo.anastasis.lu
|
||||||
</p>
|
</p>
|
||||||
|
{testing && <p class="has-text-info">Testing</p>}
|
||||||
{testing && <p class="block has-text-info">Testing</p>}
|
|
||||||
{!!error && <p class="block has-text-danger">{error}</p>}
|
|
||||||
{error === "" && <p class="block has-text-success">This provider worked!</p>}
|
|
||||||
|
|
||||||
<div class="block" style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
<div class="block" style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<button class="button" onClick={cancel}>Cancel</button>
|
<button class="button" onClick={onCancel}>Cancel</button>
|
||||||
<span data-tooltip={errors}>
|
<span data-tooltip={errors}>
|
||||||
<button class="button is-info" disabled={error !== "" || testing} onClick={addProvider}>Add</button>
|
<button class="button is-info" disabled={error !== "" || testing} onClick={() => addProvider(url!)}>Add</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="subtitle">
|
{authProviders.length > 0 ? (
|
||||||
Current providers
|
!providerLabel ?
|
||||||
</p>
|
<p class="subtitle">
|
||||||
{/* <table class="table"> */}
|
Current providers
|
||||||
{Object.keys(authProviders).map(k => {
|
</p> : <p class="subtitle">
|
||||||
const p = authProviders[k]
|
Current providers for {providerLabel} service
|
||||||
if (("currency" in p)) {
|
</p>
|
||||||
return <TableRow url={k} info={p} />
|
) : (
|
||||||
}
|
!providerLabel ? <p class="subtitle">
|
||||||
}
|
No known providers, add one.
|
||||||
|
</p> : <p class="subtitle">
|
||||||
|
No known providers for {providerLabel} service
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
{/* </table> */}
|
|
||||||
|
{authProviders.map(k => {
|
||||||
|
const p = allAuthProviders[k] as AuthenticationProviderStatusOk
|
||||||
|
return <TableRow url={k} info={p} onDelete={deleteProvider} />
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</AnastasisClientFrame>
|
</AnastasisClientFrame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function TableRow({ url, info }: { url: string, info: AuthenticationProviderStatusOk }) {
|
function TableRow({ url, info, onDelete }: { onDelete: (s: string) => void, url: string, info: AuthenticationProviderStatusOk }) {
|
||||||
const [status, setStatus] = useState("checking")
|
const [status, setStatus] = useState("checking")
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
testProvider(url.endsWith('/') ? url.substring(0, url.length - 1) : url)
|
testProvider(url.endsWith('/') ? url.substring(0, url.length - 1) : url)
|
||||||
@ -174,7 +189,7 @@ function TableRow({ url, info }: { url: string, info: AuthenticationProviderStat
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="block" style={{ marginTop: 'auto', marginBottom: 'auto', display: 'flex', justifyContent: 'space-between', flexDirection: 'column' }}>
|
<div class="block" style={{ marginTop: 'auto', marginBottom: 'auto', display: 'flex', justifyContent: 'space-between', flexDirection: 'column' }}>
|
||||||
<button class="button is-danger" >Remove</button>
|
<button class="button is-danger" onClick={() => onDelete(url)}>Remove</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
@ -2,10 +2,12 @@ import { AuthMethod, ReducerStateBackup } from "anastasis-core";
|
|||||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
import { ComponentChildren, Fragment, 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 { AddingProviderScreen } from "./AddingProviderScreen";
|
||||||
import {
|
import {
|
||||||
authMethods,
|
authMethods,
|
||||||
AuthMethodSetupProps,
|
AuthMethodSetupProps,
|
||||||
AuthMethodWithRemove,
|
AuthMethodWithRemove,
|
||||||
|
isKnownAuthMethods,
|
||||||
KnownAuthMethods,
|
KnownAuthMethods,
|
||||||
} from "./authMethod";
|
} from "./authMethod";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
@ -18,6 +20,8 @@ export function AuthenticationEditorScreen(): VNode {
|
|||||||
KnownAuthMethods | undefined
|
KnownAuthMethods | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
const [tooFewAuths, setTooFewAuths] = useState(false);
|
const [tooFewAuths, setTooFewAuths] = useState(false);
|
||||||
|
const [manageProvider, setManageProvider] = useState<string | undefined>(undefined)
|
||||||
|
|
||||||
// const [addingProvider, setAddingProvider] = useState<string | undefined>(undefined)
|
// const [addingProvider, setAddingProvider] = useState<string | undefined>(undefined)
|
||||||
const reducer = useAnastasisContext();
|
const reducer = useAnastasisContext();
|
||||||
if (!reducer) {
|
if (!reducer) {
|
||||||
@ -63,6 +67,14 @@ export function AuthenticationEditorScreen(): VNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manageProvider !== undefined) {
|
||||||
|
|
||||||
|
return <AddingProviderScreen
|
||||||
|
onCancel={() => setManageProvider(undefined)}
|
||||||
|
providerType={isKnownAuthMethods(manageProvider) ? manageProvider : undefined}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedMethod) {
|
if (selectedMethod) {
|
||||||
const cancel = (): void => setSelectedMethod(undefined);
|
const cancel = (): void => setSelectedMethod(undefined);
|
||||||
const addMethod = (args: any): void => {
|
const addMethod = (args: any): void => {
|
||||||
@ -86,9 +98,9 @@ export function AuthenticationEditorScreen(): VNode {
|
|||||||
active
|
active
|
||||||
onCancel={cancel}
|
onCancel={cancel}
|
||||||
description="No providers founds"
|
description="No providers founds"
|
||||||
label="Add a provider manually (not implemented!)"
|
label="Add a provider manually"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
null;
|
setManageProvider(selectedMethod)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
@ -179,9 +191,9 @@ export function AuthenticationEditorScreen(): VNode {
|
|||||||
active={!noProvidersAck}
|
active={!noProvidersAck}
|
||||||
onCancel={() => setNoProvidersAck(true)}
|
onCancel={() => setNoProvidersAck(true)}
|
||||||
description="No providers founds"
|
description="No providers founds"
|
||||||
label="Add a provider manually (not implemented!)"
|
label="Add a provider manually"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
null;
|
setManageProvider("")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
@ -201,11 +213,11 @@ export function AuthenticationEditorScreen(): VNode {
|
|||||||
identity via the methods you configure here. The list of
|
identity via the methods you configure here. The list of
|
||||||
authentication method is defined by the backup provider list.
|
authentication method is defined by the backup provider list.
|
||||||
</p>
|
</p>
|
||||||
{/* <p class="block">
|
<p class="block">
|
||||||
<button class="button is-info">
|
<button class="button is-info" onClick={() => setManageProvider("")}>
|
||||||
Manage backup providers
|
Manage backup providers
|
||||||
</button>
|
</button>
|
||||||
</p> */}
|
</p>
|
||||||
{authAvailableSet.size > 0 && (
|
{authAvailableSet.size > 0 && (
|
||||||
<p class="block">
|
<p class="block">
|
||||||
We couldn't find provider for some of the authentication methods.
|
We couldn't find provider for some of the authentication methods.
|
||||||
|
@ -3,12 +3,14 @@ import { useState } from "preact/hooks";
|
|||||||
import { AsyncButton } from "../../components/AsyncButton";
|
import { AsyncButton } from "../../components/AsyncButton";
|
||||||
import { NumberInput } from "../../components/fields/NumberInput";
|
import { NumberInput } from "../../components/fields/NumberInput";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
|
import { AddingProviderScreen } from "./AddingProviderScreen";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
|
|
||||||
export function SecretSelectionScreen(): VNode {
|
export function SecretSelectionScreen(): VNode {
|
||||||
const [selectingVersion, setSelectingVersion] = useState<boolean>(false);
|
const [selectingVersion, setSelectingVersion] = useState<boolean>(false);
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext()
|
||||||
|
|
||||||
|
const [manageProvider, setManageProvider] = useState(false)
|
||||||
const currentVersion = (reducer?.currentReducerState
|
const currentVersion = (reducer?.currentReducerState
|
||||||
&& ("recovery_document" in reducer.currentReducerState)
|
&& ("recovery_document" in reducer.currentReducerState)
|
||||||
&& reducer.currentReducerState.recovery_document?.version) || 0;
|
&& reducer.currentReducerState.recovery_document?.version) || 0;
|
||||||
@ -49,6 +51,10 @@ export function SecretSelectionScreen(): VNode {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manageProvider) {
|
||||||
|
return <AddingProviderScreen onCancel={() => setManageProvider(false)} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame title="Recovery: Select secret">
|
<AnastasisClientFrame title="Recovery: Select secret">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
@ -69,6 +75,12 @@ export function SecretSelectionScreen(): VNode {
|
|||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p>Secret found, you can select another version or continue to the challenges solving</p>
|
<p>Secret found, you can select another version or continue to the challenges solving</p>
|
||||||
|
<p class="block">
|
||||||
|
<button class="button is-info" onClick={() => setManageProvider(true)}>
|
||||||
|
Manage recovery providers
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AnastasisClientFrame>
|
</AnastasisClientFrame>
|
||||||
|
@ -41,7 +41,13 @@ interface AuthMethodConfiguration {
|
|||||||
solve: (props: AuthMethodSolveProps) => VNode;
|
solve: (props: AuthMethodSolveProps) => VNode;
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
}
|
}
|
||||||
export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";
|
// export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";
|
||||||
|
|
||||||
|
const ALL_METHODS = ['sms', 'email', 'post', 'question', 'video' , 'totp', 'iban'] as const;
|
||||||
|
export type KnownAuthMethods = (typeof ALL_METHODS)[number];
|
||||||
|
export function isKnownAuthMethods(value: string): value is KnownAuthMethods {
|
||||||
|
return ALL_METHODS.includes(value as KnownAuthMethods)
|
||||||
|
}
|
||||||
|
|
||||||
type KnowMethodConfig = {
|
type KnowMethodConfig = {
|
||||||
[name in KnownAuthMethods]: AuthMethodConfiguration;
|
[name in KnownAuthMethods]: AuthMethodConfiguration;
|
||||||
|
Loading…
Reference in New Issue
Block a user