taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit bdf8dfeea1997176bc4e466897288c6f88f43d24
parent 3f86a1965266a5e8a1cedfa69a7e806e56efc91d
Author: Sebastian <sebasjm@gmail.com>
Date:   Wed, 27 Nov 2024 13:28:23 -0300

add support for required input, show server measure on aml spa when doing debug

Diffstat:
Mpackages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx | 6++++++
Mpackages/aml-backoffice-ui/src/Routing.tsx | 5+++++
Mpackages/aml-backoffice-ui/src/hooks/account.ts | 33+++++++++++++++++++++++++++++++++
Mpackages/aml-backoffice-ui/src/pages/Cases.tsx | 10++++++++++
Apackages/aml-backoffice-ui/src/pages/Measures.tsx | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-util/src/kyc-aml-utils.ts | 2++
Mpackages/taler-util/src/types-taler-exchange.ts | 4++--
Mpackages/taler-util/src/types-taler-kyc-aml.ts | 15+++++++++++++++
Mpackages/taler-util/src/types-taler-merchant.ts | 2+-
9 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx @@ -34,6 +34,7 @@ import { usePreferences, } from "./hooks/preferences.js"; import { + FormIcon, HomeIcon, PeopleIcon, SearchIcon, @@ -233,6 +234,7 @@ export function ExchangeAmlFrame({ function Navigation(): VNode { const { i18n } = useTranslationContext(); + const [{ showDebugInfo }] = usePreferences(); const pageList = [ { route: privatePages.profile, Icon: PeopleIcon, label: i18n.str`Profile` }, { @@ -246,6 +248,9 @@ function Navigation(): VNode { Icon: SearchIcon, label: i18n.str`Search`, }, + showDebugInfo + ? { route: privatePages.measures, Icon: FormIcon, label: i18n.str`Forms` } + : undefined, ]; const { path } = useNavigationContext(); return ( @@ -255,6 +260,7 @@ function Navigation(): VNode { <li> <ul role="list" class="-mx-2 space-y-1"> {pageList.map((p, idx) => { + if (!p) return undefined; return ( <li key={idx}> <a diff --git a/packages/aml-backoffice-ui/src/Routing.tsx b/packages/aml-backoffice-ui/src/Routing.tsx @@ -37,6 +37,7 @@ import { CaseDetails } from "./pages/CaseDetails.js"; import { CaseUpdate, SelectForm } from "./pages/CaseUpdate.js"; import { HandleAccountNotReady } from "./pages/HandleAccountNotReady.js"; import { Search } from "./pages/Search.js"; +import { Measures } from "./pages/Measures.js"; export function Routing(): VNode { const session = useOfficer(); @@ -101,6 +102,7 @@ function PublicRounting(): VNode { export const privatePages = { profile: urlPattern(/\/profile/, () => "#/profile"), + measures: urlPattern(/\/measures/, () => "#/measures"), search: urlPattern(/\/search/, () => "#/search"), investigation: urlPattern(/\/investigation/, () => "#/investigation"), active: urlPattern(/\/active/, () => "#/active"), @@ -138,6 +140,9 @@ function PrivateRouting(): VNode { case "profile": { return <Officer />; } + case "measures": { + return <Measures />; + } case "caseUpdate": { return ( <CaseUpdate account={location.values.cid} type={location.values.type} /> diff --git a/packages/aml-backoffice-ui/src/hooks/account.ts b/packages/aml-backoffice-ui/src/hooks/account.ts @@ -65,3 +65,36 @@ export function useAccountInformation(paytoHash: string) { if (error) return error; return undefined; } + +export function useServerMeasures() { + const officer = useOfficer(); + const session = officer.state === "ready" ? officer.account : undefined; + + const { + lib: { exchange: api }, + } = useExchangeApiContext(); + + async function fetcher([officer]: [OfficerAccount]) { + return await api.getAmlMesasures(officer); + } + + const { data, error } = useSWR< + TalerExchangeResultByMethod<"getAmlMesasures">, + TalerHttpError + >(!session ? undefined : [session], fetcher, { + refreshInterval: 0, + refreshWhenHidden: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshWhenOffline: false, + errorRetryCount: 0, + errorRetryInterval: 1, + shouldRetryOnError: false, + keepPreviousData: true, + }); + + if (data) return data; + if (error) return error; + return undefined; +} + diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx @@ -369,6 +369,16 @@ export const HomeIcon = () => ( /> </svg> ); +export const FormIcon = () => ( +<svg +xmlns="http://www.w3.org/2000/svg" +viewBox="0 0 24 24" +fill="currentColor" +class="w-6 h-6" +> + <path fillRule="evenodd" d="M1.5 5.625c0-1.036.84-1.875 1.875-1.875h17.25c1.035 0 1.875.84 1.875 1.875v12.75c0 1.035-.84 1.875-1.875 1.875H3.375A1.875 1.875 0 0 1 1.5 18.375V5.625ZM21 9.375A.375.375 0 0 0 20.625 9h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5Zm0 3.75a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5Zm0 3.75a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5ZM10.875 18.75a.375.375 0 0 0 .375-.375v-1.5a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5ZM3.375 15h7.5a.375.375 0 0 0 .375-.375v-1.5a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375Zm0-3.75h7.5a.375.375 0 0 0 .375-.375v-1.5A.375.375 0 0 0 10.875 9h-7.5A.375.375 0 0 0 3 9.375v1.5c0 .207.168.375.375.375Z" clipRule="evenodd" /> +</svg> +); export const SearchIcon = () => ( <svg diff --git a/packages/aml-backoffice-ui/src/pages/Measures.tsx b/packages/aml-backoffice-ui/src/pages/Measures.tsx @@ -0,0 +1,57 @@ +/* + This file is part of GNU Taler + (C) 2022-2024 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +import { + AbsoluteTime, + AmlDecisionRequest, + TalerError, + TalerExchangeApi, +} from "@gnu-taler/taler-util"; +import { + FormMetadata, + InternationalizationAPI, + Loading, + useExchangeApiContext, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; +import { Fragment, h } from "preact"; +import { useUiFormsContext } from "../context/ui-forms.js"; +import { preloadedForms } from "../forms/index.js"; +import { useServerMeasures } from "../hooks/account.js"; +import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js"; + +export function Measures({}: {}) { + const { config } = useExchangeApiContext(); + + const { i18n } = useTranslationContext(); + + // const { forms } = useUiFormsContext(); + + // const allForms = [...forms, ...preloadedForms(i18n)]; + const measures = useServerMeasures(); + + if (!measures || !history) { + return <Loading />; + } + if (measures instanceof TalerError) { + return <ErrorLoadingWithDebug error={measures} />; + } + + return ( + <div> + <pre>{JSON.stringify(measures, undefined ,2)}</pre> + </div> + ); +} diff --git a/packages/taler-util/src/kyc-aml-utils.ts b/packages/taler-util/src/kyc-aml-utils.ts @@ -51,6 +51,8 @@ export function parseAmlProgramParams(): AmlProgramParams { prev.showRequiredContext = true; } else if (arg === "-a") { prev.showRequiredAttributes = true; + } else if (arg === "-i") { + prev.showRequiredInputs = true; } else if (arg === "-h") { prev.showHelp = true; } else if (arg === "-c") { diff --git a/packages/taler-util/src/types-taler-exchange.ts b/packages/taler-util/src/types-taler-exchange.ts @@ -2460,7 +2460,7 @@ export const codecForAmlProgramRequirement = (): Codec<AmlProgramRequirement> => export const codecForKycCheckInformation = (): Codec<KycCheckInformation> => buildCodecForObject<KycCheckInformation>() .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) + .property("description_i18n", codecOptional(codecForInternationalizedString())) .property("fallback", codecForString()) .property("outputs", codecForList(codecForString())) .property("requires", codecForList(codecForString())) @@ -2607,7 +2607,7 @@ export const codecForKycCheckPublicInformation = (): Codec<KycCheckPublicInformation> => buildCodecForObject<KycCheckPublicInformation>() .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) + .property("description_i18n", codecOptional(codecForInternationalizedString())) .build("TalerExchangeApi.KycCheckPublicInformation"); export const codecForKycRequirementInformationId = diff --git a/packages/taler-util/src/types-taler-kyc-aml.ts b/packages/taler-util/src/types-taler-kyc-aml.ts @@ -46,6 +46,7 @@ export type AmlProgramParams = { showVersion?: boolean; showRequiredContext?: boolean; showRequiredAttributes?: boolean; + showRequiredInputs?: boolean; showHelp?: boolean; config?: string; }; @@ -69,6 +70,7 @@ export type AmlProgramDefinition = { name: string; requiredContext: string[]; requiredAttributes: string[]; + requiredInputs: (keyof AmlProgramInput)[] | string[]; logic: AmlProgram; }; @@ -102,6 +104,19 @@ export interface AmlProgramInput { // JSON array with the results of historic // KYC data about the account. kyc_history: KycHistoryEntry[]; + + // Default KYC rules of the exchange (exposed and not exposed). + // + // Default KYC rules are only provided if the AML program + // specifies "default_rules" for its input requirements. + default_rules?: LegitimizationRuleSet; + + // Current KYC rules the exchange applies for this user. + // (exposed and not exposed). + // + // Current KYC rules are only provided if the AML program + // specifies "current_rules" for its input requirements. + current_rules?: LegitimizationRuleSet; } export interface AmlHistoryEntry { diff --git a/packages/taler-util/src/types-taler-merchant.ts b/packages/taler-util/src/types-taler-merchant.ts @@ -3437,7 +3437,7 @@ export const codecForTokenFamilyDetails = (): Codec<TokenFamilyDetails> => .property("slug", codecForString()) .property("name", codecForString()) .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) + .property("description_i18n", codecOptional(codecForInternationalizedString())) .property("valid_after", codecForTimestamp) .property("valid_before", codecForTimestamp) .property("duration", codecForDuration)