From ea13e19ece2deeb4ab9731373f68b1dcf5b6fa88 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 10 Nov 2021 15:43:15 -0300 Subject: file upload --- .../src/components/fields/FileInput.tsx | 47 +++++++++++++++------- .../src/components/fields/TextInput.tsx | 2 + .../src/pages/home/ReviewPoliciesScreen.tsx | 5 ++- .../src/pages/home/SecretEditorScreen.tsx | 42 +++++++++++++------ .../home/authMethod/AuthMethodQuestionSetup.tsx | 2 +- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/packages/anastasis-webui/src/components/fields/FileInput.tsx b/packages/anastasis-webui/src/components/fields/FileInput.tsx index 52d6eab4a..adf51afb0 100644 --- a/packages/anastasis-webui/src/components/fields/FileInput.tsx +++ b/packages/anastasis-webui/src/components/fields/FileInput.tsx @@ -20,11 +20,26 @@ */ import { h, VNode } from "preact"; import { useLayoutEffect, useRef, useState } from "preact/hooks"; -import { TextInputProps } from "./TextInput"; const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024; -export function FileInput(props: TextInputProps): VNode { +export interface FileTypeContent { + content: string; + type: string; + name: string; +} + +export interface FileInputProps { + label: string; + grabFocus?: boolean; + disabled?: boolean; + error?: string; + placeholder?: string; + tooltip?: string; + onChange: (v: FileTypeContent | undefined) => void; +} + +export function FileInput(props: FileInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { if (props.grabFocus) { @@ -32,18 +47,19 @@ export function FileInput(props: TextInputProps): VNode { } }, [props.grabFocus]); - const value = props.bind[0]; - // const [dirty, setDirty] = useState(false) - const image = useRef(null); + const fileInputRef = useRef(null); const [sizeError, setSizeError] = useState(false); - function onChange(v: string): void { - // setDirty(true); - props.bind[1](v); - } return (
{ const f: FileList | null = e.currentTarget.files; if (!f || f.length != 1) { - return onChange(""); + return props.onChange(undefined); } + console.log(f) if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { setSizeError(true); - return onChange(""); + return props.onChange(undefined); } setSizeError(false); return f[0].arrayBuffer().then((b) => { @@ -73,7 +90,7 @@ export function FileInput(props: TextInputProps): VNode { "", ), ); - return onChange(`data:${f[0].type};base64,${b64}` as any); + return props.onChange({content: `data:${f[0].type};base64,${b64}`, name: f[0].name, type: f[0].type}); }); }} /> diff --git a/packages/anastasis-webui/src/components/fields/TextInput.tsx b/packages/anastasis-webui/src/components/fields/TextInput.tsx index fd0c658ed..4f417730c 100644 --- a/packages/anastasis-webui/src/components/fields/TextInput.tsx +++ b/packages/anastasis-webui/src/components/fields/TextInput.tsx @@ -4,6 +4,7 @@ import { useLayoutEffect, useRef, useState } from "preact/hooks"; export interface TextInputProps { label: string; grabFocus?: boolean; + disabled?: boolean; error?: string; placeholder?: string; tooltip?: string; @@ -33,6 +34,7 @@ export function TextInput(props: TextInputProps): VNode {
{ diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx index c301b287a..3b3b441ed 100644 --- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx @@ -1,3 +1,4 @@ +import { AuthenticationProviderStatusOk } from "anastasis-core"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useAnastasisContext } from "../../context/anastasis"; @@ -22,6 +23,7 @@ export function ReviewPoliciesScreen(): VNode { reducer.currentReducerState.authentication_methods ?? []; const policies = reducer.currentReducerState.policies ?? []; + const providers = reducer.currentReducerState.authentication_providers ?? {} if (editingPolicy !== undefined) { return ( @@ -96,6 +98,7 @@ export function ReviewPoliciesScreen(): VNode { {!methods.length &&

No auth method found

} {methods.map((m, i) => { + const p = providers[m.provider] as AuthenticationProviderStatusOk return (

{m.instructions} recovery provided by{" "} - {m.provider} + {p.business_name}

); diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx index 59af8a9ee..226e43ddf 100644 --- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx @@ -5,11 +5,16 @@ import { useState } from "preact/hooks"; import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisClientFrame } from "./index"; import { TextInput } from "../../components/fields/TextInput"; -import { FileInput } from "../../components/fields/FileInput"; +import { FileInput, FileTypeContent } from "../../components/fields/FileInput"; export function SecretEditorScreen(): VNode { const reducer = useAnastasisContext(); const [secretValue, setSecretValue] = useState(""); + const [secretFile, _setSecretFile] = useState(undefined); + function setSecretFile(v) { + setSecretValue("") // reset secret value when uploading a file + _setSecretFile(v) + } const currentSecretName = reducer?.currentReducerState && @@ -29,15 +34,20 @@ export function SecretEditorScreen(): VNode { } const secretNext = async (): Promise => { + const secret = secretFile ? { + value: encodeCrock(stringToBytes(secretValue)), + filename: secretFile.name, + mime: secretFile.type, + } : { + value: encodeCrock(stringToBytes(secretValue)), + mime: "text/plain", + } return reducer.runTransaction(async (tx) => { await tx.transition("enter_secret_name", { name: secretName, }); await tx.transition("enter_secret", { - secret: { - value: encodeCrock(stringToBytes(secretValue)), - mime: "text/plain", - }, + secret, expiration: { t_ms: new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 5, }, @@ -45,12 +55,16 @@ export function SecretEditorScreen(): VNode { await tx.transition("next", {}); }); }; + const errors = !secretName ? 'Add a secret name' : ( + (!secretValue && !secretFile) ? 'Add a secret value or a choose a file to upload' : undefined + ) return ( secretNext()} > -
+
-
+
- {/*
- or  - -  to import a file -
*/} +
+
+ Or upload a secret file + + {secretFile &&
+ Uploading secret file {secretFile.name} setSecretFile(undefined)}>cancel +
+ }
); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx index 0a14021dd..03725621c 100644 --- a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx @@ -30,7 +30,7 @@ export function AuthMethodQuestionSetup({

- For2 security question authentication, you need to provide a question + For security question authentication, you need to provide a question and its answer. When recovering your secret, you will be shown the question and you will need to type the answer exactly as you typed it here. -- cgit v1.2.3