From b874f9a0c50084803de58febb698864aa8dd061a Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 12 Mar 2023 23:56:54 -0300 Subject: print and setup totp --- .../paths/instance/templates/create/CreatePage.tsx | 43 ++++++++++++-- .../src/paths/instance/templates/qr/QrPage.tsx | 65 ++++++++++++++++++++-- .../src/paths/instance/templates/qr/index.tsx | 2 - .../paths/instance/templates/update/UpdatePage.tsx | 42 ++++++++++++-- .../src/paths/instance/templates/use/UsePage.tsx | 19 ++++++- .../src/paths/instance/templates/use/index.tsx | 1 + 6 files changed, 154 insertions(+), 18 deletions(-) (limited to 'packages/merchant-backoffice-ui/src/paths') 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 22f86002a..144e968c5 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 @@ -31,9 +31,11 @@ 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 { MerchantBackend } from "../../../../declaration.js"; +import { randomBase32Key } from "../../../../utils/crypto.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; type Entity = MerchantBackend.Template.TemplateAddDetails; @@ -43,6 +45,13 @@ interface Props { onBack?: () => void; } +const algorithms = ["0", "1", "2"]; +const algorithmsNames = [ + "off", + "30s 8d TOTP-SHA1 without amount", + "30s 8d eTOTP-SHA1 with amount", +]; + export function CreatePage({ onCreate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const backend = useBackendContext(); @@ -104,7 +113,6 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { label={i18n.str`Identifier`} tooltip={i18n.str`Name of the template in URLs.`} /> - name="template_description" label={i18n.str`Description`} @@ -134,12 +142,35 @@ 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_key" - label={i18n.str`Point-of-sale key`} - help="" - tooltip={i18n.str`Useful to validate the purchase`} + + name="pos_algorithm" + label={i18n.str`Veritifaction algorithm`} + tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`} + values={algorithms} + toStr={(v) => algorithmsNames[v]} + convert={(v) => Number(v)} /> + {state.pos_algorithm && state.pos_algorithm > 0 ? ( + + name="pos_key" + label={i18n.str`Point-of-sale key`} + help="" + tooltip={i18n.str`Useful to validate the purchase`} + side={ + + + + } + /> + ) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx index 756909d15..66ac72ff5 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx @@ -31,8 +31,10 @@ import { } from "../../../../components/form/FormProvider.js"; import { Input } from "../../../../components/form/Input.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; +import { ConfirmModal } from "../../../../components/modal/index.js"; import { useBackendContext } from "../../../../context/backend.js"; import { useConfigContext } from "../../../../context/config.js"; +import { useInstanceContext } from "../../../../context/instance.js"; import { MerchantBackend } from "../../../../declaration.js"; type Entity = MerchantBackend.Template.UsingTemplateDetails; @@ -46,7 +48,9 @@ interface Props { export function QrPage({ template, id: templateId, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const { url: backendUrl } = useBackendContext(); + const { id: instanceId } = useInstanceContext(); const config = useConfigContext(); + const [setupTOTP, setSetupTOTP] = useState(false); const [state, setState] = useState>({ amount: template.template_contract.amount, @@ -82,8 +86,33 @@ export function QrPage({ template, id: templateId, onBack }: Props): VNode { const payTemplateUri = `${talerProto}//pay-template/${merchantURL.hostname}/${templateId}${paramsStr}`; + const issuer = encodeURIComponent( + `${new URL(backendUrl).hostname}/${instanceId}`, + ); + const oauthUri = !template.pos_algorithm + ? undefined + : template.pos_algorithm === 1 + ? `otpauth://totp/${issuer}:${templateId}?secret=${template.pos_key}&issuer=${issuer}&algorithm=SHA1&digits=8&period=30` + : template.pos_algorithm === 2 + ? `otpauth://totp/${issuer}:${templateId}?secret=${template.pos_key}&issuer=${issuer}&algorithm=SHA1&digits=8&period=30` + : undefined; return (
+ {oauthUri && ( + { + setSetupTOTP(false); + }} + > +

Scan this qr code with your TOTP device

+ +
+            {oauthUri}
+          
+
+ )}
@@ -114,20 +143,48 @@ export function QrPage({ template, id: templateId, onBack }: Props): VNode { Cancel )} - + {oauthUri && ( + + )}
-
-
+      
+ +
           {payTemplateUri}
         
-
); } + +function saveAsPDF(name: string): void { + const printWindow = window.open("", "", "height=400,width=800"); + if (!printWindow) return; + const divContents = document.getElementById("printThis"); + if (!divContents) return; + printWindow.document.write( + `Order template for ${name} "); + printWindow.document.close(); + printWindow.document.body.appendChild(divContents.cloneNode(true)); + printWindow.addEventListener("load", () => { + printWindow.print(); + printWindow.close(); + }); +} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx index 97d25b700..044cc7d79 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx @@ -51,10 +51,8 @@ export default function TemplateQrPage({ onNotFound, onUnauthorized, }: Props): VNode { - const { createOrderFromTemplate } = useTemplateAPI(); const result = useTemplateDetails(tid); const [notif, setNotif] = useState(undefined); - const { i18n } = useTranslationContext(); if (result.clientError && result.isUnauthorized) return onUnauthorized(); if (result.clientError && result.isNotfound) return onNotFound(); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx index eba212517..e34e2c746 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx @@ -31,9 +31,11 @@ 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 { MerchantBackend, WithId } from "../../../../declaration.js"; +import { randomBase32Key } from "../../../../utils/crypto.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId; @@ -44,6 +46,13 @@ interface Props { template: Entity; } +const algorithms = ["0", "1", "2"]; +const algorithmsNames = [ + "off", + "30s 8d TOTP-SHA1 without amount", + "30s 8d eTOTP-SHA1 with amount", +]; + export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const backend = useBackendContext(); @@ -143,12 +152,35 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { help="" tooltip={i18n.str`How much time has the customer to complete the payment once the order was created.`} /> - - name="pos_key" - label={i18n.str`Point-of-sale key`} - help="" - tooltip={i18n.str`Useful to validate the purchase`} + + name="pos_algorithm" + label={i18n.str`Veritifaction algorithm`} + tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`} + values={algorithms} + toStr={(v) => algorithmsNames[v]} + convert={(v) => Number(v)} /> + {state.pos_algorithm && state.pos_algorithm > 0 ? ( + + name="pos_key" + label={i18n.str`Point-of-sale key`} + help="" + tooltip={i18n.str`Useful to validate the purchase`} + side={ + + + + } + /> + ) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx index a63469763..5abc6b153 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx @@ -34,12 +34,13 @@ import { MerchantBackend } from "../../../../declaration.js"; type Entity = MerchantBackend.Template.UsingTemplateDetails; interface Props { + id: string; template: MerchantBackend.Template.TemplateDetails; onCreateOrder: (d: Entity) => Promise; onBack?: () => void; } -export function UsePage({ template, onCreateOrder, onBack }: Props): VNode { +export function UsePage({ id, template, onCreateOrder, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const [state, setState] = useState>({ @@ -75,6 +76,22 @@ export function UsePage({ template, onCreateOrder, onBack }: Props): VNode { return (
+
+
+
+
+
+
+ + New order for template:{" "} + {id} + +
+
+
+
+
+
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx index d5fa6d39d..b6175bcfb 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx @@ -68,6 +68,7 @@ export default function TemplateUsePage({