[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-typescript-core] branch master updated: fix #9754
From: |
Admin |
Subject: |
[taler-typescript-core] branch master updated: fix #9754 |
Date: |
Sat, 14 Jun 2025 00:08:46 +0200 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository taler-typescript-core.
The following commit(s) were added to refs/heads/master by this push:
new 4db0f46e5 fix #9754
4db0f46e5 is described below
commit 4db0f46e53e5676402820907a51a622ccc58ffdd
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Jun 13 19:07:21 2025 -0300
fix #9754
---
packages/bank-ui/src/Routing.tsx | 77 +++-------------------
packages/bank-ui/src/hooks/session.ts | 74 ++++++++++++++++++++-
packages/bank-ui/src/pages/LoginForm.tsx | 7 +-
.../merchant-backoffice-ui/src/AdminRoutes.tsx | 4 ++
packages/merchant-backoffice-ui/src/Routing.tsx | 38 +++++++++--
.../src/paths/admin/list/TableActive.tsx | 23 ++++++-
.../src/paths/admin/list/View.tsx | 3 +
.../src/paths/admin/list/index.tsx | 8 ++-
.../src/paths/instance/token/DetailPage.tsx | 9 ++-
.../src/paths/instance/token/index.tsx | 49 +++++++++++---
.../src/paths/instance/update/index.tsx | 5 --
packages/taler-util/src/http-client/bank-core.ts | 40 ++++++++++-
12 files changed, 235 insertions(+), 102 deletions(-)
diff --git a/packages/bank-ui/src/Routing.tsx b/packages/bank-ui/src/Routing.tsx
index 70d3ace92..80a996bef 100644
--- a/packages/bank-ui/src/Routing.tsx
+++ b/packages/bank-ui/src/Routing.tsx
@@ -16,27 +16,28 @@
import {
LocalNotificationBanner,
- RouteDefinition,
urlPattern,
useBankCoreApiContext,
useCurrentLocation,
useLocalNotification,
useNavigationContext,
- useTranslationContext,
+ useTranslationContext
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import {
AbsoluteTime,
AccessToken,
- Duration,
HttpStatusCode,
+ TalerErrorCode,
+ TokenRequest,
TranslatedString,
assertUnreachable,
- createRFC8959AccessTokenEncoded,
+ createRFC8959AccessTokenEncoded
} from "@gnu-taler/taler-util";
import { useEffect } from "preact/hooks";
-import { useSessionState } from "./hooks/session.js";
+import { useBankState } from "./hooks/bank-state.js";
+import { useRefreshSessionBeforeExpires, useSessionState } from
"./hooks/session.js";
import { AccountPage } from "./pages/AccountPage/index.js";
import { BankFrame } from "./pages/BankFrame.js";
import { LoginForm, SESSION_DURATION } from "./pages/LoginForm.js";
@@ -56,9 +57,6 @@ import { RemoveAccount } from
"./pages/admin/RemoveAccount.js";
import { ConversionConfig } from "./pages/regional/ConversionConfig.js";
import { CreateCashout } from "./pages/regional/CreateCashout.js";
import { ShowCashoutDetails } from "./pages/regional/ShowCashoutDetails.js";
-import { useBankState } from "./hooks/bank-state.js";
-import { TalerErrorCode } from "@gnu-taler/taler-util";
-import { TokenRequest } from "@gnu-taler/taler-util";
const TALER_SCREEN_ID = 100;
@@ -66,64 +64,7 @@ Routing.SCREEN_ID = TALER_SCREEN_ID;
export function Routing(): VNode {
const session = useSessionState();
- const refreshSession =
- session.state.status !== "loggedIn" ||
- session.state.expiration.t_ms === "never"
- ? undefined
- : {
- user: session.state.username,
- time: session.state.expiration,
- auth: session.state.token,
- };
-
- const {
- lib: { bank },
- } = useBankCoreApiContext();
-
- useEffect(() => {
- if (!refreshSession) return;
- /**
- * we need to wait before refreshing the session. Waiting too much and the
token will
- * be expired. So 20% before expiration should be close enough.
- */
- const timeLeftBeforeExpiration =
Duration.getRemaining(refreshSession.time);
- const refreshWindow = Duration.multiply(
- Duration.fromTalerProtocolDuration(SESSION_DURATION),
- 0.2,
- );
- if (
- timeLeftBeforeExpiration.d_ms === "forever" ||
- refreshWindow.d_ms === "forever"
- )
- return;
- const remain = Math.max(
- timeLeftBeforeExpiration.d_ms - refreshWindow.d_ms,
- 0,
- );
- const timeoutId = setTimeout(async () => {
- const result = await bank.createAccessTokenBasic(
- refreshSession.user,
- refreshSession.auth,
- {
- scope: "readwrite",
- duration: SESSION_DURATION,
- refreshable: true,
- },
- );
- if (result.type === "fail") {
- console.log(`could not refresh session ${result.case}`);
- return;
- }
- session.logIn({
- username: refreshSession.user,
- token: createRFC8959AccessTokenEncoded(result.body.access_token),
- expiration: AbsoluteTime.fromProtocolTimestamp(result.body.expiration),
- });
- }, remain);
- return () => {
- clearTimeout(timeoutId);
- };
- }, [refreshSession]);
+ useRefreshSessionBeforeExpires()
if (session.state.status === "loggedIn") {
const { isUserAdministrator, username } = session.state;
@@ -189,9 +130,9 @@ function PublicRounting({
duration: SESSION_DURATION,
refreshable: true,
} as TokenRequest;
- const resp = await lib.bank.createAccessTokenBasic(
+ const resp = await lib.bank.createAccessToken(
username,
- password,
+ { type: "basic", password },
tokenRequest,
);
if (resp.type === "ok") {
diff --git a/packages/bank-ui/src/hooks/session.ts
b/packages/bank-ui/src/hooks/session.ts
index 631c08bea..f7f0a8508 100644
--- a/packages/bank-ui/src/hooks/session.ts
+++ b/packages/bank-ui/src/hooks/session.ts
@@ -14,6 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { Duration } from "@gnu-taler/taler-util";
import {
AbsoluteTime,
AccessToken,
@@ -26,8 +27,11 @@ import {
codecForString,
codecOptionalDefault,
} from "@gnu-taler/taler-util";
-import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
+import { buildStorageKey, useBankCoreApiContext, useLocalStorage } from
"@gnu-taler/web-util/browser";
import { mutate } from "swr";
+import { SESSION_DURATION } from "../pages/LoginForm.js";
+import { createRFC8959AccessTokenEncoded } from "@gnu-taler/taler-util";
+import { useEffect } from "preact/hooks";
/**
* Has the information to reach and
@@ -140,3 +144,71 @@ export function useSessionState(): SessionStateHandler {
function cleanAllCache(): void {
mutate(() => true, undefined, { revalidate: false });
}
+
+/**
+ * Loads the session from local storage
+ * Sets a timeout before the session expires
+ * Makes a request to refresh the session
+ * Saves new session
+ */
+export function useRefreshSessionBeforeExpires() {
+ const session = useSessionState();
+
+ const {
+ lib: { bank },
+ } = useBankCoreApiContext();
+
+ const refreshSession =
+ session.state.status !== "loggedIn" ||
+ session.state.expiration.t_ms === "never"
+ ? undefined
+ : session.state;
+
+ useEffect(() => {
+ if (!refreshSession) return;
+ /**
+ * we need to wait before refreshing the session. Waiting too much and the
token will
+ * be expired. So 20% before expiration should be close enough.
+ */
+ const timeLeftBeforeExpiration =
Duration.getRemaining(refreshSession.expiration);
+ const refreshWindow = Duration.multiply(
+ Duration.fromTalerProtocolDuration(SESSION_DURATION),
+ 0.2,
+ );
+ if (
+ timeLeftBeforeExpiration.d_ms === "forever" ||
+ refreshWindow.d_ms === "forever"
+ )
+ return;
+ const remain = Math.max(
+ timeLeftBeforeExpiration.d_ms - refreshWindow.d_ms,
+ 0,
+ );
+ const timeoutId = setTimeout(async () => {
+ const result = await bank.createAccessToken(
+ refreshSession.username,
+ { type: "bearer", accessToken: refreshSession.token },
+ {
+ scope: "readwrite",
+ duration: SESSION_DURATION,
+ refreshable: true,
+ },
+ );
+ if (result.type === "fail") {
+ console.log(
+ `could not refresh session ${result.case}:
${JSON.stringify(result)}`,
+ );
+ return;
+ }
+ session.logIn({
+ username: refreshSession.username,
+ token: createRFC8959AccessTokenEncoded(result.body.access_token),
+ expiration: AbsoluteTime.fromProtocolTimestamp(result.body.expiration),
+ });
+ }, remain);
+ return () => {
+ clearTimeout(timeoutId);
+ };
+ }, [refreshSession]);
+
+}
diff --git a/packages/bank-ui/src/pages/LoginForm.tsx
b/packages/bank-ui/src/pages/LoginForm.tsx
index 75fda2736..cd809f6a7 100644
--- a/packages/bank-ui/src/pages/LoginForm.tsx
+++ b/packages/bank-ui/src/pages/LoginForm.tsx
@@ -43,6 +43,7 @@ const TALER_SCREEN_ID = 104;
export const SESSION_DURATION = Duration.toTalerProtocolDuration(
Duration.fromSpec({
+ // seconds: 6,
minutes: 30,
}),
);
@@ -110,9 +111,9 @@ export function LoginForm({
? undefined
: withErrorHandler(
async () =>
- authenticator.createAccessTokenBasic(
+ authenticator.createAccessToken(
username,
- password,
+ { type: "basic", password },
tokenRequest,
),
(result) => {
@@ -138,7 +139,7 @@ export function LoginForm({
password,
},
});
- onAuthorizationRequired()
+ onAuthorizationRequired();
return i18n.str`Second factor authentication required.`;
}
case TalerErrorCode.GENERIC_FORBIDDEN:
diff --git a/packages/merchant-backoffice-ui/src/AdminRoutes.tsx
b/packages/merchant-backoffice-ui/src/AdminRoutes.tsx
index b186f1408..783040f07 100644
--- a/packages/merchant-backoffice-ui/src/AdminRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/AdminRoutes.tsx
@@ -30,6 +30,10 @@ export function AdminRoutes(): VNode {
<Route
path={AdminPaths.list_instances}
component={InstanceListPage}
+ onChangePassword={(id) => {
+ console.log("ASDASD")
+ route(`/instance/${id}/token`);
+ }}
onCreate={() => {
route(AdminPaths.new_instance);
}}
diff --git a/packages/merchant-backoffice-ui/src/Routing.tsx
b/packages/merchant-backoffice-ui/src/Routing.tsx
index a9fcbf9e4..85965bfa6 100644
--- a/packages/merchant-backoffice-ui/src/Routing.tsx
+++ b/packages/merchant-backoffice-ui/src/Routing.tsx
@@ -38,13 +38,16 @@ import {
} from "./components/menu/index.js";
import { useSessionContext } from "./context/session.js";
import { useInstanceBankAccounts } from "./hooks/bank.js";
-import { useInstanceKYCDetails, useInstanceKYCDetailsLongPolling } from
"./hooks/instance.js";
+import { useInstanceKYCDetailsLongPolling } from "./hooks/instance.js";
import { usePreference } from "./hooks/preference.js";
import InstanceCreatePage from "./paths/admin/create/index.js";
import InstanceListPage from "./paths/admin/list/index.js";
import BankAccountCreatePage from "./paths/instance/accounts/create/index.js";
import BankAccountListPage from "./paths/instance/accounts/list/index.js";
import BankAccountUpdatePage from "./paths/instance/accounts/update/index.js";
+import CreateCategory from "./paths/instance/categories/create/index.js";
+import ListCategories from "./paths/instance/categories/list/index.js";
+import UpdateCategory from "./paths/instance/categories/update/index.js";
import ListKYCPage from "./paths/instance/kyc/list/index.js";
import OrderCreatePage from "./paths/instance/orders/create/index.js";
import OrderDetailsPage from "./paths/instance/orders/details/index.js";
@@ -60,7 +63,10 @@ import TemplateListPage from
"./paths/instance/templates/list/index.js";
import TemplateQrPage from "./paths/instance/templates/qr/index.js";
import TemplateUpdatePage from "./paths/instance/templates/update/index.js";
import TemplateUsePage from "./paths/instance/templates/use/index.js";
-import TokenPage from "./paths/instance/token/index.js";
+import TokenPage, {
+ AdminToken as InstanceAdminTokenPage,
+ Props as InstanceAdminTokenProps,
+} from "./paths/instance/token/index.js";
import TokenFamilyCreatePage from
"./paths/instance/tokenfamilies/create/index.js";
import TokenFamilyListPage from "./paths/instance/tokenfamilies/list/index.js";
import TokenFamilyUpdatePage from
"./paths/instance/tokenfamilies/update/index.js";
@@ -76,9 +82,6 @@ import WebhookUpdatePage from
"./paths/instance/webhooks/update/index.js";
import { LoginPage } from "./paths/login/index.js";
import { Settings } from "./paths/settings/index.js";
import { Notification } from "./utils/types.js";
-import ListCategories from "./paths/instance/categories/list/index.js";
-import CreateCategory from "./paths/instance/categories/create/index.js";
-import UpdateCategory from "./paths/instance/categories/update/index.js";
export enum InstancePaths {
error = "/error",
@@ -131,6 +134,7 @@ export enum AdminPaths {
list_instances = "/instances",
new_instance = "/instance/new",
update_instance = "/instance/:id/update",
+ update_instance_auth = "/instance/:id/token",
}
export interface Props {}
@@ -267,6 +271,9 @@ export function Routing(_p: Props): VNode {
<Route
path={AdminPaths.list_instances}
component={InstanceListPage}
+ onChangePassword={(id: string): void => {
+ route(`/instance/${id}/token`);
+ }}
onCreate={() => {
route(AdminPaths.new_instance);
}}
@@ -295,6 +302,16 @@ export function Routing(_p: Props): VNode {
}}
/>
)}
+ {state.isAdmin && (
+ <Route
+ path={AdminPaths.update_instance_auth}
+ component={AdminInstanceUpdateTokenPage}
+ onCancel={() => route(AdminPaths.list_instances)}
+ onChange={() => {
+ route(AdminPaths.list_instances);
+ }}
+ />
+ )}
{/**
* Update instance page
*/}
@@ -662,6 +679,17 @@ function AdminInstanceUpdatePage({
);
}
+function AdminInstanceUpdateTokenPage({
+ id,
+ ...rest
+}: { id: string } & InstanceAdminTokenProps): VNode {
+ return (
+ <Fragment>
+ <InstanceAdminTokenPage {...rest} instanceId={id} />
+ </Fragment>
+ );
+}
+
function BankAccountBanner(): VNode {
const { i18n } = useTranslationContext();
diff --git
a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
index 61dbea9de..792606039 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
@@ -28,6 +28,7 @@ import { useSessionContext } from
"../../../context/session.js";
interface Props {
instances: TalerMerchantApi.Instance[];
onUpdate: (id: string) => void;
+ onChangePassword: (id: string) => void;
onDelete: (id: TalerMerchantApi.Instance) => void;
onPurge: (id: TalerMerchantApi.Instance) => void;
onCreate: () => void;
@@ -40,6 +41,7 @@ export function CardTable({
onUpdate,
onPurge,
onDelete,
+ onChangePassword,
selected,
}: Props): VNode {
const [actionQueue, actionQueueHandler] = useState<Actions[]>([]);
@@ -114,6 +116,7 @@ export function CardTable({
onPurge={onPurge}
onUpdate={onUpdate}
onDelete={onDelete}
+ onChangePassword={onChangePassword}
rowSelection={rowSelection}
rowSelectionHandler={rowSelectionHandler}
/>
@@ -130,6 +133,7 @@ interface TableProps {
rowSelection: string[];
instances: TalerMerchantApi.Instance[];
onUpdate: (id: string) => void;
+ onChangePassword: (id: string) => void;
onDelete: (id: TalerMerchantApi.Instance) => void;
onPurge: (id: TalerMerchantApi.Instance) => void;
rowSelectionHandler: StateUpdater<string[]>;
@@ -140,11 +144,17 @@ function toggleSelected<T>(id: T): (prev: T[]) => T[] {
prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
}
+/**
+ * FIXME: put this on UI settings
+ */
+const HIDE_EDIT_INSTANCE = true;
+
function Table({
rowSelection,
rowSelectionHandler,
instances,
onUpdate,
+ onChangePassword,
onDelete,
onPurge,
}: TableProps): VNode {
@@ -212,12 +222,21 @@ function Table({
<td>{i.name}</td>
<td class="is-actions-cell right-sticky">
<div class="buttons is-right">
+ {HIDE_EDIT_INSTANCE ? undefined : (
+ <button
+ class="button is-small is-success jb-modal"
+ type="button"
+ onClick={(): void => onUpdate(i.id)}
+ >
+ <i18n.Translate>Edit</i18n.Translate>
+ </button>
+ )}
<button
class="button is-small is-success jb-modal"
type="button"
- onClick={(): void => onUpdate(i.id)}
+ onClick={(): void => onChangePassword(i.id)}
>
- <i18n.Translate>Edit</i18n.Translate>
+ <i18n.Translate>Change password</i18n.Translate>
</button>
{!i.deleted && (
<button
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
b/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
index 969a037a9..0813a9a2c 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
@@ -29,6 +29,7 @@ interface Props {
instances: TalerMerchantApi.Instance[];
onCreate: () => void;
onUpdate: (id: string) => void;
+ onChangePassword: (id: string) => void;
onDelete: (id: TalerMerchantApi.Instance) => void;
onPurge: (id: TalerMerchantApi.Instance) => void;
selected?: boolean;
@@ -40,6 +41,7 @@ export function View({
onDelete,
onPurge,
onUpdate,
+ onChangePassword,
selected,
}: Props): VNode {
const [show, setShow] = useState<"active" | "deleted" | null>("active");
@@ -98,6 +100,7 @@ export function View({
instances={showingInstances}
onDelete={onDelete}
onPurge={onPurge}
+ onChangePassword={onChangePassword}
onUpdate={onUpdate}
selected={selected}
onCreate={onCreate}
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
index 8ce243686..3e0321e19 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
@@ -41,10 +41,15 @@ import { View } from "./View.js";
interface Props {
onCreate: () => void;
onUpdate: (id: string) => void;
+ onChangePassword: (id: string) => void;
instances: TalerMerchantApi.Instance[];
}
-export default function Instances({ onCreate, onUpdate }: Props): VNode {
+export default function Instances({
+ onCreate,
+ onUpdate,
+ onChangePassword,
+}: Props): VNode {
const result = useBackendInstances();
const [deleting, setDeleting] = useState<TalerMerchantApi.Instance | null>(
null,
@@ -80,6 +85,7 @@ export default function Instances({ onCreate, onUpdate }:
Props): VNode {
onCreate={onCreate}
onPurge={setPurging}
onUpdate={onUpdate}
+ onChangePassword={onChangePassword}
selected={!!deleting}
/>
{deleting && (
diff --git
a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
index c3a00bbed..3b786d2ad 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
@@ -19,6 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { AccessToken, createRFC8959AccessTokenPlain } from
"@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
@@ -26,11 +27,10 @@ import { AsyncButton } from
"../../../components/exception/AsyncButton.js";
import { FormProvider } from "../../../components/form/FormProvider.js";
import { Input } from "../../../components/form/Input.js";
import { NotificationCard } from "../../../components/menu/index.js";
-import { useSessionContext } from "../../../context/session.js";
-import { AccessToken, createRFC8959AccessTokenPlain } from
"@gnu-taler/taler-util";
import { undefinedIfEmpty } from "../../../utils/table.js";
interface Props {
+ instanceId: string;
hasToken: boolean | undefined;
onClearToken: (c: AccessToken | undefined) => void;
onNewToken: (c: AccessToken | undefined, s: AccessToken) => void;
@@ -38,6 +38,7 @@ interface Props {
}
export function DetailPage({
+ instanceId,
hasToken,
onBack,
onNewToken,
@@ -69,9 +70,7 @@ export function DetailPage({
const hasErrors = errors !== undefined;
- const { state } = useSessionContext();
-
- const text = i18n.str`You are updating the password from instance with id
"${state.instance}"`;
+ const text = i18n.str`You are updating the password from instance with id
"${instanceId}"`;
async function submitForm() {
if (hasErrors) return;
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
index 77071e532..1d0201bd9 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -17,6 +17,8 @@ import {
HttpStatusCode,
MerchantAuthMethod,
TalerError,
+ TalerMerchantInstanceHttpClient,
+ TalerMerchantManagementResultByMethod,
assertUnreachable,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
@@ -26,22 +28,47 @@ import { ErrorLoadingMerchant } from
"../../../components/ErrorLoadingMerchant.j
import { Loading } from "../../../components/exception/loading.js";
import { NotificationCard } from "../../../components/menu/index.js";
import { useSessionContext } from "../../../context/session.js";
-import { useInstanceDetails } from "../../../hooks/instance.js";
+import { useInstanceDetails, useManagedInstanceDetails } from
"../../../hooks/instance.js";
import { Notification } from "../../../utils/types.js";
import { LoginPage } from "../../login/index.js";
import { NotFoundPageOrAdminCreate } from "../../notfound/index.js";
import { DetailPage } from "./DetailPage.js";
-interface Props {
+export interface Props {
onChange: () => void;
onCancel: () => void;
}
-export default function Token({ onChange, onCancel }: Props): VNode {
+export default function Token(props: Props): VNode {
+ const { lib } = useSessionContext();
+ const updateCurrentInstanceAuthentication =
lib.instance.updateCurrentInstanceAuthentication.bind(lib.instance);
+ const createAuthTokenFromToken =
lib.instance.createAuthTokenFromToken.bind(lib.instance);
+ const result = useInstanceDetails();
+ return CommonToken(props, result, updateCurrentInstanceAuthentication,
createAuthTokenFromToken, true)
+}
+
+export function AdminToken(props: Props& { instanceId: string }): VNode {
+ const { lib } = useSessionContext();
+ const subInstaceLib = lib.subInstanceApi(props.instanceId).instance;
+ const updateCurrentInstanceAuthentication =
subInstaceLib.updateCurrentInstanceAuthentication.bind(subInstaceLib);
+ const createAuthTokenFromToken =
subInstaceLib.createAuthTokenFromToken.bind(subInstaceLib);
+ const result = useManagedInstanceDetails(props.instanceId);
+ return CommonToken(props, result, updateCurrentInstanceAuthentication,
createAuthTokenFromToken, false)
+}
+
+function CommonToken(
+ { onChange, onCancel }: Props,
+ result:
+ | TalerMerchantManagementResultByMethod<"getInstanceDetails">
+ | TalerError
+ | undefined,
+ updateCurrentInstanceAuthentication: typeof
TalerMerchantInstanceHttpClient.prototype.updateCurrentInstanceAuthentication,
+ createAuthTokenFromToken: typeof
TalerMerchantInstanceHttpClient.prototype.createAuthTokenFromToken,
+ replaceSession: boolean,
+): VNode {
const { i18n } = useTranslationContext();
- const { state, logIn, lib } = useSessionContext();
+ const { state, logIn } = useSessionContext();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const result = useInstanceDetails();
if (!result) return <Loading />;
if (result instanceof TalerError) {
@@ -68,10 +95,11 @@ export default function Token({ onChange, onCancel }:
Props): VNode {
<NotificationCard notification={notif} />
<DetailPage
onBack={onCancel}
+ instanceId={result.body.name}
hasToken={hasToken}
onClearToken={async (currentToken): Promise<void> => {
try {
- const resp = await
lib.instance.updateCurrentInstanceAuthentication(
+ const resp = await updateCurrentInstanceAuthentication(
currentToken,
{
method: MerchantAuthMethod.EXTERNAL,
@@ -99,7 +127,7 @@ export default function Token({ onChange, onCancel }:
Props): VNode {
try {
{
const resp =
- await lib.instance.updateCurrentInstanceAuthentication(
+ await updateCurrentInstanceAuthentication(
currentToken,
{
token: newToken,
@@ -114,7 +142,7 @@ export default function Token({ onChange, onCancel }:
Props): VNode {
});
}
}
- const resp = await lib.instance.createAuthTokenFromToken(newToken,
{
+ const resp = await createAuthTokenFromToken(newToken, {
scope: "write",
duration: {
d_us: "forever",
@@ -122,7 +150,10 @@ export default function Token({ onChange, onCancel }:
Props): VNode {
refreshable: true,
});
if (resp.type === "ok") {
- logIn(state.instance, resp.body.token);
+ if (replaceSession) {
+ // only renew the session token if we are not the admin
+ logIn(state.instance, resp.body.token);
+ }
return onChange();
} else {
return setNotif({
diff --git
a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
index 2b2327eb2..eeb522a6e 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
@@ -35,11 +35,6 @@ import { UpdatePage } from "./UpdatePage.js";
export interface Props {
onBack: () => void;
onConfirm: () => void;
-
- // onUnauthorized: () => VNode;
- // onNotFound: () => VNode;
- // onLoadError: (e: HttpError<TalerErrorDetail>) => VNode;
- // onUpdateError: (e: HttpError<TalerErrorDetail>) => void;
}
export default function Update(props: Props): VNode {
diff --git a/packages/taler-util/src/http-client/bank-core.ts
b/packages/taler-util/src/http-client/bank-core.ts
index 60443fa50..9e1e2097e 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -29,6 +29,7 @@ import {
TokenRequest,
UserAndPassword,
UserAndToken,
+ assertUnreachable,
codecForTalerCommonConfigResponse,
codecForTokenInfoList,
codecForTokenSuccessResponse,
@@ -100,6 +101,15 @@ export enum TalerCoreBankCacheEviction {
CREATE_CASHOUT,
}
+export type Credentials = BasicCredentials | BearerCredentials;
+export type BasicCredentials = {
+ type: "basic";
+ password: string;
+};
+export type BearerCredentials = {
+ type: "bearer";
+ accessToken: AccessToken;
+};
/**
* Protocol version spoken with the core bank.
*
@@ -129,11 +139,12 @@ export class TalerCoreBankHttpClient {
}
/**
+ *
*
https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token
*/
- async createAccessTokenBasic(
+ async createAccessToken(
username: string,
- password: string,
+ cred: Credentials,
body: TokenRequest,
cid?: string,
) {
@@ -141,7 +152,12 @@ export class TalerCoreBankHttpClient {
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
- Authorization: makeBasicAuthHeader(username, password),
+ Authorization:
+ cred.type === "basic"
+ ? makeBasicAuthHeader(username, cred.password)
+ : cred.type === "bearer"
+ ? makeBearerTokenAuthHeader(cred.accessToken)
+ : assertUnreachable(cred),
"X-Challenge-Id": cid,
},
body,
@@ -175,6 +191,24 @@ export class TalerCoreBankHttpClient {
}
}
+ /**
+ * @deprecated use createAccessToken
+ *
https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token
+ */
+ async createAccessTokenBasic(
+ username: string,
+ password: string,
+ body: TokenRequest,
+ cid?: string,
+ ) {
+ return this.createAccessToken(
+ username,
+ { type: "basic", password },
+ body,
+ cid,
+ );
+ }
+
/**
*
https://docs.taler.net/core/api-corebank.html#delete--accounts-$USERNAME-token
*/
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-typescript-core] branch master updated: fix #9754,
Admin <=