commit b677f250a8ee66b580189718960c5286b38b9bc0
parent f25215a33118c82260ced14f4867f081d786be1e
Author: Sebastian <sebasjm@gmail.com>
Date: Mon, 23 Jun 2025 09:22:02 -0300
fix #10120
Diffstat:
1 file changed, 79 insertions(+), 59 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -14,6 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import {
+ AccessToken,
HttpStatusCode,
MerchantAuthMethod,
TalerError,
@@ -43,35 +44,84 @@ export interface Props {
}
export default function Token(props: Props): VNode {
- const { lib, state } = useSessionContext();
- const updateCurrentInstanceAuthentication =
- lib.instance.updateCurrentInstanceAuthentication.bind(lib.instance);
- const createAuthTokenFromToken = lib.instance.createAuthTokenFromToken.bind(
- lib.instance,
- );
+ const { lib, state, logIn } = useSessionContext();
const result = useInstanceDetails();
+
+ async function changeToken(
+ currentToken: AccessToken | undefined,
+ newToken: AccessToken,
+ ) {
+ {
+ const resp = await lib.instance.updateCurrentInstanceAuthentication(
+ currentToken,
+ {
+ token: newToken,
+ method: MerchantAuthMethod.TOKEN,
+ },
+ );
+ if (resp.type === "fail") {
+ throw Error(resp.detail?.hint ?? "The request failed");
+ }
+ }
+ const resp = await lib.instance.createAuthTokenFromToken(newToken, {
+ scope: "write",
+ duration: {
+ d_us: "forever",
+ },
+ refreshable: true,
+ });
+ if (resp.type === "ok") {
+ logIn(state.instance, resp.body.token);
+ return;
+ } else {
+ throw Error(resp.detail?.hint ?? "The new login failed");
+ }
+ }
+
return CommonToken(
{ ...props, instanceId: state.instance },
result,
- updateCurrentInstanceAuthentication,
- createAuthTokenFromToken,
+ changeToken,
);
}
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 { lib, state } = useSessionContext();
+
+ const subInstanceLib = lib.subInstanceApi(props.instanceId).instance;
const result = useManagedInstanceDetails(props.instanceId);
- return CommonToken(
- props,
- result,
- updateCurrentInstanceAuthentication,
- createAuthTokenFromToken,
- );
+
+ async function changeToken(
+ currentToken: AccessToken | undefined,
+ newToken: AccessToken,
+ ) {
+ {
+ const resp = await lib.instance.updateInstanceAuthentication(
+ state.token,
+ props.instanceId,
+ {
+ token: newToken,
+ method: MerchantAuthMethod.TOKEN,
+ },
+ );
+ if (resp.type === "fail") {
+ throw Error(resp.detail?.hint ?? "The request failed");
+ }
+ }
+ const resp = await subInstanceLib.createAuthTokenFromToken(newToken, {
+ scope: "write",
+ duration: {
+ d_us: "forever",
+ },
+ refreshable: true,
+ });
+ if (resp.type === "ok") {
+ return;
+ } else {
+ throw Error(resp.detail?.hint ?? "The new login failed");
+ }
+ }
+ return CommonToken(props, result, changeToken);
}
function CommonToken(
@@ -80,11 +130,13 @@ function CommonToken(
| TalerMerchantManagementResultByMethod<"getInstanceDetails">
| TalerError
| undefined,
- updateCurrentInstanceAuthentication: typeof TalerMerchantInstanceHttpClient.prototype.updateCurrentInstanceAuthentication,
- createAuthTokenFromToken: typeof TalerMerchantInstanceHttpClient.prototype.createAuthTokenFromToken,
+ onNewToken: (
+ oldToken: AccessToken | undefined,
+ newToken: AccessToken,
+ ) => Promise<void>,
): VNode {
const { i18n } = useTranslationContext();
- const { state, logIn } = useSessionContext();
+ const { state } = useSessionContext();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
if (!result) return <Loading />;
@@ -105,7 +157,8 @@ function CommonToken(
}
}
- const adminChangingPwdForAnotherInstance = state.isAdmin && state.instance !== instanceId;
+ const adminChangingPwdForAnotherInstance =
+ state.isAdmin && state.instance !== instanceId;
const hasToken =
result.body.auth.method === MerchantAuthMethod.TOKEN &&
!adminChangingPwdForAnotherInstance;
@@ -119,41 +172,8 @@ function CommonToken(
hasToken={hasToken}
onNewToken={async (currentToken, newToken): Promise<void> => {
try {
- {
- const resp = await updateCurrentInstanceAuthentication(
- state.isAdmin ? state.token : currentToken,
- {
- token: newToken,
- method: MerchantAuthMethod.TOKEN,
- },
- );
- if (resp.type === "fail") {
- return setNotif({
- message: i18n.str`Failed to set new password`,
- type: "ERROR",
- description: resp.detail?.hint,
- });
- }
- }
- const resp = await createAuthTokenFromToken(newToken, {
- scope: "write",
- duration: {
- d_us: "forever",
- },
- refreshable: true,
- });
- if (resp.type === "ok") {
- if (!state.isAdmin) {
- // only renew the session token if we are not the admin
- logIn(state.instance, resp.body.token);
- }
- return onChange();
- } else {
- return setNotif({
- message: i18n.str`Failed to set new password`,
- type: "ERROR",
- });
- }
+ await onNewToken(currentToken, newToken);
+ return onChange();
} catch (error) {
return setNotif({
message: i18n.str`Failed to set new password`,