commit c6e78d08f4aaa75c07ed5eb12a89b3a600803d84
parent 8d82b2fc77b642784ab5025df33493d141cafca2
Author: Sebastian <sebasjm@gmail.com>
Date: Thu, 8 May 2025 15:54:45 -0300
restriction regex fallback
Diffstat:
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 "{lastAddr}
" 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 "
<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)) {