taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit b677f250a8ee66b580189718960c5286b38b9bc0
parent f25215a33118c82260ced14f4867f081d786be1e
Author: Sebastian <sebasjm@gmail.com>
Date:   Mon, 23 Jun 2025 09:22:02 -0300

fix #10120

Diffstat:
Mpackages/merchant-backoffice-ui/src/paths/instance/token/index.tsx | 138+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
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`,