From e1d86816a7c07cb8ca2d54676d5cdbbe513f2ba7 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 4 Sep 2023 14:17:55 -0300 Subject: backoffcie new version, lot of changes --- .../paths/instance/templates/create/CreatePage.tsx | 127 +++++---------------- 1 file changed, 27 insertions(+), 100 deletions(-) (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx') diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx index e20b9bc27..8629d8dee 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx @@ -24,7 +24,7 @@ import { MerchantTemplateContractDetails, } from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; -import { Fragment, h, VNode } from "preact"; +import { Fragment, VNode, h } from "preact"; import { useState } from "preact/hooks"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { @@ -35,17 +35,16 @@ import { Input } from "../../../../components/form/Input.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputDuration } from "../../../../components/form/InputDuration.js"; import { InputNumber } from "../../../../components/form/InputNumber.js"; -import { InputSelector } from "../../../../components/form/InputSelector.js"; import { InputWithAddon } from "../../../../components/form/InputWithAddon.js"; import { useBackendContext } from "../../../../context/backend.js"; +import { useInstanceContext } from "../../../../context/instance.js"; import { MerchantBackend } from "../../../../declaration.js"; import { - isBase32RFC3548Charset, - randomBase32Key, + isBase32RFC3548Charset } from "../../../../utils/crypto.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; -import { QR } from "../../../../components/exception/QR.js"; -import { useInstanceContext } from "../../../../context/instance.js"; +import { InputSearchOnList } from "../../../../components/form/InputSearchOnList.js"; +import { useInstanceOtpDevices } from "../../../../hooks/otp.js"; type Entity = MerchantBackend.Template.TemplateAddDetails; @@ -54,16 +53,11 @@ interface Props { onBack?: () => void; } -const algorithms = [0, 1, 2]; -const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"]; - export function CreatePage({ onCreate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const backend = useBackendContext(); - const { id: instanceId } = useInstanceContext(); - const issuer = new URL(backend.url).hostname; + const devices = useInstanceOtpDevices() - const [showKey, setShowKey] = useState(false); const [state, setState] = useState>({ template_contract: { minimum_age: 0, @@ -78,7 +72,11 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { : Amounts.parse(state.template_contract?.amount); const errors: FormErrors = { - template_id: !state.template_id ? i18n.str`should not be empty` : undefined, + template_id: !state.template_id + ? i18n.str`should not be empty` + : !/[a-zA-Z0-9]*/.test(state.template_id) + ? i18n.str`no valid. only characters and numbers` + : undefined, template_description: !state.template_description ? i18n.str`should not be empty` : undefined, @@ -104,15 +102,6 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { ? i18n.str`to short` : undefined, } as Partial), - pos_key: !state.pos_key - ? !state.pos_algorithm - ? undefined - : i18n.str`required` - : !isBase32RFC3548Charset(state.pos_key) - ? i18n.str`just letters and numbers from 2 to 7` - : state.pos_key.length !== 32 - ? i18n.str`size of the key should be 32` - : undefined, }; const hasErrors = Object.keys(errors).some( @@ -124,7 +113,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { return onCreate(state as any); }; - const qrText = `otpauth://totp/${instanceId}/${state.template_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${state.pos_key}`; + const deviceList = !devices.ok ? [] : devices.data.otp_devices return (
@@ -139,7 +128,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { > name="template_id" - help={`${backend.url}/instances/templates/${state.template_id ?? ""}`} + help={`${backend.url}/templates/${state.template_id ?? ""}`} label={i18n.str`Identifier`} tooltip={i18n.str`Name of the template in URLs.`} /> @@ -172,83 +161,21 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { help="" tooltip={i18n.str`How much time has the customer to complete the payment once the order was created.`} /> - - name="pos_algorithm" - label={i18n.str`Verification algorithm`} - tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`} - values={algorithms} - toStr={(v) => algorithmsNames[v]} - fromStr={(v) => Number(v)} + + name="otp_id" + label={i18n.str`OTP device`} + readonly + tooltip={i18n.str`Use to verify transaction in offline mode.`} + /> + setState((v) => ({ ...v, otp_id: p?.id }))} + list={deviceList.map(e => ({ + description: e.device_description, + id: e.otp_device_id + }))} /> - {state.pos_algorithm && state.pos_algorithm > 0 ? ( - - - name="pos_key" - label={i18n.str`Point-of-sale key`} - inputType={showKey ? "text" : "password"} - help="Be sure to be very hard to guess or use the random generator" - tooltip={i18n.str`Useful to validate the purchase`} - fromStr={(v) => v.toUpperCase()} - addonAfter={ - - {showKey ? ( - - ) : ( - - )} - - } - side={ - - - - - } - /> - {showKey && ( - - -
- {qrText} -
-
- )} -
- ) : undefined} +
-- cgit v1.2.3