-
-
- Copyright © 2014—2023 Taler Systems SA.
- {versionText}
-
-
+
);
diff --git a/packages/exchange-backoffice-ui/src/pages.ts b/packages/exchange-backoffice-ui/src/pages.ts
index b46cf5d51..a78a137a0 100644
--- a/packages/exchange-backoffice-ui/src/pages.ts
+++ b/packages/exchange-backoffice-ui/src/pages.ts
@@ -1,25 +1,35 @@
import { Home } from "./pages/Home.js";
import { Settings } from "./pages/Settings.js";
-import { ShowForm } from "./pages/ShowForm.js";
+import { AntiMoneyLaunderingForm } from "./pages/AntiMoneyLaunderingForm.js";
import { Welcome } from "./pages/Welcome.js";
import { PageEntry, pageDefinition } from "./route.js";
+import { Officer } from "./pages/Officer.js";
+import { Info } from "./pages/Info.js";
const home: PageEntry = {
url: "#/",
view: Home,
};
+const info: PageEntry = {
+ url: "#/info",
+ view: Info,
+};
const settings: PageEntry = {
url: "#/settings",
view: Settings,
};
+const officer: PageEntry = {
+ url: "#/officer",
+ view: Officer,
+};
const welcome: PageEntry<{ asd?: string; name?: string }> = {
url: pageDefinition("#/welcome/:name?"),
view: Welcome,
};
const form: PageEntry<{ number?: string }> = {
url: pageDefinition("#/form/:number?"),
- view: ShowForm,
+ view: AntiMoneyLaunderingForm,
};
-export const Pages = { home, settings, welcome, form };
+export const Pages = { home, info, officer, settings, welcome, form };
diff --git a/packages/exchange-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx b/packages/exchange-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx
new file mode 100644
index 000000000..ee9d1ce30
--- /dev/null
+++ b/packages/exchange-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx
@@ -0,0 +1,71 @@
+import { h } from "preact";
+import { NiceForm } from "../NiceForm.js";
+import { v1 as form_902_11e_v1 } from "../forms/902_11e.js";
+import { v1 as form_902_12e_v1 } from "../forms/902_12e.js";
+import { v1 as form_902_13e_v1 } from "../forms/902_13e.js";
+import { v1 as form_902_15e_v1 } from "../forms/902_15e.js";
+import { v1 as form_902_1e_v1 } from "../forms/902_1e.js";
+import { v1 as form_902_4e_v1 } from "../forms/902_4e.js";
+import { v1 as form_902_5e_v1 } from "../forms/902_5e.js";
+import { v1 as form_902_9e_v1 } from "../forms/902_9e.js";
+import { DocumentDuplicateIcon } from "@heroicons/react/24/solid";
+
+export function AntiMoneyLaunderingForm({ number }: { number?: string }) {
+ const selectedForm = Number.parseInt(number ?? "0", 10);
+ if (Number.isNaN(selectedForm)) {
+ return
WHAT! {number}
;
+ }
+ const showingFrom = allForms[selectedForm].impl;
+ const storedValue = {
+ fullName: "loggedIn_user_fullname",
+ when: {
+ t_ms: new Date().getTime(),
+ },
+ };
+ return (
+
{}} />
+ );
+}
+
+export const allForms = [
+ {
+ name: "Identification form (902.1e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_1e_v1,
+ },
+ {
+ name: "Operational legal entity or partnership (902.11e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_11e_v1,
+ },
+ {
+ name: "Foundations (902.12e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_12e_v1,
+ },
+ {
+ name: "Declaration for trusts (902.13e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_13e_v1,
+ },
+ {
+ name: "Information on life insurance policies (902.15e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_15e_v1,
+ },
+ {
+ name: "Declaration of beneficial owner (902.9e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_9e_v1,
+ },
+ {
+ name: "Customer profile (902.5e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_5e_v1,
+ },
+ {
+ name: "Risk profile (902.4e)",
+ icon: DocumentDuplicateIcon,
+ impl: form_902_4e_v1,
+ },
+];
diff --git a/packages/exchange-backoffice-ui/src/pages/Info.tsx b/packages/exchange-backoffice-ui/src/pages/Info.tsx
new file mode 100644
index 000000000..661ab02a7
--- /dev/null
+++ b/packages/exchange-backoffice-ui/src/pages/Info.tsx
@@ -0,0 +1,5 @@
+import { h } from "preact";
+
+export function Info() {
+ return Show key and wire info
;
+}
diff --git a/packages/exchange-backoffice-ui/src/pages/Officer.tsx b/packages/exchange-backoffice-ui/src/pages/Officer.tsx
new file mode 100644
index 000000000..c72ca0720
--- /dev/null
+++ b/packages/exchange-backoffice-ui/src/pages/Officer.tsx
@@ -0,0 +1,116 @@
+import { useLocalStorage } from "@gnu-taler/web-util/browser";
+import { h } from "preact";
+import { useEffect, useState } from "preact/hooks";
+
+const oldKey =
+ "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDPQVq8F0Ce6kTXKQ5Ea2fZRoap6poFYs0FOln8o8+ehGI8rDdMBzNU3pLIlOMKs/vKvhDNMG4m4xxb92wDbvefDxkxaEkbRSZnRiJd4MIbh8Lx8zvFbLp03rkXu9KPN8IprKOXxgN7xbxm0KKcu03rtqLiOvC1gMqja2LMIPCi32nyNneduszHZ57d+CqIKZdVnaqAcXOSMAQsVoEq2joBOeIaSAnIJHg+T8HQ+VcLV8Y722jhX/bH84IyEMup9e7mhgVFnHgINc77c6TONH8H+dHlXCQ+hMPGw9wM+wgpJgIDzrhIN+QSjn283EOXD6z6dpiWBdEYfJRLHwEWk8wNAgMBAAECggEAB/anZrMasQsoXP9qBG1Uvq+r4fXZODFtK5vBNGi+RAWAhCX2iU3SMPB3wbby0wj1DlESR91qBhrTjqG+/TzIzUxLuARyoVZysiTVkjeIzdJVcRgwU5bTbUUs5da6MaA/WNGWMZvoALFUMBEpMQ4uDCC8OSbG8/prDtoZSuWjHrxBhsqSyIoJ3Q0iPQxPT0ShC9d5T56QuhsRQeRIWhQVtFlytXl1lqEbqljhIEOzkvS5QOcXcS3OBo/Nvdit+vi9kkLuiP8z2p6WAiVZCgCXfffNH3EEbQG/BEpIOynkchiDy1L31mFRFk1oYJRs9xD8+oF/N75GhlmYO7IbxeHw0wKBgQDnYZWjGlRM2oHpeiPSII5m9rC7qohO0ImxqifYZPp47vdRMbBWrdbxX68SqdzGfSzXcDPLfBAObG4QR8Xol1LMNJUT9og9pERZHgob+yWkTd68lLSdxfCJEKRJaDmD8dHgSrBYe86ADUeAj+fC4dycYXH//fwed1gt/G8iXtdU9wKBgQDlTp9752+tEh9fMlUdINbZXmGbjHBrZMTnAYJI509iJLIvJvYroU5TvRMsp+rACDc2Zy2nbsaCM5Xzd5wUxRBvF+PiBCFoi7c/EBaLCtb9+vyXtHAIHtzHeYUP/1cq7MOdTwrWvZqzIoW6xm7L9HRX/5i+n+rVUSxnzYIxgTlaGwKBgQC0INgpXbn7CrDQXnG8h/PUXIBB2QS8tsQ7N8hFQndr5j1LTG+HS1ZmGqNk2DAzpgdewM7RvweQ8wDMU9PSutuOdfEI1YhC1LsQ1b3xApfPTX/1N59UpGAZlIcRTr5X5c4J2ptmhxu/vJbJkz5ODR997q6dJ9E6tpZDVp3+F+9zCQKBgQCrp+OzuVjcUoixltgoagDrz7951fQCMPlFhNenA6FlctsAeUYm+yXLgersrvcIsh3C2BJRGJf5t+w0ygFJewwGXff1pensfUq8Jqr5gy/WCSE135lOOuxDVzDI/Pif5YW6KQWQI3e/ScSaQRmIDINbrLcHXGdLMOzw9+LSdE4eqQKBgQDe86MfzwMLPoDH07WC09dCcoIUSYMThYrFwUK3qgEiYaJMZJvdAIwr12szVwVRYIX4wHBObFsQZLTaY5+O/REnze6Q1AQa2H6eH1TalC1r6jBS5/LhIrVWl/0VSdsUIe41tc8xPDWrm9hmLeJLZk+xb5/hAm3REsDM1Iif9O7zzg==";
+export function Officer() {
+ const storage = useLocalStorage("officer");
+ const [keys, setKeys] = useState({ priv: "", pub: "" });
+ useEffect(() => {
+ loadPreviousSession(oldKey).then((keys) =>
+ setKeys(keys ?? { priv: "", pub: "" }),
+ );
+ // generateNewId().then((keys) => setKeys(keys));
+ }, []);
+
+ console.log(keys.pub);
+ console.log(keys.priv);
+ return (
+
+
Officer
+
+ Public key
+
+
+ -----BEGIN PUBLIC KEY-----
+
{keys.pub}
+ -----END PUBLIC KEY-----
+
+
+ Private key
+
+
+ -----BEGIN PRIVATE KEY-----
+
{keys.priv}
+ -----END PRIVATE KEY-----
+
+
+ );
+}
+
+const rsaAlgorithm: RsaHashedKeyGenParams = {
+ name: "RSA-OAEP",
+ modulusLength: 2048,
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+ hash: "SHA-256",
+};
+
+async function generateNewId() {
+ const key = await crypto.subtle.generateKey(rsaAlgorithm, true, [
+ "encrypt",
+ "decrypt",
+ ]);
+
+ if (key instanceof CryptoKey) {
+ throw Error("unexpected key without pair");
+ }
+ const { privateKey, publicKey } = key;
+ const privRaw = await crypto.subtle.exportKey("pkcs8", privateKey);
+
+ const pubRaw = await crypto.subtle.exportKey("spki", publicKey);
+
+ const priv = btoa(ab2str(privRaw));
+
+ const pub = btoa(ab2str(pubRaw));
+ return { priv, pub };
+}
+
+async function loadPreviousSession(priv: string) {
+ const key = str2ab(window.atob(priv));
+ const privateKey = await window.crypto.subtle
+ .importKey("pkcs8", key, rsaAlgorithm, true, ["decrypt"])
+ .catch(throwErrorWithStack);
+
+ if (!privateKey) return undefined;
+
+ // export private key to JWK
+ const jwk = await crypto.subtle
+ .exportKey("jwk", privateKey)
+ .catch(throwErrorWithStack);
+
+ // remove private data from JWK
+ delete jwk.d;
+ delete jwk.dp;
+ delete jwk.dq;
+ delete jwk.q;
+ delete jwk.qi;
+ jwk.key_ops = ["encrypt"];
+
+ const publicKey = await crypto.subtle
+ .importKey("jwk", jwk, rsaAlgorithm, true, ["encrypt"])
+ .catch(throwErrorWithStack);
+
+ const pubRaw = await crypto.subtle
+ .exportKey("spki", publicKey)
+ .catch(throwErrorWithStack);
+
+ const pub = btoa(ab2str(pubRaw));
+
+ return { priv, pub };
+}
+
+function ab2str(buf: ArrayBuffer) {
+ return String.fromCharCode.apply(null, Array.from(new Uint8Array(buf)));
+}
+function str2ab(str: string) {
+ const buf = new ArrayBuffer(str.length);
+ const bufView = new Uint8Array(buf);
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
+ bufView[i] = str.charCodeAt(i);
+ }
+ return buf;
+}
+function throwErrorWithStack(e: Error): never {
+ throw new Error(e.message);
+}
diff --git a/packages/exchange-backoffice-ui/src/pages/ShowForm.tsx b/packages/exchange-backoffice-ui/src/pages/ShowForm.tsx
deleted file mode 100644
index 5440ab7e1..000000000
--- a/packages/exchange-backoffice-ui/src/pages/ShowForm.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { h } from "preact";
-import { allForms } from "../Dashboard.js";
-import { NiceForm } from "../NiceForm.js";
-
-export function ShowForm({ number }: { number?: string }) {
- const selectedForm = Number.parseInt(number ?? "0", 10);
- if (Number.isNaN(selectedForm)) {
- return WHAT! {number}
;
- }
- const showingFrom = allForms[selectedForm].impl;
- const storedValue = {
- fullName: "loggedIn_user_fullname",
- when: {
- t_ms: new Date().getTime(),
- },
- };
- return (
- {}} />
- );
-}