From 5eec408d9fb5e8c2375937166997ef8267a4053c Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 22 Nov 2023 18:18:42 +0100 Subject: wallet-core: check debit account restrictions for deposit --- .../taler-wallet-core/src/util/coinSelection.ts | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'packages/taler-wallet-core/src/util') diff --git a/packages/taler-wallet-core/src/util/coinSelection.ts b/packages/taler-wallet-core/src/util/coinSelection.ts index 8c90f26f1..9506fff19 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.ts @@ -26,6 +26,7 @@ import { GlobalIDB } from "@gnu-taler/idb-bridge"; import { AbsoluteTime, + AccountRestriction, AgeCommitmentProof, AgeRestriction, AllowedAuditorInfo, @@ -42,6 +43,7 @@ import { Duration, ForcedCoinSel, ForcedDenomSel, + InternationalizedString, j2s, Logger, parsePaytoUri, @@ -535,6 +537,30 @@ function selectForced( return selectedDenom; } +export function checkAccountRestriction( + paytoUri: string, + restrictions: AccountRestriction[], +): { ok: boolean; hint?: string; hintI18n?: InternationalizedString } { + for (const myRestriction of restrictions) { + switch (myRestriction.type) { + case "deny": + return { ok: false }; + case "regex": + const regex = new RegExp(myRestriction.payto_regex); + if (!regex.test(paytoUri)) { + return { + ok: false, + hint: myRestriction.human_hint, + hintI18n: myRestriction.human_hint_i18n, + }; + } + } + } + return { + ok: true, + }; +} + export interface SelectPayCoinRequestNg { exchanges: AllowedExchangeInfo[]; auditors: AllowedAuditorInfo[]; @@ -546,6 +572,15 @@ export interface SelectPayCoinRequestNg { prevPayCoins?: PreviousPayCoins; requiredMinimumAge?: number; forcedSelection?: ForcedCoinSel; + + /** + * Deposit payto URI, in case we already know the account that + * will be deposited into. + * + * That is typically the case when the wallet does a deposit to + * return funds to the user's own bank account. + */ + depositPaytoUri?: string; } export type AvailableDenom = DenominationInfo & { @@ -593,6 +628,20 @@ async function selectPayMerchantCandidates( AbsoluteTime.fromProtocolTimestamp(x.endStamp), ); })?.wireFee; + let debitAccountCheckOk = false; + if (req.depositPaytoUri) { + // FIXME: We should somehow propagate the hint here! + const checkResult = checkAccountRestriction( + req.depositPaytoUri, + acc.debit_restrictions, + ); + if (checkResult.ok) { + debitAccountCheckOk = true; + } + } else { + debitAccountCheckOk = true; + } + if (wireFeeStr) { wireMethodFee = wireFeeStr; } @@ -602,6 +651,7 @@ async function selectPayMerchantCandidates( break; } wfPerExchange[exchange.baseUrl] = Amounts.parseOrThrow(wireMethodFee); + // 3.- exchange is trusted in the exchange list or auditor list let accepted = false; for (const allowedExchange of req.exchanges) { -- cgit v1.2.3