diff options
author | Florian Dold <florian@dold.me> | 2024-06-11 14:46:04 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-06-11 14:46:11 +0200 |
commit | 11648f3bfc7e87b9472602b95a2f05cfdd964a4c (patch) | |
tree | bc39cb9ead6537251d265f5307576f4f427822c4 /packages | |
parent | 32aea1525551b18e8068f719f1361f3e91a23f70 (diff) | |
download | wallet-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.ts | 1 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/common.ts | 19 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/exchanges.ts | 57 |
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; } |