summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-01-09 18:51:49 -0300
committerSebastian <sebasjm@gmail.com>2024-01-09 18:51:49 -0300
commitf5771cc7b99dc938fd606dcbee350b66ec8027c9 (patch)
tree95c1aa5b8a5e6067c7689b0caf161c50d1f694ed
parent1826b9121a0308aa0a7ac39a89ad7dc8ea2ae965 (diff)
downloadwallet-core-f5771cc7b99dc938fd606dcbee350b66ec8027c9.tar.gz
wallet-core-f5771cc7b99dc938fd606dcbee350b66ec8027c9.tar.bz2
wallet-core-f5771cc7b99dc938fd606dcbee350b66ec8027c9.zip
prepare for 2fa impl
-rw-r--r--packages/demobank-ui/src/components/Cashouts/views.tsx6
-rw-r--r--packages/demobank-ui/src/context/config.ts21
-rw-r--r--packages/demobank-ui/src/pages/AccountPage/state.ts6
-rw-r--r--packages/demobank-ui/src/pages/OperationState/state.ts6
-rw-r--r--packages/demobank-ui/src/pages/OperationState/views.tsx30
-rw-r--r--packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx14
-rw-r--r--packages/demobank-ui/src/pages/QrCodeSection.tsx7
-rw-r--r--packages/demobank-ui/src/pages/RegistrationPage.tsx16
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx7
-rw-r--r--packages/demobank-ui/src/pages/WireTransfer.tsx6
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx22
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalQRCode.tsx5
-rw-r--r--packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx21
-rw-r--r--packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx9
-rw-r--r--packages/demobank-ui/src/pages/admin/AccountForm.tsx6
-rw-r--r--packages/demobank-ui/src/pages/admin/AccountList.tsx4
-rw-r--r--packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx18
-rw-r--r--packages/demobank-ui/src/pages/admin/RemoveAccount.tsx14
-rw-r--r--packages/demobank-ui/src/pages/business/CreateCashout.tsx44
-rw-r--r--packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx29
-rw-r--r--packages/taler-util/src/http-client/bank-core.ts182
-rw-r--r--packages/taler-util/src/operation.ts10
22 files changed, 276 insertions, 207 deletions
diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx
index 341c43b48..1f1f02e4e 100644
--- a/packages/demobank-ui/src/components/Cashouts/views.tsx
+++ b/packages/demobank-ui/src/components/Cashouts/views.tsx
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, TalerError, assertUnreachable } from "@gnu-taler/taler-util";
+import { Amounts, HttpStatusCode, TalerError, assertUnreachable } from "@gnu-taler/taler-util";
import { Attention, Loading, useTranslationContext } from "@gnu-taler/web-util/browser";
import { format } from "date-fns";
import { Fragment, VNode, h } from "preact";
@@ -26,13 +26,13 @@ import { State } from "./index.js";
export function FailedView({ error }: State.Failed) {
const { i18n } = useTranslationContext();
switch (error.case) {
- case "cashout-not-supported": return <Attention type="danger"
+ case HttpStatusCode.NotImplemented: return <Attention type="danger"
title={i18n.str`Cashout not supported.`}>
<div class="mt-2 text-sm text-red-700">
{error.detail.hint}
</div>
</Attention>
- case "account-not-found": return <Attention type="danger"
+ case HttpStatusCode.NotFound: return <Attention type="danger"
title={i18n.str`Account not found.`}>
<div class="mt-2 text-sm text-red-700">
{error.detail.hint}
diff --git a/packages/demobank-ui/src/context/config.ts b/packages/demobank-ui/src/context/config.ts
index 9908c73a2..2d70cf932 100644
--- a/packages/demobank-ui/src/context/config.ts
+++ b/packages/demobank-ui/src/context/config.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { TalerCorebankApi, TalerCoreBankHttpClient, TalerError } from "@gnu-taler/taler-util";
+import { LibtoolVersion, TalerCorebankApi, TalerCoreBankHttpClient, TalerError } from "@gnu-taler/taler-util";
import { BrowserHttpLib, ErrorLoading, useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, createContext, FunctionComponent, h, VNode } from "preact";
import { useContext, useEffect, useState } from "preact/hooks";
@@ -34,8 +34,15 @@ const Context = createContext<Type>(undefined as any);
export const useBankCoreApiContext = (): Type => useContext(Context);
+enum VersionHint {
+ /**
+ * when this flag is on, server is running an old version with cashout before implementing 2fa API
+ */
+ CASHOUT_BEFORE_2FA,
+}
+
export type ConfigResult = undefined
- | { type: "ok", config: TalerCorebankApi.Config }
+ | { type: "ok", config: TalerCorebankApi.Config, hint: VersionHint[] }
| { type: "incompatible", result: TalerCorebankApi.Config, supported: string }
| { type: "error", error: TalerError }
@@ -56,9 +63,15 @@ export const BankCoreApiProvider = ({
api.getConfig()
.then((resp) => {
if (api.isCompatible(resp.body.version)) {
- setChecked({ type: "ok", config: resp.body });
+ setChecked({ type: "ok", config: resp.body, hint: [] });
} else {
- setChecked({ type: "incompatible", result: resp.body, supported: api.PROTOCOL_VERSION })
+ //this API supports version 3.0.3
+ const compare = LibtoolVersion.compare("3:0:3", resp.body.version)
+ if (compare?.compatible ?? false) {
+ setChecked({ type: "ok", config: resp.body, hint: [VersionHint.CASHOUT_BEFORE_2FA] });
+ } else {
+ setChecked({ type: "incompatible", result: resp.body, supported: api.PROTOCOL_VERSION })
+ }
}
})
.catch((error: unknown) => {
diff --git a/packages/demobank-ui/src/pages/AccountPage/state.ts b/packages/demobank-ui/src/pages/AccountPage/state.ts
index d28aba7bf..88e8cf747 100644
--- a/packages/demobank-ui/src/pages/AccountPage/state.ts
+++ b/packages/demobank-ui/src/pages/AccountPage/state.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, TalerError, parsePaytoUri } from "@gnu-taler/taler-util";
+import { Amounts, HttpStatusCode, TalerError, parsePaytoUri } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { useAccountDetails } from "../../hooks/access.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
@@ -40,11 +40,11 @@ export function useComponentState({ account, goToConfirmOperation }: Props): Sta
if (result.type === "fail") {
switch (result.case) {
- case "unauthorized": return {
+ case HttpStatusCode.Unauthorized: return {
status: "login",
reason: "forbidden"
}
- case "not-found": return {
+ case HttpStatusCode.NotFound: return {
status: "login",
reason: "not-found",
}
diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts b/packages/demobank-ui/src/pages/OperationState/state.ts
index defca6f13..477146d1e 100644
--- a/packages/demobank-ui/src/pages/OperationState/state.ts
+++ b/packages/demobank-ui/src/pages/OperationState/state.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, FailCasesByMethod, TalerCoreBankErrorsByMethod, TalerError, TalerErrorDetail, TranslatedString, parsePaytoUri, parseWithdrawUri, stringifyWithdrawUri } from "@gnu-taler/taler-util";
+import { Amounts, FailCasesByMethod, HttpStatusCode, TalerCoreBankErrorsByMethod, TalerError, TalerErrorDetail, TranslatedString, parsePaytoUri, parseWithdrawUri, stringifyWithdrawUri } from "@gnu-taler/taler-util";
import { notify, notifyError, notifyInfo, useTranslationContext, utils } from "@gnu-taler/web-util/browser";
import { useEffect, useState } from "preact/hooks";
import { mutate } from "swr";
@@ -134,8 +134,8 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
if (result.type === "fail") {
switch (result.case) {
- case "invalid-id":
- case "not-found": {
+ case HttpStatusCode.BadRequest:
+ case HttpStatusCode.NotFound: {
return {
status: "aborted",
error: undefined,
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx b/packages/demobank-ui/src/pages/OperationState/views.tsx
index b1f09ba2a..a02bb3bbd 100644
--- a/packages/demobank-ui/src/pages/OperationState/views.tsx
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { TranslatedString, stringifyWithdrawUri } from "@gnu-taler/taler-util";
+import { HttpStatusCode, TalerErrorCode, TranslatedString, stringifyWithdrawUri } from "@gnu-taler/taler-util";
import { Attention, LocalNotificationBanner, ShowInputErrorLabel, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useMemo, useState } from "preact/hooks";
@@ -70,19 +70,19 @@ export function NeedConfirmationView({ error, onAbort: doAbort, onConfirm: doCon
const resp = await doAbort()
if (!resp) return;
switch (resp.case) {
- case "previously-confirmed": return notify({
+ case HttpStatusCode.Conflict: return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
@@ -104,31 +104,31 @@ export function NeedConfirmationView({ error, onAbort: doAbort, onConfirm: doCon
return
}
switch (hasError.case) {
- case "previously-aborted": return notify({
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return notify({
type: "error",
title: i18n.str`The withdrawal has been aborted previously and can't be confirmed`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
})
- case "no-exchange-or-reserve-selected": return notify({
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return notify({
type: "error",
title: i18n.str`The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
})
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
});
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
});
- case "insufficient-funds": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`Your balance is not enough.`,
description: hasError.detail.hint as TranslatedString,
@@ -215,19 +215,19 @@ export function NeedConfirmationView({ error, onAbort: doAbort, onConfirm: doCon
export function FailedView({ error }: State.Failed) {
const { i18n } = useTranslationContext();
switch (error.case) {
- case "unauthorized": return <Attention type="danger"
+ case HttpStatusCode.Unauthorized: return <Attention type="danger"
title={i18n.str`Unauthorized to make the operation, maybe the session has expired or the password changed.`}>
<div class="mt-2 text-sm text-red-700">
{error.detail.hint}
</div>
</Attention>
- case "insufficient-funds": return <Attention type="danger"
+ case HttpStatusCode.Conflict: return <Attention type="danger"
title={i18n.str`The operation was rejected due to insufficient funds.`}>
<div class="mt-2 text-sm text-red-700">
{error.detail.hint}
</div>
</Attention>
- case "account-not-found": return <Attention type="danger"
+ case HttpStatusCode.NotFound: return <Attention type="danger"
title={i18n.str`The operation was rejected due to insufficient funds.`}>
<div class="mt-2 text-sm text-red-700">
{error.detail.hint}
@@ -322,19 +322,19 @@ export function ReadyView({ uri, onClose: doClose }: State.Ready): VNode<{}> {
const hasError = await doClose()
if (!hasError) return;
switch (hasError.case) {
- case "previously-confirmed": return notify({
+ case HttpStatusCode.Conflict: return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
})
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: hasError.detail.hint as TranslatedString,
debug: hasError.detail,
});
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: hasError.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index c785b24df..7a94f5486 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -21,8 +21,10 @@ import {
Amounts,
CurrencySpecification,
FRAC_SEPARATOR,
+ HttpStatusCode,
Logger,
PaytoString,
+ TalerErrorCode,
TranslatedString,
buildPayto,
parsePaytoUri,
@@ -151,37 +153,37 @@ export function PaytoWireTransferForm({
mutate(() => true)
if (res.type === "fail") {
switch (res.case) {
- case "invalid-input": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The request was invalid or the payto://-URI used unacceptable features.`,
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`Not enough permission to complete the operation.`,
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
- case "creditor-not-found": return notify({
+ case TalerErrorCode.BANK_UNKNOWN_CREDITOR: return notify({
type: "error",
title: i18n.str`The destination account "${puri}" was not found.`,
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
- case "creditor-same": return notify({
+ case TalerErrorCode.BANK_SAME_ACCOUNT: return notify({
type: "error",
title: i18n.str`The origin and the destination of the transfer can't be the same.`,
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
- case "insufficient-funds": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`Your balance is not enough.`,
description: res.detail.hint as TranslatedString,
debug: res.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The origin account "${puri}" was not found.`,
description: res.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index 60beb012e..64ebf7e83 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -15,6 +15,7 @@
*/
import {
+ HttpStatusCode,
stringifyWithdrawUri,
TranslatedString,
WithdrawUriResult
@@ -68,17 +69,17 @@ export function QrCodeSection({
onAborted();
} else {
switch (resp.case) {
- case "previously-confirmed": return notify({
+ case HttpStatusCode.Conflict: return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`
})
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index d20c402ac..89bfbcb35 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AccessToken, Logger, TranslatedString } from "@gnu-taler/taler-util";
+import { AccessToken, HttpStatusCode, Logger, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
import {
LocalNotificationBanner,
ShowInputErrorLabel,
@@ -101,43 +101,43 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
const creationResponse = await api.createAccount("" as AccessToken, { name, username, password });
if (creationResponse.type === "fail") {
switch (creationResponse.case) {
- case "invalid-phone-or-email": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`Server replied with invalid phone or email.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "insufficient-funds": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`Registration is disabled because the bank ran out of bonus credit.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`No enough permission to create that account.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "payto-already-exists": return notify({
+ case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return notify({
type: "error",
title: i18n.str`That account id is already taken.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "username-already-exists": return notify({
+ case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return notify({
type: "error",
title: i18n.str`That username is already taken.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "username-reserved": return notify({
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({
type: "error",
title: i18n.str`That username can't be used because is reserved.`,
description: creationResponse.detail.hint as TranslatedString,
debug: creationResponse.detail,
})
- case "user-cant-set-debt": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return notify({
type: "error",
title: i18n.str`Only admin is allow to set debt limit.`,
description: creationResponse.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index 5eef95f1e..bee36e7ad 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -17,6 +17,7 @@
import {
AmountJson,
Amounts,
+ HttpStatusCode,
Logger,
TranslatedString,
parseWithdrawUri
@@ -103,7 +104,7 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {
}
} else {
switch (resp.case) {
- case "insufficient-funds": {
+ case HttpStatusCode.Conflict: {
notify({
type: "error",
title: i18n.str`The operation was rejected due to insufficient funds`,
@@ -112,7 +113,7 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {
})
break;
}
- case "unauthorized": {
+ case HttpStatusCode.Unauthorized: {
notify({
type: "error",
title: i18n.str`The operation was rejected due to insufficient funds`,
@@ -121,7 +122,7 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {
})
break;
}
- case "account-not-found": {
+ case HttpStatusCode.NotFound: {
notify({
type: "error",
title: i18n.str`Account not found`,
diff --git a/packages/demobank-ui/src/pages/WireTransfer.tsx b/packages/demobank-ui/src/pages/WireTransfer.tsx
index 7648df482..d6133b504 100644
--- a/packages/demobank-ui/src/pages/WireTransfer.tsx
+++ b/packages/demobank-ui/src/pages/WireTransfer.tsx
@@ -1,4 +1,4 @@
-import { Amounts, TalerError } from "@gnu-taler/taler-util";
+import { Amounts, HttpStatusCode, TalerError } from "@gnu-taler/taler-util";
import { Loading, notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
@@ -22,8 +22,8 @@ export function WireTransfer({ toAccount, onRegister, onCancel, onSuccess }: { o
}
if (result.type === "fail") {
switch (result.case) {
- case "unauthorized": return <LoginForm currentUser={account} />
- case "not-found": return <LoginForm currentUser={account} />
+ case HttpStatusCode.Unauthorized: return <LoginForm currentUser={account} />
+ case HttpStatusCode.NotFound: return <LoginForm currentUser={account} />
default: assertUnreachable(result)
}
}
diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
index 43b88ccd8..ed1db854a 100644
--- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
@@ -16,11 +16,13 @@
import {
AmountJson,
+ HttpStatusCode,
Logger,
PaytoUri,
PaytoUriIBAN,
PaytoUriTalerBank,
TalerError,
+ TalerErrorCode,
TranslatedString,
WithdrawUriResult
} from "@gnu-taler/taler-util";
@@ -81,8 +83,8 @@ export function WithdrawalConfirmationQuestion({
}
if (withdrawalInfo.type === "fail") {
switch (withdrawalInfo.case) {
- case "not-found": return <OperationNotFound onClose={onAborted} />
- case "invalid-id": return <OperationNotFound onClose={onAborted} />
+ case HttpStatusCode.NotFound: return <OperationNotFound onClose={onAborted} />
+ case HttpStatusCode.BadRequest: return <OperationNotFound onClose={onAborted} />
default: assertUnreachable(withdrawalInfo)
}
}
@@ -121,31 +123,31 @@ export function WithdrawalConfirmationQuestion({
}
} else {
switch (resp.case) {
- case "previously-aborted": return notify({
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return notify({
type: "error",
title: i18n.str`The withdrawal has been aborted previously and can't be confirmed`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "no-exchange-or-reserve-selected": return notify({
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return notify({
type: "error",
title: i18n.str`The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "insufficient-funds": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`Your balance is not enough for the operation.`,
description: resp.detail.hint as TranslatedString,
@@ -167,17 +169,17 @@ export function WithdrawalConfirmationQuestion({
onAborted();
} else {
switch (resp.case) {
- case "previously-confirmed": return notify({
+ case HttpStatusCode.Conflict: return notify({
type: "error",
title: i18n.str`The reserve operation has been confirmed previously and can't be aborted`
});
- case "invalid-id": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
title: i18n.str`The operation id is invalid.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The operation was not found.`,
description: resp.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index c5a558ab8..f05f183d4 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -16,6 +16,7 @@
import {
Amounts,
+ HttpStatusCode,
Logger,
TalerError,
WithdrawUriResult,
@@ -55,8 +56,8 @@ export function WithdrawalQRCode({
}
if (result.type === "fail") {
switch (result.case) {
- case "invalid-id":
- case "not-found": return <OperationNotFound onClose={onClose} />
+ case HttpStatusCode.BadRequest:
+ case HttpStatusCode.NotFound: return <OperationNotFound onClose={onClose} />
default: assertUnreachable(result)
}
}
diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
index 4b66c0d8d..98fb72283 100644
--- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
@@ -1,4 +1,4 @@
-import { TalerCorebankApi, TalerError, TranslatedString } from "@gnu-taler/taler-util";
+import { HttpStatusCode, TalerCorebankApi, TalerError, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
import { Loading, LocalNotificationBanner, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
@@ -40,8 +40,8 @@ export function ShowAccountDetails({
}
if (result.type === "fail") {
switch (result.case) {
- case "not-found": return <LoginForm currentUser={account} />
- case "unauthorized": return <LoginForm currentUser={account} />
+ case HttpStatusCode.Unauthorized:
+ case HttpStatusCode.NotFound: return <LoginForm currentUser={account} />
default: assertUnreachable(result)
}
}
@@ -52,6 +52,7 @@ export function ShowAccountDetails({
const resp = await api.updateAccount({
token: creds.token,
username: account,
+
}, submitAccount);
if (resp.type === "ok") {
@@ -59,39 +60,39 @@ export function ShowAccountDetails({
onUpdateSuccess();
} else {
switch (resp.case) {
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`The rights to change the account are not sufficient`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The username was not found`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "user-cant-change-name": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return notify({
type: "error",
title: i18n.str`You can't change the legal name, please contact the your account administrator.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "user-cant-change-debt": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return notify({
type: "error",
title: i18n.str`You can't change the debt limit, please contact the your account administrator.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "user-cant-change-cashout": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return notify({
type: "error",
title: i18n.str`You can't change the cashout address, please contact the your account administrator.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "missing-contact-data": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_CONTACT: return notify({
type: "error",
- title: i18n.str`You need contact data to enable 2FA.`,
+ title: i18n.str`You can't change the contact data, please contact the your account administrator.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
index ece1f63e7..95c425dc7 100644
--- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
@@ -9,6 +9,7 @@ import { doAutoFocus } from "../PaytoWireTransferForm.js";
import { ProfileNavigation } from "../ProfileNavigation.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
import { LocalNotificationBanner } from "@gnu-taler/web-util/browser";
+import { HttpStatusCode, TalerErrorCode } from "@gnu-taler/taler-util";
export function UpdateAccountPassword({
account: accountName,
@@ -57,19 +58,19 @@ export function UpdateAccountPassword({
onUpdateSuccess();
} else {
switch (resp.case) {
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`Not authorized to change the password, maybe the session is invalid.`
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`Account not found`
})
- case "user-require-old-password": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD: return notify({
type: "error",
title: i18n.str`Old password need to be provided in order to change new one. If you don't have it contact your account administrator.`
})
- case "wrong-old-password": return notify({
+ case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD: return notify({
type: "error",
title: i18n.str`Your current password doesn't match, can't change to a new password.`
})
diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
index c64431918..859c04396 100644
--- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
@@ -66,7 +66,7 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({
const defaultValue: AccountFormData = {
- debit_threshold: Amounts.stringifyValue(template?.debit_threshold ??config.default_debit_threshold),
+ debit_threshold: Amounts.stringifyValue(template?.debit_threshold ?? config.default_debit_threshold),
isExchange: template?.is_taler_exchange,
isPublic: template?.is_public,
name: template?.name ?? "",
@@ -418,13 +418,13 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({
<i18n.Translate>Is public</i18n.Translate>
</span>
</span>
- <button type="button" data-enabled={form.isPublic ?? defaultValue.isPublic ? "true" : "false"} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
+ <button type="button" data-enabled={form.isPublic ?? defaultValue.isPublic ? "true" : "false"} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
onClick={() => {
form.isPublic = !form.isPublic
updateForm(structuredClone(form))
}}>
- <span aria-hidden="true" data-enabled={form.isPublic ?? defaultValue.isPublic ? "true" : "false"} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
+ <span aria-hidden="true" data-enabled={form.isPublic ?? defaultValue.isPublic ? "true" : "false"} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
<p class="mt-2 text-sm text-gray-500" >
diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx b/packages/demobank-ui/src/pages/admin/AccountList.tsx
index 42d3d7fca..dd4586697 100644
--- a/packages/demobank-ui/src/pages/admin/AccountList.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx
@@ -1,4 +1,4 @@
-import { Amounts, TalerError } from "@gnu-taler/taler-util";
+import { Amounts, HttpStatusCode, TalerError } from "@gnu-taler/taler-util";
import { Loading, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js";
@@ -29,7 +29,7 @@ export function AccountList({ onRemoveAccount, onShowAccountDetails, onUpdateAcc
}
if (result.data.type === "fail") {
switch (result.data.case) {
- case "unauthorized": return <Fragment />
+ case HttpStatusCode.Unauthorized: return <Fragment />
default: assertUnreachable(result.data.case)
}
}
diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
index 3d196973e..d6b7d5b1e 100644
--- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
@@ -1,4 +1,4 @@
-import { TalerCorebankApi, TranslatedString } from "@gnu-taler/taler-util";
+import { HttpStatusCode, TalerCorebankApi, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
import { Attention, LocalNotificationBanner, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
@@ -48,43 +48,43 @@ export function CreateNewAccount({
onCreateSuccess();
} else {
switch (resp.case) {
- case "invalid-phone-or-email": return notify({
+ case HttpStatusCode.BadRequest: return notify({
type: "error",
- title: i18n.str`Server replied with invalid phone or email`,
+ title: i18n.str`Server replied that phone or email is invalid`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`The rights to perform the operation are not sufficient`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "username-already-exists": return notify({
+ case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return notify({
type: "error",
title: i18n.str`Account username is already taken`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "payto-already-exists": return notify({
+ case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return notify({
type: "error",
title: i18n.str`Account id is already taken`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "insufficient-funds": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`Bank ran out of bonus credit.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "username-reserved": return notify({
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({
type: "error",
title: i18n.str`Account username can't be used because is reserved`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "user-cant-set-debt": return notify({
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return notify({
type: "error",
title: i18n.str`Only admin is allow to set debt limit.`,
description: resp.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index 0d294a3a6..d47f48dd9 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -1,4 +1,4 @@
-import { Amounts, TalerError, TranslatedString } from "@gnu-taler/taler-util";
+import { Amounts, HttpStatusCode, TalerError, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
import { Attention, Loading, LocalNotificationBanner, ShowInputErrorLabel, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
@@ -39,8 +39,8 @@ export function RemoveAccount({
}
if (result.type === "fail") {
switch (result.case) {
- case "unauthorized": return <LoginForm currentUser={account} />
- case "not-found": return <LoginForm currentUser={account} />
+ case HttpStatusCode.Unauthorized: return <LoginForm currentUser={account} />
+ case HttpStatusCode.NotFound: return <LoginForm currentUser={account} />
default: assertUnreachable(result)
}
}
@@ -65,25 +65,25 @@ export function RemoveAccount({
onUpdateSuccess();
} else {
switch (resp.case) {
- case "unauthorized": return notify({
+ case HttpStatusCode.Unauthorized: return notify({
type: "error",
title: i18n.str`No enough permission to delete the account.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`The username was not found.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "username-reserved": return notify({
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({
type: "error",
title: i18n.str`Can't delete a reserved username.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "balance-not-zero": return notify({
+ case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO: return notify({
type: "error",
title: i18n.str`Can't delete an account with balance different than zero.`,
description: resp.detail.hint as TranslatedString,
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 92c80ea38..c3921cbd0 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -15,7 +15,9 @@
*/
import {
Amounts,
+ HttpStatusCode,
TalerError,
+ TalerErrorCode,
TranslatedString,
encodeCrock,
getRandomBytes,
@@ -99,8 +101,8 @@ export function CreateCashout({
}
if (resultAccount.type === "fail") {
switch (resultAccount.case) {
- case "unauthorized": return <LoginForm currentUser={accountName} />
- case "not-found": return <LoginForm currentUser={accountName} />
+ case HttpStatusCode.Unauthorized: return <LoginForm currentUser={accountName} />
+ case HttpStatusCode.NotFound: return <LoginForm currentUser={accountName} />
default: assertUnreachable(resultAccount)
}
}
@@ -181,8 +183,9 @@ export function CreateCashout({
async function createCashout() {
const request_uid = encodeCrock(getRandomBytes(32))
await handleError(async () => {
- if (!creds || !form.subject || !form.channel) return;
+ const validChannel = config.supported_tan_channels.length === 0 || form.channel
+ if (!creds || !form.subject || !validChannel) return;
const resp = await api.createCashout(creds, {
request_uid,
amount_credit: Amounts.stringify(calc.credit),
@@ -194,47 +197,55 @@ export function CreateCashout({
notifyInfo(i18n.str`Cashout created`)
} else {
switch (resp.case) {
- case "account-not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`Account not found`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "request-already-used": return notify({
+ case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return notify({
type: "error",
title: i18n.str`Duplicated request detected, check if the operation succeded or try again.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "incorrect-exchange-rate": return notify({
+ case TalerErrorCode.BANK_BAD_CONVERSION: return notify({
type: "error",
title: i18n.str`The exchange rate was incorrectly applied`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "no-enough-balance": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`The account does not have sufficient funds`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "cashout-not-supported": return notify({
+ case HttpStatusCode.NotImplemented: return notify({
type: "error",
title: i18n.str`Cashouts are not supported`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "no-cashout-uri": return notify({
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return notify({
type: "error",
title: i18n.str`Missing cashout URI in the profile`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
+ case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED: return notify({
+ type: "error",
+ title: i18n.str`Sending the confirmation message failed, retry later or contact the administrator.`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
}
assertUnreachable(resp)
}
})
}
+ const cashoutDisabled = config.supported_tan_channels.length < 1 || !resultAccount.body.cashout_payto_uri
+ console.log("disab", cashoutDisabled)
const cashoutAccount = !resultAccount.body.cashout_payto_uri ? undefined :
parsePaytoUri(resultAccount.body.cashout_payto_uri);
const cashoutAccountName = !cashoutAccount ? undefined : cashoutAccount.targetPath
@@ -317,7 +328,7 @@ export function CreateCashout({
class="block w-full rounded-md disabled:bg-gray-200 border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
name="subject"
id="subject"
- disabled={!resultAccount.body.cashout_payto_uri}
+ disabled={cashoutDisabled}
data-error={!!errors?.subject && form.subject !== undefined}
value={form.subject ?? ""}
onChange={(e) => {
@@ -360,7 +371,7 @@ export function CreateCashout({
left
currency={limit.currency}
value={trimmedAmountStr}
- onChange={!resultAccount.body.cashout_payto_uri ? undefined : (value) => {
+ onChange={cashoutDisabled ? undefined : (value) => {
form.amount = value;
updateForm(structuredClone(form));
}}
@@ -424,7 +435,15 @@ export function CreateCashout({
)}
{/* channel */}
- {config.supported_tan_channels.length === 0 ? undefined :
+ {config.supported_tan_channels.length === 0 ?
+ <div class="sm:col-span-5">
+ <Attention type="warning" title={i18n.str`No cashout channel available`}>
+ <i18n.Translate>
+ Before doing a cashout the server need to provide an second channel to confirm the operation
+ </i18n.Translate>
+ </Attention>
+ </div>
+ :
<div class="sm:col-span-5">
<label
class="block text-sm font-medium leading-6 text-gray-900"
@@ -507,7 +526,6 @@ export function CreateCashout({
</div>
</form>
</div>
-
</div>
);
}
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
index 3ef835574..5d8db5aee 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
@@ -15,7 +15,9 @@
*/
import {
Amounts,
+ HttpStatusCode,
TalerError,
+ TalerErrorCode,
TranslatedString
} from "@gnu-taler/taler-util";
import {
@@ -73,9 +75,9 @@ export function ShowCashoutDetails({
}
if (result.type === "fail") {
switch (result.case) {
- case "not-found": return <Attention type="warning" title={i18n.str`This cashout not found. Maybe already aborted.`}>
+ case HttpStatusCode.NotFound: return <Attention type="warning" title={i18n.str`This cashout not found. Maybe already aborted.`}>
</Attention>
- case "cashout-not-supported": return <Attention type="warning" title={i18n.str`Cashouts are not supported`}>
+ case HttpStatusCode.NotImplemented: return <Attention type="warning" title={i18n.str`Cashouts are not supported`}>
</Attention>
default: assertUnreachable(result)
}
@@ -93,6 +95,7 @@ export function ShowCashoutDetails({
});
const isPending = String(result.body.status).toUpperCase() === "PENDING";
const { fiat_currency_specification, regional_currency_specification } = info.body
+ // won't implement in retry in old API 3:0:3 since request_uid is missing
async function doAbortCashout() {
if (!creds) return;
await handleError(async () => {
@@ -101,19 +104,19 @@ export function ShowCashoutDetails({
onCancel();
} else {
switch (resp.case) {
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`Cashout not found. It may be also mean that it was already aborted.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "already-confirmed": return notify({
+ case HttpStatusCode.Conflict: return notify({
type: "error",
title: i18n.str`Cashout was already confimed.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "cashout-not-supported": return notify({
+ case HttpStatusCode.NotImplemented: return notify({
type: "error",
title: i18n.str`Cashout operation is not supported.`,
description: resp.detail.hint as TranslatedString,
@@ -136,49 +139,49 @@ export function ShowCashoutDetails({
mutate(() => true)//clean cashout state
} else {
switch (resp.case) {
- case "not-found": return notify({
+ case HttpStatusCode.NotFound: return notify({
type: "error",
title: i18n.str`Cashout not found. It may be also mean that it was already aborted.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "no-enough-balance": return notify({
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
type: "error",
title: i18n.str`The account does not have sufficient funds`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "incorrect-exchange-rate": return notify({
+ case TalerErrorCode.BANK_BAD_CONVERSION: return notify({
type: "error",
title: i18n.str`The exchange rate was incorrectly applied`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "already-aborted": return notify({
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return notify({
type: "error",
title: i18n.str`The cashout operation is already aborted.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- case "no-cashout-payto": return notify({
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return notify({
type: "error",
title: i18n.str`Missing destination account.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "too-many-attempts": return notify({
+ case HttpStatusCode.TooManyRequests: return notify({
type: "error",
title: i18n.str`Too many failed attempts.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "cashout-not-supported": return notify({
+ case HttpStatusCode.NotImplemented: return notify({
type: "error",
title: i18n.str`Cashout operation is not supported.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "invalid-code": return notify({
+ case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return notify({
type: "error",
title: i18n.str`The code for this cashout is invalid.`,
description: resp.detail.hint as TranslatedString,
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
index b7e0292bd..dd0948250 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -20,7 +20,9 @@ import {
TalerErrorCode,
codecForChallenge,
codecForTalerErrorDetail,
- codecForTanTransmission
+ codecForTanTransmission,
+ opKnownHttpFailure,
+ opKnownTalerFailure
} from "@gnu-taler/taler-util";
import {
HttpRequestLibrary,
@@ -45,7 +47,7 @@ export type TalerCoreBankErrorsByMethod<prop extends keyof TalerCoreBankHttpClie
* Uses libtool's current:revision:age versioning.
*/
export class TalerCoreBankHttpClient {
- public readonly PROTOCOL_VERSION = "0:0:0";
+ public readonly PROTOCOL_VERSION = "4:0:0";
httpLib: HttpRequestLibrary;
@@ -95,17 +97,17 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForRegisterAccountResponse())
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-phone-or-email", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return opKnownFailure("username-already-exists", resp);
- case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return opKnownFailure("payto-already-exists", resp);
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("insufficient-funds", resp);
- case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return opKnownFailure("username-reserved", resp);
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownFailure("user-cant-set-debt", resp);
+ case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -127,14 +129,14 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return opKnownFailure("username-reserved", resp);
- case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO: return opKnownFailure("balance-not-zero", resp);
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -158,16 +160,16 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return opKnownFailure("user-cant-change-name", resp);
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownFailure("user-cant-change-debt", resp);
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return opKnownFailure("user-cant-change-cashout", resp);
- case TalerErrorCode.BANK_MISSING_TAN_INFO: return opKnownFailure("missing-contact-data", resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_CONTACT: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -191,14 +193,14 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD: return opKnownFailure("user-require-old-password", resp);
- case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD: return opKnownFailure("wrong-old-password", resp);
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -246,7 +248,7 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForListBankAccountsResponse())
case HttpStatusCode.NoContent: return opFixedSuccess({ accounts: [] })
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -265,8 +267,8 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForAccountData())
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -291,8 +293,8 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountTransactionsResponse())
case HttpStatusCode.NoContent: return opFixedSuccess({ transactions: [] })
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -311,8 +313,8 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountTransactionInfo())
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -333,16 +335,16 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.Ok: return opSuccess(resp, codecForCreateTransactionResponse())
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_SAME_ACCOUNT: return opKnownFailure("creditor-same", resp);
- case TalerErrorCode.BANK_UNKNOWN_CREDITOR: return opKnownFailure("creditor-not-found", resp);
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("insufficient-funds", resp);
+ case TalerErrorCode.BANK_SAME_ACCOUNT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNKNOWN_CREDITOR: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -369,9 +371,9 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountCreateWithdrawalResponse())
- case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp);
- case HttpStatusCode.Conflict: return opKnownFailure("insufficient-funds", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -391,9 +393,9 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.NoContent: return opEmptySuccess()
//FIXME: missing in docs
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-id", resp)
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp)
- case HttpStatusCode.Conflict: return opKnownFailure("previously-confirmed", resp);
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp)
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp)
+ case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -414,15 +416,15 @@ export class TalerCoreBankHttpClient {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.NoContent: return opEmptySuccess()
//FIXME: missing in docs
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-id", resp)
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp)
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp)
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp)
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownFailure("previously-aborted", resp);
- case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownFailure("no-exchange-or-reserve-selected", resp);
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("insufficient-funds", resp);
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -449,8 +451,8 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForWithdrawalPublicInfo())
//FIXME: missing in docs
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-id", resp)
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp)
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp)
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp)
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -475,19 +477,27 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutPending())
- case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp)
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp)
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return opKnownFailure("request-already-used", resp);
- case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownFailure("incorrect-exchange-rate", resp);
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("no-enough-balance", resp);
- case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownFailure("no-cashout-uri", resp);
+ case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.BadGateway: {
+ const body = await resp.json()
+ const details = codecForTalerErrorDetail().decode(body)
+ switch (details.code) {
+ case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED: return opKnownTalerFailure(details.code, resp);
+ default: return opUnknownFailure(resp, body)
+ }
+ }
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -506,9 +516,9 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Conflict: return opKnownFailure("already-confirmed", resp);
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -528,21 +538,21 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Conflict: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownFailure("already-aborted", resp);
- case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownFailure("no-cashout-payto", resp);
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("no-enough-balance", resp);
- case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownFailure("incorrect-exchange-rate", resp);
- case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownFailure("invalid-code", resp);
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
- case HttpStatusCode.TooManyRequests: return opKnownFailure("too-many-attempts", resp);
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.TooManyRequests: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -561,8 +571,8 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutStatusResponse())
- case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -583,8 +593,8 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashouts())
case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
- case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp);;
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);;
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -605,7 +615,7 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForGlobalCashouts())
case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
- case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -634,11 +644,11 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForMonitorResponse())
- case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp);
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
//FIXME remove when server is updated
//FIXME: should be 404 ?
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("monitor-not-supported", resp);
+ case HttpStatusCode.ServiceUnavailable: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -656,13 +666,13 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForTanTransmission())
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("invalid-challenge", resp);
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.BadGateway: {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
- case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED: return opKnownFailure("tan-failed", resp);
+ case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED: return opKnownTalerFailure(details.code, resp);
default: return opUnknownFailure(resp, body)
}
}
@@ -679,11 +689,19 @@ export class TalerCoreBankHttpClient {
},
});
switch (resp.status) {
- case HttpStatusCode.Ok: return opEmptySuccess()
- case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("invalid-challenge", resp);
- case HttpStatusCode.Conflict: return opKnownFailure("wrong-code", resp);
- case HttpStatusCode.TooManyRequests: return opKnownFailure("too-many-errors", resp);
+ case HttpStatusCode.NoContent: return opEmptySuccess()
+ case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);
+ case HttpStatusCode.Conflict: {
+ const body = await resp.json()
+ const details = codecForTalerErrorDetail().decode(body)
+ switch (details.code) {
+ case TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED: return opKnownTalerFailure(details.code, resp);
+ case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownTalerFailure(details.code, resp);
+ default: return opUnknownFailure(resp, body)
+ }
+ }
+ case HttpStatusCode.TooManyRequests: return opKnownHttpFailure(resp.status, resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts
index 06bfe26bd..8b264d905 100644
--- a/packages/taler-util/src/operation.ts
+++ b/packages/taler-util/src/operation.ts
@@ -1,5 +1,5 @@
import { HttpResponse, readSuccessResponseJsonOrThrow, readTalerErrorResponse } from "./http-common.js";
-import { Codec, TalerError, TalerErrorCode, TalerErrorDetail } from "./index.js";
+import { Codec, HttpStatusCode, TalerError, TalerErrorCode, TalerErrorDetail } from "./index.js";
export type OperationResult<Body, ErrorEnum> =
| OperationOk<Body>
@@ -31,6 +31,14 @@ export function opFixedSuccess<T>(body: T): OperationOk<T> {
export function opEmptySuccess(): OperationOk<void> {
return { type: "ok" as const, body: void 0 }
}
+export async function opKnownHttpFailure<T extends HttpStatusCode>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
+ const detail = await readTalerErrorResponse(resp)
+ return { type: "fail", case: s, detail }
+}
+export async function opKnownTalerFailure<T extends TalerErrorCode>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
+ const detail = await readTalerErrorResponse(resp)
+ return { type: "fail", case: s, detail }
+}
export async function opKnownFailure<T extends string>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
const detail = await readTalerErrorResponse(resp)
return { type: "fail", case: s, detail }