commit ce89223b51e71dae83d00fa93a0ab1c09b3c190a
parent 77456187e967a81fe77de59a5df42460d54f0972
Author: Florian Dold <florian@dold.me>
Date: Tue, 11 Jun 2024 16:39:09 +0200
wallet-core: check that ToS was accepted for certain requests
Diffstat:
6 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/packages/taler-util/src/errors.ts b/packages/taler-util/src/errors.ts
@@ -166,6 +166,11 @@ export interface DetailsMap {
[TalerErrorCode.WALLET_DB_UNAVAILABLE]: {
innerError: TalerErrorDetail | undefined;
};
+ [TalerErrorCode.WALLET_EXCHANGE_TOS_NOT_ACCEPTED]: {
+ exchangeBaseUrl: string;
+ tosStatus: string;
+ currentEtag: string | undefined;
+ };
}
type ErrBody<Y> = Y extends keyof DetailsMap ? DetailsMap[Y] : empty;
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
@@ -31,6 +31,8 @@ import {
ExchangeUpdateStatus,
Logger,
RefreshReason,
+ TalerError,
+ TalerErrorCode,
TalerErrorDetail,
TalerPreciseTimestamp,
TalerProtocolTimestamp,
@@ -61,6 +63,7 @@ import {
WithdrawalGroupRecord,
timestampPreciseToDb,
} from "./db.js";
+import { ReadyExchangeSummary } from "./exchanges.js";
import { createRefreshGroup } from "./refresh.js";
import { WalletExecutionContext, getDenomInfo } from "./wallet.js";
@@ -829,3 +832,22 @@ export async function genericWaitForState(
throw e;
}
}
+
+export function requireExchangeTosAcceptedOrThrow(
+ exchange: ReadyExchangeSummary,
+): void {
+ switch (exchange.tosStatus) {
+ case ExchangeTosStatus.Accepted:
+ case ExchangeTosStatus.MissingTos:
+ break;
+ default:
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_EXCHANGE_TOS_NOT_ACCEPTED,
+ {
+ exchangeBaseUrl: exchange.exchangeBaseUrl,
+ currentEtag: exchange.tosCurrentEtag,
+ tosStatus: exchange.tosStatus,
+ },
+ );
+ }
+}
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
@@ -885,6 +885,7 @@ async function downloadTosMeta(
switch (resp.status) {
case HttpStatusCode.NotFound:
+ case HttpStatusCode.NotImplemented:
return { type: "not-found" };
case HttpStatusCode.Ok:
break;
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -59,6 +59,7 @@ import {
TombstoneTag,
TransactionContext,
constructTaskIdentifier,
+ requireExchangeTosAcceptedOrThrow,
} from "./common.js";
import {
KycPendingInfo,
@@ -1021,7 +1022,8 @@ export async function initiatePeerPullPayment(
const exchangeBaseUrl = maybeExchangeBaseUrl;
- await fetchFreshExchange(wex, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(wex, exchangeBaseUrl);
+ requireExchangeTosAcceptedOrThrow(exchange);
const mergeReserveInfo = await getMergeReserveInfo(wex, {
exchangeBaseUrl: exchangeBaseUrl,
diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -61,6 +61,7 @@ import {
TombstoneTag,
TransactionContext,
constructTaskIdentifier,
+ requireExchangeTosAcceptedOrThrow,
} from "./common.js";
import {
KycPendingInfo,
@@ -407,7 +408,8 @@ export async function preparePeerPushCredit(
const exchangeBaseUrl = uri.exchangeBaseUrl;
- await fetchFreshExchange(wex, exchangeBaseUrl);
+ const exchange = await fetchFreshExchange(wex, exchangeBaseUrl);
+ requireExchangeTosAcceptedOrThrow(exchange);
const contractPriv = uri.contractPriv;
const contractPub = encodeCrock(eddsaGetPublic(decodeCrock(contractPriv)));
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
@@ -45,6 +45,7 @@ import {
EddsaPrivateKeyString,
ExchangeBatchWithdrawRequest,
ExchangeListItem,
+ ExchangeTosStatus,
ExchangeUpdateStatus,
ExchangeWireAccount,
ExchangeWithdrawBatchResponse,
@@ -118,6 +119,7 @@ import {
genericWaitForState,
makeCoinAvailable,
makeCoinsVisible,
+ requireExchangeTosAcceptedOrThrow,
} from "./common.js";
import { EddsaKeypair } from "./crypto/cryptoImplementation.js";
import {
@@ -3118,6 +3120,7 @@ export async function confirmWithdrawal(
}
const exchange = await fetchFreshExchange(wex, selectedExchange);
+ requireExchangeTosAcceptedOrThrow(exchange);
const talerWithdrawUri = withdrawalGroup.wgInfo.bankInfo.talerWithdrawUri;
const confirmUrl = withdrawalGroup.wgInfo.bankInfo.confirmUrl;