commit f8c228464bfcd74e493aa5284d569fcf949a0b58
parent fa7373350d98a06541b16f1f4b9d46229cf39fd6
Author: Sebastian <sebasjm@gmail.com>
Date: Mon, 10 Nov 2025 07:47:56 -0300
fix #10553
Diffstat:
3 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/packages/aml-backoffice-ui/src/components/UnlockAccount.tsx b/packages/aml-backoffice-ui/src/components/UnlockAccount.tsx
@@ -21,10 +21,11 @@ import {
LocalNotificationBanner,
useForm,
useLocalNotificationBetter,
- useTranslationContext
+ useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { OfficerLocked } from "../hooks/officer.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
type FormType = {
password: string;
@@ -59,10 +60,13 @@ export function UnlockAccount({ officer }: { officer: OfficerLocked }): VNode {
officer.tryUnlock,
status.status === "fail" ? undefined : [status.result.password],
);
- const forget = safeFunctionHandler(
- async () => officer.forget(),
- [],
- );
+ unlock.onFail = (fail) => {
+ switch (fail.case) {
+ case HttpStatusCode.Forbidden:
+ return i18n.str`Couldn't unlock the account, the password may be wrong.`;
+ }
+ };
+ const forget = safeFunctionHandler(async () => officer.forget(), []);
return (
<div class="flex min-h-full flex-col ">
@@ -81,7 +85,7 @@ export function UnlockAccount({ officer }: { officer: OfficerLocked }): VNode {
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px] ">
- <div class="bg-gray-100 px-6 py-6 shadow sm:rounded-lg sm:px-12">
+ <form class="bg-gray-100 px-6 py-6 shadow sm:rounded-lg sm:px-12">
<div class="mb-4">
<InputLine
label={i18n.str`Password`}
@@ -101,7 +105,7 @@ export function UnlockAccount({ officer }: { officer: OfficerLocked }): VNode {
<i18n.Translate>Unlock</i18n.Translate>
</ButtonBetter>
</div>
- </div>
+ </form>
<ButtonBetter
type="button"
onClick={forget}
diff --git a/packages/aml-backoffice-ui/src/hooks/officer.ts b/packages/aml-backoffice-ui/src/hooks/officer.ts
@@ -18,9 +18,11 @@ import {
Codec,
Duration,
EddsaPrivP,
+ HttpStatusCode,
LockedAccount,
OfficerAccount,
OfficerId,
+ OperationFail,
OperationOk,
buildCodecForObject,
codecForAbsoluteTime,
@@ -29,7 +31,8 @@ import {
decodeCrock,
encodeCrock,
opFixedSuccess,
- unlockOfficerAccount,
+ opKnownFailure,
+ unlockOfficerAccount
} from "@gnu-taler/taler-util";
import {
buildStorageKey,
@@ -41,7 +44,7 @@ import { usePreferences } from "./preferences.js";
const DEFAULT_SESSION_DURATION = Duration.fromSpec({
// seconds: 10,
- hours: 1
+ hours: 1,
});
export interface Officer {
@@ -79,7 +82,7 @@ export interface OfficerNotFound {
export interface OfficerLocked {
state: "locked";
forget: () => OperationOk<void>;
- tryUnlock: (password: string) => Promise<OperationOk<void>>;
+ tryUnlock: (password: string) => Promise<OperationOk<void> | OperationFail<HttpStatusCode.Forbidden>>;
}
export interface OfficerReady {
state: "ready";
@@ -109,7 +112,7 @@ export function useOfficer(): OfficerState {
return {
id: accountStorage.value.id as OfficerId,
signingKey: decodeCrock(accountStorage.value.strKey) as EddsaPrivP,
- unlocked: accountStorage.value.unlocked
+ unlocked: accountStorage.value.unlocked,
};
}, [accountStorage.value?.id, accountStorage.value?.strKey]);
@@ -152,14 +155,19 @@ export function useOfficer(): OfficerState {
return opFixedSuccess(undefined);
},
tryUnlock: async (pwd: string) => {
- const ac = await unlockOfficerAccount(officer.account, pwd);
- // accountStorage.update(ac);
- accountStorage.update({
- id: ac.id,
- strKey: encodeCrock(ac.signingKey),
- unlocked: AbsoluteTime.now(),
- });
- return opFixedSuccess(undefined);
+ try {
+ const ac = await unlockOfficerAccount(officer.account, pwd);
+ // accountStorage.update(ac);
+ accountStorage.update({
+ id: ac.id,
+ strKey: encodeCrock(ac.signingKey),
+ unlocked: AbsoluteTime.now(),
+ });
+ return opFixedSuccess(undefined);
+ } catch (e) {
+ const d = opKnownFailure(HttpStatusCode.Forbidden);
+ return d;
+ }
},
};
}
diff --git a/packages/aml-backoffice-ui/src/pages/DecisionWizard.tsx b/packages/aml-backoffice-ui/src/pages/DecisionWizard.tsx
@@ -19,7 +19,7 @@ import {
PaytoString,
PaytoUri,
TalerError,
- TranslatedString
+ TranslatedString,
} from "@gnu-taler/taler-util";
import { CopyButton, useTranslationContext } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
@@ -118,7 +118,7 @@ export function DecisionWizard({
newPayto?: string;
formId: string | undefined;
step?: WizardSteps;
- officer: OfficerReady,
+ officer: OfficerReady;
onMove: (n: WizardSteps | undefined) => void;
}): VNode {
const { i18n } = useTranslationContext();
@@ -139,7 +139,12 @@ export function DecisionWizard({
return <Attributes formId={formId} />;
case "summary":
return (
- <Summary account={account} onMove={onMove} newPayto={newPayto} officer={officer}/>
+ <Summary
+ account={account}
+ onMove={onMove}
+ newPayto={newPayto}
+ officer={officer}
+ />
);
}
assertUnreachable(stepOrDefault);