save tos etag after forced refresh
This commit is contained in:
parent
a5f357f078
commit
984cbb7ab7
@ -731,14 +731,14 @@ export const codecForGetWithdrawalDetailsForAmountRequest =
|
||||
|
||||
export interface AcceptExchangeTosRequest {
|
||||
exchangeBaseUrl: string;
|
||||
etag: string;
|
||||
etag: string | undefined;
|
||||
}
|
||||
|
||||
export const codecForAcceptExchangeTosRequest =
|
||||
(): Codec<AcceptExchangeTosRequest> =>
|
||||
buildCodecForObject<AcceptExchangeTosRequest>()
|
||||
.property("exchangeBaseUrl", codecForString())
|
||||
.property("etag", codecForString())
|
||||
.property("etag", codecOptional(codecForString()))
|
||||
.build("AcceptExchangeTosRequest");
|
||||
|
||||
export interface ApplyRefundRequest {
|
||||
|
@ -478,7 +478,7 @@ class BankServiceBase {
|
||||
protected globalTestState: GlobalTestState,
|
||||
protected bankConfig: BankConfig,
|
||||
protected configFile: string,
|
||||
) {}
|
||||
) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -920,7 +920,7 @@ export class FakeBankService {
|
||||
private globalTestState: GlobalTestState,
|
||||
private bankConfig: FakeBankConfig,
|
||||
private configFile: string,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async start(): Promise<void> {
|
||||
this.proc = this.globalTestState.spawnService(
|
||||
@ -1175,7 +1175,7 @@ export class ExchangeService implements ExchangeServiceInterface {
|
||||
private exchangeConfig: ExchangeConfig,
|
||||
private configFilename: string,
|
||||
private keyPair: EddsaKeyPair,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
get name() {
|
||||
return this.exchangeConfig.name;
|
||||
@ -1276,7 +1276,7 @@ export class ExchangeService implements ExchangeServiceInterface {
|
||||
accTargetType,
|
||||
`${this.exchangeConfig.currency}:0.01`,
|
||||
`${this.exchangeConfig.currency}:0.01`,
|
||||
`${this.exchangeConfig.currency}:0.01`,
|
||||
// `${this.exchangeConfig.currency}:0.01`,
|
||||
"upload",
|
||||
],
|
||||
);
|
||||
@ -1398,7 +1398,7 @@ export class MerchantApiClient {
|
||||
constructor(
|
||||
private baseUrl: string,
|
||||
public readonly auth: MerchantAuthConfiguration,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
|
||||
const url = new URL("private/auth", this.baseUrl);
|
||||
@ -1591,7 +1591,7 @@ export class MerchantService implements MerchantServiceInterface {
|
||||
private globalState: GlobalTestState,
|
||||
private merchantConfig: MerchantConfig,
|
||||
private configFilename: string,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
private currentTimetravel: Duration | undefined;
|
||||
|
||||
@ -1888,10 +1888,8 @@ export class WalletCli {
|
||||
const resp = await sh(
|
||||
self.globalTestState,
|
||||
`wallet-${self.name}`,
|
||||
`taler-wallet-cli ${
|
||||
self.timetravelArg ?? ""
|
||||
} --no-throttle -LTRACE --wallet-db '${
|
||||
self.dbfile
|
||||
`taler-wallet-cli ${self.timetravelArg ?? ""
|
||||
} --no-throttle -LTRACE --wallet-db '${self.dbfile
|
||||
}' api '${op}' ${shellWrap(JSON.stringify(payload))}`,
|
||||
);
|
||||
console.log("--- wallet core response ---");
|
||||
|
@ -363,13 +363,20 @@ async function provideExchangeRecord(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
now: Timestamp,
|
||||
): Promise<ExchangeRecord> {
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord | undefined;
|
||||
}> {
|
||||
|
||||
return await ws.db
|
||||
.mktx((x) => ({ exchanges: x.exchanges }))
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.runReadWrite(async (tx) => {
|
||||
let r = await tx.exchanges.get(baseUrl);
|
||||
if (!r) {
|
||||
r = {
|
||||
let exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
const r = {
|
||||
permanent: true,
|
||||
baseUrl: baseUrl,
|
||||
retryInfo: initRetryInfo(),
|
||||
@ -379,8 +386,10 @@ async function provideExchangeRecord(
|
||||
nextRefreshCheck: now,
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
exchange = r;
|
||||
}
|
||||
return r;
|
||||
const exchangeDetails = await getExchangeDetails(tx, baseUrl);
|
||||
return { exchange, exchangeDetails };
|
||||
});
|
||||
}
|
||||
|
||||
@ -519,33 +528,15 @@ async function updateExchangeFromUrlImpl(
|
||||
exchange: ExchangeRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord;
|
||||
}> {
|
||||
logger.trace(`updating exchange info for ${baseUrl}`);
|
||||
logger.info(`updating exchange info for ${baseUrl}, forced: ${forceNow}`);
|
||||
const now = getTimestampNow();
|
||||
baseUrl = canonicalizeBaseUrl(baseUrl);
|
||||
|
||||
const r = await provideExchangeRecord(ws, baseUrl, now);
|
||||
const { exchange, exchangeDetails } = await provideExchangeRecord(ws, baseUrl, now);
|
||||
|
||||
if (!forceNow && r && !isTimestampExpired(r.nextUpdate)) {
|
||||
const res = await ws.db
|
||||
.mktx((x) => ({
|
||||
exchanges: x.exchanges,
|
||||
exchangeDetails: x.exchangeDetails,
|
||||
}))
|
||||
.runReadOnly(async (tx) => {
|
||||
const exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
return;
|
||||
}
|
||||
const exchangeDetails = await getExchangeDetails(tx, baseUrl);
|
||||
if (!exchangeDetails) {
|
||||
return;
|
||||
}
|
||||
return { exchange, exchangeDetails };
|
||||
});
|
||||
if (res) {
|
||||
logger.info("using existing exchange info");
|
||||
return res;
|
||||
}
|
||||
if (!forceNow && exchangeDetails !== undefined && !isTimestampExpired(exchange.nextUpdate)) {
|
||||
logger.info("using existing exchange info");
|
||||
return { exchange, exchangeDetails };
|
||||
}
|
||||
|
||||
logger.info("updating exchange /keys info");
|
||||
@ -584,6 +575,7 @@ async function updateExchangeFromUrlImpl(
|
||||
timeout,
|
||||
acceptedFormat,
|
||||
);
|
||||
const tosHasBeenAccepted = exchangeDetails?.termsOfServiceAcceptedEtag === tosDownload.tosEtag
|
||||
|
||||
let recoupGroupId: string | undefined;
|
||||
|
||||
@ -619,7 +611,7 @@ async function updateExchangeFromUrlImpl(
|
||||
exchangeBaseUrl: r.baseUrl,
|
||||
wireInfo,
|
||||
termsOfServiceText: tosDownload.tosText,
|
||||
termsOfServiceAcceptedEtag: undefined,
|
||||
termsOfServiceAcceptedEtag: tosHasBeenAccepted ? tosDownload.tosEtag : undefined,
|
||||
termsOfServiceContentType: tosDownload.tosContentType,
|
||||
termsOfServiceLastEtag: tosDownload.tosEtag,
|
||||
termsOfServiceAcceptedTimestamp: getTimestampNow(),
|
||||
|
@ -27,9 +27,10 @@ export function TermsOfServiceSection({
|
||||
onReview,
|
||||
}: Props): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
const ableToReviewTermsOfService = onReview !== undefined;
|
||||
if (!reviewing) {
|
||||
if (!reviewed) {
|
||||
if (!onReview) {
|
||||
if (!ableToReviewTermsOfService) {
|
||||
return (
|
||||
<Fragment>
|
||||
{terms.status === "notfound" && (
|
||||
@ -78,7 +79,7 @@ export function TermsOfServiceSection({
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
{onReview && (
|
||||
{ableToReviewTermsOfService && (
|
||||
<section>
|
||||
<LinkSuccess upperCased onClick={() => onReview(true)}>
|
||||
<i18n.Translate>Show terms of service</i18n.Translate>
|
||||
@ -96,7 +97,7 @@ export function TermsOfServiceSection({
|
||||
}
|
||||
onToggle={() => {
|
||||
onAccept(!reviewed);
|
||||
if (onReview) onReview(false);
|
||||
if (ableToReviewTermsOfService) onReview(false);
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
@ -136,7 +137,7 @@ export function TermsOfServiceSection({
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
{reviewed && onReview && (
|
||||
{reviewed && ableToReviewTermsOfService && (
|
||||
<section>
|
||||
<LinkSuccess upperCased onClick={() => onReview(false)}>
|
||||
<i18n.Translate>Hide terms of service</i18n.Translate>
|
||||
@ -155,7 +156,7 @@ export function TermsOfServiceSection({
|
||||
}
|
||||
onToggle={() => {
|
||||
onAccept(!reviewed);
|
||||
if (onReview) onReview(false);
|
||||
if (ableToReviewTermsOfService) onReview(false);
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
|
@ -293,11 +293,14 @@ export function WithdrawPageWithParsedURI({
|
||||
|
||||
const details = detailsHook.response;
|
||||
|
||||
const onAccept = async (): Promise<void> => {
|
||||
const onAccept = async (accepted: boolean): Promise<void> => {
|
||||
if (!exchange) return;
|
||||
try {
|
||||
await wxApi.setExchangeTosAccepted(exchange, details.tos.version);
|
||||
setReviewed(true);
|
||||
await wxApi.setExchangeTosAccepted(
|
||||
exchange,
|
||||
accepted ? details.tos.version : undefined,
|
||||
);
|
||||
setReviewed(accepted);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
//FIXME: uncomment this and display error
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
CoinDumpJson,
|
||||
ExchangeListItem,
|
||||
NotificationType,
|
||||
Timestamp,
|
||||
Translate,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
|
||||
@ -246,7 +247,13 @@ export function View({
|
||||
{operations.reverse().map((o) => {
|
||||
return (
|
||||
<NotifyUpdateFadeOut key={hashObjectId(o)}>
|
||||
<dt>{o.type}</dt>
|
||||
<dt>
|
||||
{o.type}{" "}
|
||||
<Time
|
||||
timestamp={o.timestampDue}
|
||||
format="yy/MM/dd hh:mm:ss"
|
||||
/>
|
||||
</dt>
|
||||
<dd>
|
||||
<pre>{JSON.stringify(o, undefined, 2)}</pre>
|
||||
</dd>
|
||||
|
@ -319,7 +319,6 @@ try {
|
||||
function headerListener(
|
||||
details: chrome.webRequest.WebResponseHeadersDetails,
|
||||
): chrome.webRequest.BlockingResponse | undefined {
|
||||
console.log("header listener");
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError);
|
||||
return;
|
||||
@ -329,13 +328,11 @@ function headerListener(
|
||||
console.warn("wallet not available while handling header");
|
||||
return;
|
||||
}
|
||||
console.log("in header listener");
|
||||
if (
|
||||
details.statusCode === 402 ||
|
||||
details.statusCode === 202 ||
|
||||
details.statusCode === 200
|
||||
) {
|
||||
console.log(`got 402/202 from ${details.url}`);
|
||||
for (const header of details.responseHeaders || []) {
|
||||
if (header.name.toLowerCase() === "taler") {
|
||||
const talerUri = header.value || "";
|
||||
|
Loading…
Reference in New Issue
Block a user