diff options
| author | Sebastian <sebasjm@gmail.com> | 2021-09-13 15:32:06 -0300 | 
|---|---|---|
| committer | Sebastian <sebasjm@gmail.com> | 2021-09-13 15:32:15 -0300 | 
| commit | 9f009873809d5b7e8d1d95d77f009862724c577b (patch) | |
| tree | cd424abc49b290c684f9947daa759a9a6fb28150 /packages | |
| parent | 57b6cd42692584063819ccac3c2218f1283332a4 (diff) | |
added integration with the wallet-core to get info about the last tos approved
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/taler-util/src/walletTypes.ts | 2 | ||||
| -rw-r--r-- | packages/taler-wallet-core/src/db.ts | 5 | ||||
| -rw-r--r-- | packages/taler-wallet-core/src/operations/backup/import.ts | 1 | ||||
| -rw-r--r-- | packages/taler-wallet-core/src/operations/exchanges.ts | 13 | ||||
| -rw-r--r-- | packages/taler-wallet-core/src/operations/withdraw.ts | 37 | ||||
| -rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 2 | ||||
| -rw-r--r-- | packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx | 4 | ||||
| -rw-r--r-- | packages/taler-wallet-webextension/src/cta/Withdraw.tsx | 46 | ||||
| -rw-r--r-- | packages/taler-wallet-webextension/src/wxApi.ts | 13 | 
9 files changed, 109 insertions, 14 deletions
| diff --git a/packages/taler-util/src/walletTypes.ts b/packages/taler-util/src/walletTypes.ts index 7ec182fa2..79403ac69 100644 --- a/packages/taler-util/src/walletTypes.ts +++ b/packages/taler-util/src/walletTypes.ts @@ -716,12 +716,14 @@ export const codecForGetWithdrawalDetailsForUri = (): Codec<GetWithdrawalDetails  export interface GetExchangeWithdrawalInfo {    exchangeBaseUrl: string;    amount: AmountJson; +  tosAcceptedFormat?: string[];  }  export const codecForGetExchangeWithdrawalInfo = (): Codec<GetExchangeWithdrawalInfo> =>    buildCodecForObject<GetExchangeWithdrawalInfo>()      .property("exchangeBaseUrl", codecForString())      .property("amount", codecForAmountJson()) +    .property("tosAcceptedFormat", codecOptional(codecForList(codecForString())))      .build("GetExchangeWithdrawalInfo");  export interface AbortProposalRequest { diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 7ea8b9ead..902f749cf 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -450,6 +450,11 @@ export interface ExchangeDetailsRecord {    termsOfServiceText: string | undefined;    /** +   * content-type of the last downloaded termsOfServiceText. +   */ +   termsOfServiceContentType: string | undefined; + +  /**     * ETag for last terms of service download.     */    termsOfServiceLastEtag: string | undefined; diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index 9eee34cf0..7623ab189 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -306,6 +306,7 @@ export async function importBackup(              termsOfServiceAcceptedEtag: backupExchangeDetails.tos_accepted_etag,              termsOfServiceText: undefined,              termsOfServiceLastEtag: undefined, +            termsOfServiceContentType: undefined,              termsOfServiceAcceptedTimestamp:                backupExchangeDetails.tos_accepted_timestamp,              wireInfo, diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index cf52e00b6..9cd20c673 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -127,20 +127,22 @@ function getExchangeRequestTimeout(e: ExchangeRecord): Duration {    return { d_ms: 5000 };  } -interface ExchangeTosDownloadResult { +export interface ExchangeTosDownloadResult {    tosText: string;    tosEtag: string; +  tosContentType: string;  } -async function downloadExchangeWithTermsOfService( +export async function downloadExchangeWithTermsOfService(    exchangeBaseUrl: string,    http: HttpRequestLibrary,    timeout: Duration, +  contentType: string,  ): Promise<ExchangeTosDownloadResult> {    const reqUrl = new URL("terms", exchangeBaseUrl);    reqUrl.searchParams.set("cacheBreaker", WALLET_CACHE_BREAKER_CLIENT_VERSION);    const headers = { -    Accept: "text/plain", +    Accept: contentType,    };    const resp = await http.get(reqUrl.href, { @@ -149,8 +151,9 @@ async function downloadExchangeWithTermsOfService(    });    const tosText = await readSuccessResponseTextOrThrow(resp);    const tosEtag = resp.headers.get("etag") || "unknown"; +  const tosContentType = resp.headers.get("content-type") || "text/plain"; -  return { tosText, tosEtag }; +  return { tosText, tosEtag, tosContentType };  }  /** @@ -469,6 +472,7 @@ async function updateExchangeFromUrlImpl(      baseUrl,      ws.http,      timeout, +    "text/plain"    );    let recoupGroupId: string | undefined = undefined; @@ -506,6 +510,7 @@ async function updateExchangeFromUrlImpl(          wireInfo,          termsOfServiceText: tosDownload.tosText,          termsOfServiceAcceptedEtag: undefined, +        termsOfServiceContentType: tosDownload.tosContentType,          termsOfServiceLastEtag: tosDownload.tosEtag,          termsOfServiceAcceptedTimestamp: getTimestampNow(),        }; diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 620ad88be..f63723535 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -66,6 +66,8 @@ import {    WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,    WALLET_EXCHANGE_PROTOCOL_VERSION,  } from "../versions.js"; +import { stringify } from "querystring"; +import { downloadExchangeWithTermsOfService, ExchangeTosDownloadResult } from "./exchanges";  /**   * Logger for this file. @@ -132,6 +134,11 @@ export interface ExchangeWithdrawDetails {    termsOfServiceAccepted: boolean;    /** +   * Tos  +   */ +  tosRequested: ExchangeTosDownloadResult | undefined + +  /**     * The exchange is trusted directly.     */    isTrusted: boolean; @@ -930,6 +937,7 @@ export async function getExchangeWithdrawalInfo(    ws: InternalWalletState,    baseUrl: string,    amount: AmountJson, +  tosAcceptedFormat?: string[],  ): Promise<ExchangeWithdrawDetails> {    const {      exchange, @@ -996,6 +1004,34 @@ export async function getExchangeWithdrawalInfo(      }    } +  const noTosDownloaded =  +    exchangeDetails.termsOfServiceContentType === undefined ||  +    exchangeDetails.termsOfServiceAcceptedEtag === undefined ||  +    exchangeDetails.termsOfServiceText === undefined; +   +  let tosFound: ExchangeTosDownloadResult | undefined = noTosDownloaded ? undefined : { +    tosContentType: exchangeDetails.termsOfServiceContentType!, +    tosEtag: exchangeDetails.termsOfServiceAcceptedEtag!, +    tosText: exchangeDetails.termsOfServiceText!, +  }; + +  try { +    if (tosAcceptedFormat) for (const format of tosAcceptedFormat) { +      const resp = await downloadExchangeWithTermsOfService( +        exchangeDetails.exchangeBaseUrl, +        ws.http, +        { d_ms: 1000 }, +        format +      ); +      if (resp.tosContentType === format) { +        tosFound = resp +        break +      } +    } +  } catch (e) { +    tosFound = undefined +  } +    const withdrawFee = Amounts.sub(      selectedDenoms.totalWithdrawCost,      selectedDenoms.totalCoinValue, @@ -1018,6 +1054,7 @@ export async function getExchangeWithdrawalInfo(      walletVersion: WALLET_EXCHANGE_PROTOCOL_VERSION,      withdrawFee,      termsOfServiceAccepted: tosAccepted, +    tosRequested: tosFound    };    return ret;  } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index cbaf03c3b..a0da3d356 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -696,7 +696,7 @@ async function dispatchRequestInternal(      }      case "getExchangeWithdrawalInfo": {        const req = codecForGetExchangeWithdrawalInfo().decode(payload); -      return await getExchangeWithdrawalInfo(ws, req.exchangeBaseUrl, req.amount); +      return await getExchangeWithdrawalInfo(ws, req.exchangeBaseUrl, req.amount, req.tosAcceptedFormat);      }      case "acceptManualWithdrawal": {        const req = codecForAcceptManualWithdrawalRequet().decode(payload); diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx index 022b92454..94fdea8fb 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx @@ -35,6 +35,8 @@ export default {  };  const termsXml = `<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd"> +<!-- Generated by Docutils 0.14 -->  <document source="/home/grothoff/research/taler/exchange/contrib/tos/tos.rst">      <section ids="terms-of-service" names="terms\ of\ service">          <title>Terms Of Service</title> @@ -234,7 +236,6 @@ const termsXml = `<?xml version="1.0" encoding="utf-8"?>              <enumerated_list enumtype="loweralpha" prefix="(" suffix=")">                  <list_item>                      <paragraph>any lost profits, data loss, cost of procurement of substitute goods or -* TLSv1.3 (IN), TLS Unknown, Unknown (23):                          services, or direct, indirect, incidental, special, punitive, compensatory,                          or consequential damages of any kind whatsoever resulting from:</paragraph>                  </list_item> @@ -377,7 +378,6 @@ const termsXml = `<?xml version="1.0" encoding="utf-8"?>          </section>      </section>  </document> -  `;  export const WithdrawNewTermsXML = createExample(TestedComponent, { diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index c0347000d..ac25bcd15 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -30,7 +30,7 @@ import { LogoHeader } from '../components/LogoHeader';  import { Part } from '../components/Part';  import { ButtonDestructive, ButtonSuccess, ButtonWarning, LinkSuccess, TermsOfService, WalletAction } from '../components/styled';  import { -  acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, onUpdateNotification +  acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, onUpdateNotification, setExchangeTosAccepted  } from "../wxApi";  import { h } from 'preact'; @@ -48,6 +48,7 @@ export interface ViewProps {    onAccept: (b: boolean) => void;    reviewing: boolean;    accepted: boolean; +  confirmed: boolean;    terms: {      value?: TermsDocument;      status: TermsStatus; @@ -75,7 +76,7 @@ function amountToString(text: AmountLike) {    return `${amount} ${aj.currency}`  } -export function View({ details, amount, onWithdraw, terms, reviewing, onReview, onAccept, accepted }: ViewProps) { +export function View({ details, amount, onWithdraw, terms, reviewing, onReview, onAccept, accepted, confirmed }: ViewProps) {    const needsReview = terms.status === 'changed' || terms.status === 'new'    return ( @@ -172,7 +173,7 @@ export function View({ details, amount, onWithdraw, terms, reviewing, onReview,            <div>              <ButtonSuccess                upperCased -              disabled={!details.exchangeInfo.baseUrl} +              disabled={!details.exchangeInfo.baseUrl || confirmed}                onClick={onWithdraw}              >                {i18n.str`Confirm withdrawal`} @@ -203,6 +204,7 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element    const [updateCounter, setUpdateCounter] = useState(1);    const [reviewing, setReviewing] = useState<boolean>(false)    const [accepted, setAccepted] = useState<boolean>(false) +  const [confirmed, setConfirmed] = useState<boolean>(false)    useEffect(() => {      return onUpdateNotification(() => { @@ -231,7 +233,8 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element        if (!uriInfo || !uriInfo.defaultExchangeBaseUrl) return        const res = await getExchangeWithdrawalInfo({          exchangeBaseUrl: uriInfo.defaultExchangeBaseUrl, -        amount: Amounts.parseOrThrow(uriInfo.amount) +        amount: Amounts.parseOrThrow(uriInfo.amount), +        tosAcceptedFormat: ['text/json', 'text/xml', 'text/pdf']        })        setDetails(res)      } @@ -242,10 +245,19 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element      return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>;    } +  const onAccept = async (): Promise<void> => { +    if (!details) { +      throw Error("can't accept, no exchange selected"); +    } +    await setExchangeTosAccepted(details.exchangeDetails.exchangeBaseUrl, details.tosRequested?.tosEtag) +    setAccepted(true) +  } +    const onWithdraw = async (): Promise<void> => {      if (!details) {        throw Error("can't accept, no exchange selected");      } +    setConfirmed(true)      console.log("accepting exchange", details.exchangeInfo.baseUrl);      const res = await acceptWithdrawal(talerWithdrawUri, details.exchangeInfo.baseUrl);      console.log("accept withdrawal response", res); @@ -267,11 +279,33 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element      return <span><i18n.Translate>Getting withdrawal details.</i18n.Translate></span>;    } +  let termsContent: TermsDocument | undefined = undefined; +  if (details.tosRequested) { +    if (details.tosRequested.tosContentType === 'text/xml') { +      try { +        const document = new DOMParser().parseFromString(details.tosRequested.tosText, "text/xml") +        termsContent = { type: 'xml', document } +      } catch (e) { +        console.log(e) +        debugger; +       } +    } +  } + +  const status: TermsStatus = !termsContent ? 'notfound' : ( +    !details.exchangeDetails.termsOfServiceAcceptedEtag ? 'new' : ( +      details.tosRequested?.tosEtag !== details.exchangeDetails.termsOfServiceAcceptedEtag ? 'changed' : 'accepted' +    )) + +    return <View onWithdraw={onWithdraw}      // setCancelled={setCancelled} setSelecting={setSelecting}      details={details} amount={uriInfo.amount} -    terms={{} as any} -    accepted={accepted} onAccept={setAccepted} +    terms={{ +      status, value: termsContent +    }} +    confirmed={confirmed} +    accepted={accepted} onAccept={onAccept}      reviewing={reviewing} onReview={setReviewing}    // terms={[]}    /> diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index acb28ffec..63774b00b 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -39,6 +39,7 @@ import {    RetryTransactionRequest,    SetWalletDeviceIdRequest,    GetExchangeWithdrawalInfo, +  AcceptExchangeTosRequest,  } from "@gnu-taler/taler-util";  import { AddBackupProviderRequest, BackupProviderState, OperationFailedError, RemoveBackupProviderRequest } from "@gnu-taler/taler-wallet-core";  import { BackupInfo } from "@gnu-taler/taler-wallet-core"; @@ -251,6 +252,16 @@ export function acceptWithdrawal(    });  } +export function setExchangeTosAccepted( +  exchangeBaseUrl: string, +  etag: string | undefined +): Promise<void> { +  return callBackend("setExchangeTosAccepted", { +    exchangeBaseUrl, etag +  } as AcceptExchangeTosRequest) +} + +  /**   * Get diagnostics information   */ @@ -287,7 +298,7 @@ export function getWithdrawalDetailsForUri(  /**   * Get diagnostics information   */ - export function getExchangeWithdrawalInfo( +export function getExchangeWithdrawalInfo(    req: GetExchangeWithdrawalInfo,  ): Promise<ExchangeWithdrawDetails> {    return callBackend("getExchangeWithdrawalInfo", req); | 
