commit c2b9a77f559b3c79f1e0b9cd75daf56ab691ed8c
parent f074734752fbf2b853a6b067ea5b267d1838fef5
Author: Sebastian <sebasjm@taler-systems.com>
Date: Mon, 9 Feb 2026 12:43:36 -0300
fix #11029
Diffstat:
2 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx
@@ -94,7 +94,10 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
const { i18n } = useTranslationContext();
const { lib, logIn, config } = useSessionContext();
- const { value: savedForm, update: saveForm } = useLocalStorage(NEWACCOUNT_STATE_KEY, {});
+ const { value: savedForm, update: saveForm } = useLocalStorage(
+ NEWACCOUNT_STATE_KEY,
+ {},
+ );
const [value, setValue] = useState<Partial<Account>>(savedForm);
@@ -103,6 +106,14 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
const serverRequiresSms =
config.mandatory_tan_channels?.indexOf(TanChannel.SMS) !== -1;
+ let phoneRegex: RegExp | undefined = undefined;
+ if (config.phone_regex)
+ try {
+ phoneRegex = new RegExp(config.phone_regex);
+ } catch (e) {
+ console.log("invalid phone regex", e);
+ }
+
const errors = undefinedIfEmpty<FormErrors<Account>>({
id: !value.id
? i18n.str`Required`
@@ -127,10 +138,14 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
? undefined
: !value.phone
? i18n.str`Required`
- : !value.phone.startsWith("+")
- ? i18n.str`Should start with +`
- : !PHONE_JUST_NUMBERS_REGEX.test(value.phone)
- ? i18n.str`A phone number consists of numbers only`
+ : !phoneRegex
+ ? !value.phone.startsWith("+")
+ ? i18n.str`Should start with +`
+ : !PHONE_JUST_NUMBERS_REGEX.test(value.phone)
+ ? i18n.str`A phone number consists of numbers only`
+ : undefined
+ : !phoneRegex.test(value.phone)
+ ? i18n.str`Invalid phone number`
: undefined,
tos: !value.tos ? i18n.str`Required` : undefined,
});
@@ -155,7 +170,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
phone: next.phone,
tos: next.tos,
};
- saveForm(saved)
+ saveForm(saved);
}
const [notification, safeFunctionHandler] = useLocalNotificationBetter();
@@ -194,7 +209,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
if (success) {
logIn(req.id, success.access_token);
}
- saveForm({})
+ saveForm({});
onCreated();
};
create.onFail = (fail) => {
@@ -311,10 +326,14 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
borderTop: 0,
}}
>
- <button class="button" type="button" onClick={() => {
- saveForm({})
- onCancel()
- }}>
+ <button
+ class="button"
+ type="button"
+ onClick={() => {
+ saveForm({});
+ onCancel();
+ }}
+ >
<i18n.Translate>Cancel</i18n.Translate>
</button>
<ButtonBetterBulma onClick={create} type="submit">
diff --git a/packages/taler-util/src/types-taler-merchant.ts b/packages/taler-util/src/types-taler-merchant.ts
@@ -1243,6 +1243,12 @@ export interface MerchantVersionResponse {
// Since **v25**.
report_generators: string[];
+ // Posix regular expression for allowed phone numbers;
+ // applies when creating or patching an instance.
+ // Optional, can be NULL for no restrictions.
+ // Since **v26**.
+ phone_regex?: string;
+
// Array of exchanges trusted by the merchant.
// Since protocol **v6**.
exchanges: ExchangeConfigInfo[];
@@ -3184,7 +3190,6 @@ export interface ExpectedTransferDetails {
}
interface ExchangeTransferReconciliationDetails {
-
// ID of the order for which these are the
// reconciliation details.
order_id: string;
@@ -3199,7 +3204,6 @@ interface ExchangeTransferReconciliationDetails {
// Deposit fees paid to the exchange for this order.
deposit_fee: AmountString;
-
}
export interface OtpDeviceAddDetails {
@@ -4159,6 +4163,10 @@ export const codecForTalerMerchantConfigResponse =
"report_generators",
codecOptionalDefault(codecForList(codecForString()), []),
)
+ .property(
+ "phone_regex",
+ codecOptional(codecForString()),
+ )
.property("exchanges", codecForList(codecForExchangeConfigInfo()))
.property("implementation", codecOptional(codecForString()))
.property(