taler-typescript-core

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

commit c6e78d08f4aaa75c07ed5eb12a89b3a600803d84
parent 8d82b2fc77b642784ab5025df33493d141cafca2
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu,  8 May 2025 15:54:45 -0300

restriction regex fallback

Diffstat:
Mpackages/challenger-ui/src/pages/AnswerChallenge.tsx | 44++++++++++++++++++++++++++------------------
Mpackages/challenger-ui/src/pages/AskChallenge.tsx | 106++++++++++++++++++++++++++++++++++++++++++-------------------------------------
2 files changed, 82 insertions(+), 68 deletions(-)

diff --git a/packages/challenger-ui/src/pages/AnswerChallenge.tsx b/packages/challenger-ui/src/pages/AnswerChallenge.tsx @@ -19,7 +19,7 @@ import { HttpStatusCode, TalerError, ChallengerApi, - assertUnreachable + assertUnreachable, } from "@gnu-taler/taler-util"; import { Attention, @@ -40,6 +40,7 @@ import { } from "../hooks/challenge.js"; import { SessionId, useSessionState } from "../hooks/session.js"; import { TalerFormAttributes } from "@gnu-taler/taler-util"; +import { useMemo } from "preact/compat"; type Props = { focus?: boolean; @@ -66,9 +67,12 @@ function useReloadOnDeadline(deadline: AbsoluteTime): void { }, [deadline]); } -export function getAddressDescriptionFromAddrType(type: ChallengerApi.ChallengerTermsOfServiceResponse["address_type"], addr: Record<string,string>): string { +export function getAddressDescriptionFromAddrType( + type: ChallengerApi.ChallengerTermsOfServiceResponse["address_type"], + addr: Record<string, string>, +): string { switch (type) { - case "email":{ + case "email": { return addr[TalerFormAttributes.CONTACT_EMAIL]; } case "phone": { @@ -79,7 +83,6 @@ export function getAddressDescriptionFromAddrType(type: ChallengerApi.Challenger } case "postal-ch": { return addr[TalerFormAttributes.CONTACT_NAME]; - } } } @@ -106,17 +109,23 @@ export function AnswerChallenge({ ? result.body : undefined; - const deadline = - lastStatus == undefined - ? undefined - : AbsoluteTime.fromProtocolTimestamp(lastStatus.retransmission_time); + const deadlineTS = + lastStatus == undefined ? undefined : lastStatus.retransmission_time; - useReloadOnDeadline(deadline ?? AbsoluteTime.never()); + const deadline = useMemo(() => { + return !deadlineTS + ? AbsoluteTime.never() + : AbsoluteTime.fromProtocolTimestamp(deadlineTS); + }, [deadlineTS?.t_s]); + + useReloadOnDeadline(deadline); - const lastAddr = - !lastStatus?.last_address - ? undefined - : getAddressDescriptionFromAddrType(config.address_type, lastStatus.last_address); + const lastAddr = !lastStatus?.last_address + ? undefined + : getAddressDescriptionFromAddrType( + config.address_type, + lastStatus.last_address, + ); const unableToChangeAddr = !lastStatus || lastStatus.changes_left < 1; const contact = lastStatus?.last_address; @@ -125,7 +134,6 @@ export function AnswerChallenge({ contact === undefined || lastStatus == undefined || lastStatus.pin_transmissions_left === 0 || - !deadline || !AbsoluteTime.isExpired(deadline) ? undefined : withErrorHandler( @@ -200,15 +208,15 @@ export function AnswerChallenge({ function LastContactSent(): VNode { return ( <p class="mt-2 text-lg leading-8 text-gray-600"> - {!lastStatus || !deadline || AbsoluteTime.isExpired(deadline) ? ( + {!lastStatus || + AbsoluteTime.isExpired(deadline) || + AbsoluteTime.isNever(deadline) ? ( <i18n.Translate> Last TAN code was sent to &quot;{lastAddr} &quot; is not valid anymore. </i18n.Translate> ) : ( - <Attention - title={i18n.str`A TAN code was sent to "${lastAddr}"`} - > + <Attention title={i18n.str`A TAN code was sent to "${lastAddr}"`}> <i18n.Translate> You should wait until &quot; <Time format="dd/MM/yyyy HH:mm:ss" timestamp={deadline} /> diff --git a/packages/challenger-ui/src/pages/AskChallenge.tsx b/packages/challenger-ui/src/pages/AskChallenge.tsx @@ -14,9 +14,13 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { + assertUnreachable, + ChallengerApi, EmptyObject, HttpStatusCode, + InternationalizationAPI, TalerError, + TalerFormAttributes, TranslatedString, } from "@gnu-taler/taler-util"; import { @@ -27,26 +31,19 @@ import { FormUI, LocalNotificationBanner, RouteDefinition, - ShowInputErrorLabel, - Time, useChallengerApiContext, useForm, useLocalNotificationHandler, - useTranslationContext, + useTranslationContext } from "@gnu-taler/web-util/browser"; -import { Fragment, VNode, h } from "preact"; +import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useChallengeSession } from "../hooks/challenge.js"; import { SessionId, useSessionState } from "../hooks/session.js"; import { - doAutoFocus, - getAddressDescriptionFromAddrType, + getAddressDescriptionFromAddrType } from "./AnswerChallenge.js"; import { ErrorLoadingWithDebug } from "./ErrorLoadingWithDebug.js"; -import { ChallengerApi } from "@gnu-taler/taler-util"; -import { TalerFormAttributes } from "@gnu-taler/taler-util"; -import { InternationalizationAPI } from "@gnu-taler/taler-util"; -import { assertUnreachable } from "@gnu-taler/taler-util"; type Props = { onSendSuccesful: () => void; @@ -138,9 +135,9 @@ export function AskChallenge({ const lastStatus = result.body; - const initial = lastStatus.last_address ?? {} + const initial = lastStatus.last_address ?? {}; if (config.address_type === "postal-ch") { - initial[TalerFormAttributes.ADDRESS_COUNTRY] = "CH" + initial[TalerFormAttributes.ADDRESS_COUNTRY] = "CH"; } const design = getFormDesignBasedOnAddressType( @@ -381,13 +378,13 @@ export function AskChallenge({ /> </div> </div> - - - - </form> */} <div class="mx-auto mt-4 max-w-xl "> - <FormUI design={design} model={form.model} onSubmit={onSend?.onClick} /> + <FormUI + design={design} + model={form.model} + onSubmit={onSend?.onClick} + /> </div> {lastStatus === undefined ? undefined : ( @@ -522,6 +519,40 @@ export const CONTACT_REGEX = /.*/; export const ZIPCODE_REGEX = /.*/; export const ADDR_LINES_REGEX = /.*/; +function getRestriction( + i18n: InternationalizationAPI, + serverConfig: ChallengerApi.Restriction | undefined, + fallback?: RegExp, +): { regex: undefined | RegExp; hint: TranslatedString } { + const regexText = + serverConfig && serverConfig.regex ? serverConfig.regex : undefined; + const hint = + serverConfig && serverConfig.hint + ? (serverConfig.hint as TranslatedString) + : i18n.str`Invalid field`; + + let regex; + if (regexText) { + try { + regex = new RegExp(regexText); + } catch (e) { + console.error(`Invalid server regular expression configuration. Server restriction + is "${regexText}" but it didn't compile: ${String(e)}`); + // return ( + // <Attention title={i18n.str`Server configuration error`} type="danger"> + // <i18n.Translate> + // Invalid server regular expression configuration. Server + // restriction is "{regexText}" but it didn't compile: {String(e)} + // </i18n.Translate> + // </Attention> + // ); + regex = fallback; + } + } else { + regex = fallback; + } + return { regex, hint }; +} function getFormDesignBasedOnAddressType( i18n: InternationalizationAPI, type: ChallengerApi.ChallengerTermsOfServiceResponse["address_type"], @@ -529,39 +560,6 @@ function getFormDesignBasedOnAddressType( prevValue: Record<string, string>, read_only: boolean, ): FormDesign { - function getRestriction( - serverConfig: ChallengerApi.Restriction | undefined, - fallback?: RegExp, - ): { regex: undefined | RegExp; hint: TranslatedString } { - const regexText = - serverConfig && serverConfig.regex ? serverConfig.regex : undefined; - const hint = - serverConfig && serverConfig.hint - ? (serverConfig.hint as TranslatedString) - : i18n.str`Invalid field`; - - let regex; - if (regexText) { - try { - regex = new RegExp(regexText); - } catch (e) { - console.error(`Invalid server regular expression configuration. Server restriction - is "${regexText}" but it didn't compile: ${String(e)}`); - // return ( - // <Attention title={i18n.str`Server configuration error`} type="danger"> - // <i18n.Translate> - // Invalid server regular expression configuration. Server - // restriction is "{regexText}" but it didn't compile: {String(e)} - // </i18n.Translate> - // </Attention> - // ); - } - regex = fallback; - } else { - regex = fallback; - } - return { regex, hint }; - } switch (type) { case "email": return { @@ -575,6 +573,7 @@ function getFormDesignBasedOnAddressType( disabled: read_only, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.CONTACT_EMAIL], EMAIL_REGEX, ); @@ -602,6 +601,7 @@ function getFormDesignBasedOnAddressType( disabled: read_only, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.CONTACT_PHONE], PHONE_REGEX, ); @@ -630,6 +630,7 @@ function getFormDesignBasedOnAddressType( placeholder: i18n.str`Person full name or name of the business`, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.CONTACT_NAME], CONTACT_REGEX, ); @@ -648,6 +649,7 @@ function getFormDesignBasedOnAddressType( placeholder: ADDRESS_EXAMPLE_INTERNATIONAL, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.ADDRESS_LINES], ADDR_LINES_REGEX, ); @@ -667,6 +669,7 @@ function getFormDesignBasedOnAddressType( preferredChoiceVals: ["CH", "DE"], validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.ADDRESS_COUNTRY], ); if (restriction.regex && !restriction.regex.test(text)) { @@ -691,6 +694,7 @@ function getFormDesignBasedOnAddressType( placeholder: i18n.str`Your full name`, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.CONTACT_NAME], ); if (restriction.regex && !restriction.regex.test(text)) { @@ -709,6 +713,7 @@ function getFormDesignBasedOnAddressType( placeholder: ADDRESS_EXAMPLE_CH, validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.ADDRESS_LINES], ); if (restriction.regex && !restriction.regex.test(text)) { @@ -727,6 +732,7 @@ function getFormDesignBasedOnAddressType( preferredChoiceVals: ["CH"], validator(text) { const restriction = getRestriction( + i18n, restrictions[TalerFormAttributes.ADDRESS_COUNTRY], ); if (restriction.regex && !restriction.regex.test(text)) {