use /taler-uri as redirection point to all taler uris

This commit is contained in:
Sebastian 2023-04-13 12:21:39 -03:00
parent ebd0041956
commit 7b2de89444
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
4 changed files with 122 additions and 128 deletions

View File

@ -38,6 +38,7 @@ import { useAsyncAsHook } from "./hooks/useAsyncAsHook.js";
import qrIcon from "./svg/qr_code_24px.svg";
import settingsIcon from "./svg/settings_black_24dp.svg";
import warningIcon from "./svg/warning_24px.svg";
import { parseTalerUri, TalerUriAction } from "@gnu-taler/taler-util";
/**
* List of pages used by the wallet
@ -115,6 +116,7 @@ export const Pages = {
"/settings/exchange/add/:currency?",
),
defaultCta: pageDefinition<{ uri: string }>("/taler-uri/:uri"),
cta: pageDefinition<{ action: string }>("/cta/:action"),
ctaPay: "/cta/pay",
ctaPayTemplate: "/cta/pay/template",
@ -136,6 +138,34 @@ export const Pages = {
),
};
const talerUriActionToPageName: {
[t in TalerUriAction]: keyof typeof Pages | undefined;
} = {
[TalerUriAction.Withdraw]: "ctaWithdraw",
[TalerUriAction.Pay]: "ctaPay",
[TalerUriAction.Tip]: "ctaTips",
[TalerUriAction.Refund]: "ctaRefund",
[TalerUriAction.PayPull]: "ctaInvoicePay",
[TalerUriAction.PayPush]: "ctaTransferPickup",
[TalerUriAction.Restore]: "ctaRecovery",
[TalerUriAction.PayTemplate]: "ctaPayTemplate",
[TalerUriAction.DevExperiment]: undefined,
[TalerUriAction.Exchange]: undefined,
[TalerUriAction.Auditor]: undefined,
};
export function getPathnameForTalerURI(talerUri: string): string | undefined {
const uri = parseTalerUri(talerUri);
if (!uri) {
return undefined;
}
const pageName = talerUriActionToPageName[uri.type];
if (!pageName) {
return undefined;
}
return `${Pages[pageName]}?talerUri=${encodeURIComponent(talerUri)}`;
}
export type PopupNavBarOptions = "balance" | "backup" | "dev";
export function PopupNavBar({ path }: { path?: PopupNavBarOptions }): VNode {
const api = useBackendContext();

View File

@ -15,11 +15,11 @@
*/
import {
classifyTalerUri,
Logger,
TalerErrorCode,
TalerUriType,
TalerUriAction,
TalerError,
parseTalerUri,
} from "@gnu-taler/taler-util";
import { WalletOperations } from "@gnu-taler/taler-wallet-core";
import { BackgroundOperations } from "../wxApi.js";
@ -239,80 +239,83 @@ function openWalletURIFromPopup(maybeTalerUri: string): void {
const talerUri = maybeTalerUri.startsWith("ext+")
? maybeTalerUri.substring(4)
: maybeTalerUri;
const uriType = classifyTalerUri(talerUri);
const uri = parseTalerUri(talerUri);
if (!uri) {
logger.warn(
`Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
);
return;
}
//FIXME: this should redirect to just one place
// the target pathname should handle what happens if the endpoint is not there
// like "trying to open from popup but this uri is not handled"
encodeURIComponent;
let url: string | undefined = undefined;
switch (uriType) {
case TalerUriType.TalerWithdraw:
switch (uri.type) {
case TalerUriAction.Withdraw:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/withdraw?talerWithdrawUri=${encodeURIComponent(
`static/wallet.html#/cta/withdraw?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerRecovery:
case TalerUriAction.Restore:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/recovery?talerRecoveryUri=${encodeURIComponent(
`static/wallet.html#/cta/recovery?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerPay:
case TalerUriAction.Pay:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/pay?talerPayUri=${encodeURIComponent(
`static/wallet.html#/cta/pay?talerUri=${encodeURIComponent(talerUri)}`,
);
break;
case TalerUriAction.Tip:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/tip?talerUri=${encodeURIComponent(talerUri)}`,
);
break;
case TalerUriAction.Refund:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/refund?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerTip:
case TalerUriAction.PayPull:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/tip?talerTipUri=${encodeURIComponent(
`static/wallet.html#/cta/invoice/pay?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerRefund:
case TalerUriAction.PayPush:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/refund?talerRefundUri=${encodeURIComponent(
`static/wallet.html#/cta/transfer/pickup?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerPayPull:
case TalerUriAction.PayTemplate:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/invoice/pay?talerPayPullUri=${encodeURIComponent(
`static/wallet.html#/cta/pay/template?talerUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerPayPush:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.TalerPayTemplate:
url = chrome.runtime.getURL(
`static/wallet.html#/cta/pay/template?talerPayTemplateUri=${encodeURIComponent(
talerUri,
)}`,
);
break;
case TalerUriType.Unknown:
logger.warn(
`Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
);
return;
case TalerUriType.TalerDevExperiment:
case TalerUriAction.DevExperiment:
logger.warn(`taler://dev-experiment URIs are not allowed in headers`);
return;
case TalerUriType.TalerTemplate:
logger.warn(`taler://dev-template URIs are not allowed in headers`);
case TalerUriAction.Exchange:
logger.warn(`taler://exchange not yet supported`);
return;
case TalerUriAction.Auditor:
logger.warn(`taler://auditor not yet supported`);
return;
default: {
const error: never = uriType;
const error: never = uri;
logger.warn(
`Response with HTTP 402 the Taler header "${error}", but header value is not a taler:// URI.`,
);

View File

@ -20,7 +20,11 @@
* @author sebasjm
*/
import { TranslatedString } from "@gnu-taler/taler-util";
import {
TalerUriAction,
TranslatedString,
parseTalerUri,
} from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { ComponentChildren, Fragment, h, VNode } from "preact";
import { route, Route, Router } from "preact-router";
@ -55,7 +59,12 @@ import {
WithdrawPageFromParams,
WithdrawPageFromURI,
} from "../cta/Withdraw/index.js";
import { Pages, WalletNavBar, WalletNavBarOptions } from "../NavigationBar.js";
import {
Pages,
WalletNavBar,
WalletNavBarOptions,
getPathnameForTalerURI,
} from "../NavigationBar.js";
import { platform } from "../platform/foreground.js";
import CloseIcon from "../svg/close_24px.svg";
import { AddBackupProviderPage } from "./AddBackupProvider/index.js";
@ -285,12 +294,22 @@ export function Application(): VNode {
{/**
* CALL TO ACTION
*/}
<Route
path={Pages.defaultCta.pattern}
component={({ uri }: { uri: string }) => {
const path = getPathnameForTalerURI(uri);
if (!path) {
return <Redirect to={Pages.balance} />;
}
return <Redirect to={path} />;
}}
/>
<Route
path={Pages.ctaPay}
component={({ talerPayUri }: { talerPayUri: string }) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash payment`}>
<PaymentPage
talerPayUri={decodeURIComponent(talerPayUri)}
talerPayUri={decodeURIComponent(talerUri)}
goToWalletManualWithdraw={(amount?: string) =>
redirectTo(Pages.receiveCash({ amount }))
}
@ -304,14 +323,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaPayTemplate}
component={({
talerPayTemplateUri,
}: {
talerPayTemplateUri: string;
}) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash payment`}>
<PaymentTemplatePage
talerTemplateUri={decodeURIComponent(talerPayTemplateUri)}
talerTemplateUri={decodeURIComponent(talerUri)}
goToWalletManualWithdraw={(amount?: string) =>
redirectTo(Pages.receiveCash({ amount }))
}
@ -325,10 +340,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaRefund}
component={({ talerRefundUri }: { talerRefundUri: string }) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash refund`}>
<RefundPage
talerRefundUri={decodeURIComponent(talerRefundUri)}
talerRefundUri={decodeURIComponent(talerUri)}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))
@ -339,10 +354,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaTips}
component={({ talerTipUri }: { talerTipUri: string }) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash tip`}>
<TipPage
talerTipUri={decodeURIComponent(talerTipUri)}
talerTipUri={decodeURIComponent(talerUri)}
onCancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))
@ -353,14 +368,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaWithdraw}
component={({
talerWithdrawUri,
}: {
talerWithdrawUri: string;
}) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
<WithdrawPageFromURI
talerWithdrawUri={decodeURIComponent(talerWithdrawUri)}
talerWithdrawUri={decodeURIComponent(talerUri)}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))
@ -387,15 +398,15 @@ export function Application(): VNode {
path={Pages.ctaDeposit}
component={({
amount,
talerDepositUri,
talerUri,
}: {
amount: string;
talerDepositUri: string;
talerUri: string;
}) => (
<CallToActionTemplate title={i18n.str`Digital cash deposit`}>
<DepositPageCTA
amountStr={amount}
talerDepositUri={decodeURIComponent(talerDepositUri)}
talerDepositUri={decodeURIComponent(talerUri)}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))
@ -434,10 +445,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaInvoicePay}
component={({ talerPayPullUri }: { talerPayPullUri: string }) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash invoice`}>
<InvoicePayPage
talerPayPullUri={decodeURIComponent(talerPayPullUri)}
talerPayPullUri={decodeURIComponent(talerUri)}
goToWalletManualWithdraw={(amount?: string) =>
redirectTo(Pages.receiveCash({ amount }))
}
@ -451,10 +462,10 @@ export function Application(): VNode {
/>
<Route
path={Pages.ctaTransferPickup}
component={({ talerPayPushUri }: { talerPayPushUri: string }) => (
component={({ talerUri }: { talerUri: string }) => (
<CallToActionTemplate title={i18n.str`Digital cash transfer`}>
<TransferPickupPage
talerPayPushUri={decodeURIComponent(talerPayPushUri)}
talerPayPushUri={decodeURIComponent(talerUri)}
onClose={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))

View File

@ -34,6 +34,8 @@ import {
WalletDiagnostics,
makeErrorDetail,
getErrorDetailFromException,
parseTalerUri,
TalerUriAction,
} from "@gnu-taler/taler-util";
import {
DbAccess,
@ -332,69 +334,17 @@ function parseTalerUriAndRedirect(tabId: number, maybeTalerUri: string): void {
const talerUri = maybeTalerUri.startsWith("ext+")
? maybeTalerUri.substring(4)
: maybeTalerUri;
const uriType = classifyTalerUri(talerUri);
switch (uriType) {
case TalerUriType.TalerWithdraw:
return platform.redirectTabToWalletPage(
tabId,
`/cta/withdraw?talerWithdrawUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerPay:
return platform.redirectTabToWalletPage(
tabId,
`/cta/pay?talerPayUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerTip:
return platform.redirectTabToWalletPage(
tabId,
`/cta/tip?talerTipUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerRefund:
return platform.redirectTabToWalletPage(
tabId,
`/cta/refund?talerRefundUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerPayPull:
return platform.redirectTabToWalletPage(
tabId,
`/cta/invoice/pay?talerPayPullUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerPayPush:
return platform.redirectTabToWalletPage(
tabId,
`/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerRecovery:
return platform.redirectTabToWalletPage(
tabId,
`/cta/transfer/recovery?talerBackupUri=${encodeURIComponent(talerUri)}`,
);
case TalerUriType.TalerPayTemplate:
return platform.redirectTabToWalletPage(
tabId,
`/cta/pay/template?talerPayTemplateUri=${encodeURIComponent(talerUri)}`,
);
return;
case TalerUriType.Unknown:
logger.warn(
`Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
);
return;
case TalerUriType.TalerDevExperiment:
// FIXME: Implement!
logger.warn("not implemented");
return;
case TalerUriType.TalerTemplate:
logger.warn("not implemented");
return;
default: {
const error: never = uriType;
logger.warn(
`Response with HTTP 402 the Taler header "${error}", but header value is not a taler:// URI.`,
);
return;
}
const uri = parseTalerUri(talerUri);
if (!uri) {
logger.warn(
`Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
);
return;
}
return platform.redirectTabToWalletPage(
tabId,
`/taler-uri/${encodeURIComponent(talerUri)}`,
);
}
/**