aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-06-11 14:46:04 +0200
committerFlorian Dold <florian@dold.me>2024-06-11 14:46:11 +0200
commit11648f3bfc7e87b9472602b95a2f05cfdd964a4c (patch)
treebc39cb9ead6537251d265f5307576f4f427822c4 /packages
parent32aea1525551b18e8068f719f1361f3e91a23f70 (diff)
downloadwallet-core-11648f3bfc7e87b9472602b95a2f05cfdd964a4c.tar.xz
wallet-core: introduce 'missing-tos' tosStatus for exchange entries
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-util/src/wallet-types.ts1
-rw-r--r--packages/taler-wallet-core/src/common.ts19
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts57
3 files changed, 62 insertions, 15 deletions
diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts
index a7aa4f863..d23780145 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -1338,6 +1338,7 @@ export enum ExchangeTosStatus {
Pending = "pending",
Proposed = "proposed",
Accepted = "accepted",
+ MissingTos = "missing-tos",
}
export enum ExchangeEntryStatus {
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
index a20278cf3..4b4f73185 100644
--- a/packages/taler-wallet-core/src/common.ts
+++ b/packages/taler-wallet-core/src/common.ts
@@ -41,7 +41,6 @@ import {
checkDbInvariant,
checkLogicInvariant,
durationMul,
- j2s,
} from "@gnu-taler/taler-util";
import {
BackupProviderRecord,
@@ -121,7 +120,10 @@ export async function makeCoinAvailable(
coinRecord.exchangeBaseUrl,
coinRecord.denomPubHash,
]);
- checkDbInvariant(!!denom, `denomination of a coin is missing hash: ${coinRecord.denomPubHash}`);
+ checkDbInvariant(
+ !!denom,
+ `denomination of a coin is missing hash: ${coinRecord.denomPubHash}`,
+ );
const ageRestriction = coinRecord.maxAge;
let car = await tx.coinAvailability.get([
coinRecord.exchangeBaseUrl,
@@ -175,13 +177,19 @@ export async function spendCoins(
coin.exchangeBaseUrl,
coin.denomPubHash,
);
- checkDbInvariant(!!denom, `denomination of a coin is missing hash: ${coin.denomPubHash}`);
+ checkDbInvariant(
+ !!denom,
+ `denomination of a coin is missing hash: ${coin.denomPubHash}`,
+ );
const coinAvailability = await tx.coinAvailability.get([
coin.exchangeBaseUrl,
coin.denomPubHash,
coin.maxAge,
]);
- checkDbInvariant(!!coinAvailability, `age denom info is missing for ${coin.maxAge}`);
+ checkDbInvariant(
+ !!coinAvailability,
+ `age denom info is missing for ${coin.maxAge}`,
+ );
const contrib = csi.contributions[i];
if (coin.status !== CoinStatus.Fresh) {
const alloc = coin.spendAllocation;
@@ -257,6 +265,9 @@ export enum TombstoneTag {
export function getExchangeTosStatusFromRecord(
exchange: ExchangeEntryRecord,
): ExchangeTosStatus {
+ if (exchange.tosCurrentEtag == null) {
+ return ExchangeTosStatus.MissingTos;
+ }
if (!exchange.tosAcceptedEtag) {
return ExchangeTosStatus.Proposed;
}
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
index adb696de0..51c702ca9 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -53,6 +53,7 @@ import {
GetExchangeResourcesResponse,
GetExchangeTosResult,
GlobalFees,
+ HttpStatusCode,
LibtoolVersion,
Logger,
NotificationType,
@@ -93,6 +94,8 @@ import {
getExpiry,
readSuccessResponseJsonOrThrow,
readSuccessResponseTextOrThrow,
+ readTalerErrorResponse,
+ throwUnexpectedRequestError,
} from "@gnu-taler/taler-util/http";
import {
PendingTaskType,
@@ -861,6 +864,40 @@ async function downloadExchangeKeysInfo(
};
}
+type TosMetaResult = { type: "not-found" } | { type: "ok"; etag: string };
+
+/**
+ * Download metadata about an exchange's terms of service.
+ */
+async function downloadTosMeta(
+ wex: WalletExecutionContext,
+ exchangeBaseUrl: string,
+): Promise<TosMetaResult> {
+ logger.trace(`downloading exchange tos metadata for ${exchangeBaseUrl}`);
+ const reqUrl = new URL("terms", exchangeBaseUrl);
+
+ // FIXME: We can/should make a HEAD request here.
+ // Not sure if qtart supports it at the moment.
+ const resp = await wex.http.fetch(reqUrl.href, {
+ cancellationToken: wex.cancellationToken,
+ });
+
+ switch (resp.status) {
+ case HttpStatusCode.NotFound:
+ return { type: "not-found" };
+ case HttpStatusCode.Ok:
+ break;
+ default:
+ throwUnexpectedRequestError(resp, await readTalerErrorResponse(resp));
+ }
+
+ const etag = resp.headers.get("etag") || "unknown";
+ return {
+ type: "ok",
+ etag,
+ };
+}
+
async function downloadTosFromAcceptedFormat(
wex: WalletExecutionContext,
baseUrl: string,
@@ -1367,7 +1404,6 @@ export async function updateExchangeFromUrlHandler(
AbsoluteTime.min(nextUpdateStamp, nextRefreshCheckStamp),
);
}
-
}
// When doing the auto-refresh check, we always update
@@ -1423,15 +1459,7 @@ export async function updateExchangeFromUrlHandler(
logger.trace("finished validating exchange /wire info");
- // We download the text/plain version here,
- // because that one needs to exist, and we
- // will get the current etag from the response.
- const tosDownload = await downloadTosFromAcceptedFormat(
- wex,
- exchangeBaseUrl,
- timeout,
- ["text/plain"],
- );
+ const tosMeta = await downloadTosMeta(wex, exchangeBaseUrl);
logger.trace("updating exchange info in database");
@@ -1524,7 +1552,14 @@ export async function updateExchangeFromUrlHandler(
};
r.noFees = noFees;
r.peerPaymentsDisabled = peerPaymentsDisabled;
- r.tosCurrentEtag = tosDownload.tosEtag;
+ switch (tosMeta.type) {
+ case "not-found":
+ r.tosCurrentEtag = undefined;
+ break;
+ case "ok":
+ r.tosCurrentEtag = tosMeta.etag;
+ break;
+ }
if (existingDetails?.rowId) {
newDetails.rowId = existingDetails.rowId;
}