aboutsummaryrefslogtreecommitdiff
path: root/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/exchange-backoffice-ui/src/hooks/useOfficer.ts')
-rw-r--r--packages/exchange-backoffice-ui/src/hooks/useOfficer.ts100
1 files changed, 100 insertions, 0 deletions
diff --git a/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts b/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts
new file mode 100644
index 000000000..2ed375846
--- /dev/null
+++ b/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts
@@ -0,0 +1,100 @@
+import {
+ AbsoluteTime,
+ Codec,
+ buildCodecForObject,
+ codecForAbsoluteTime,
+ codecForString,
+} from "@gnu-taler/taler-util";
+import {
+ Account,
+ LockedAccount,
+ createNewAccount,
+ unlockAccount,
+} from "../account.js";
+import {
+ buildStorageKey,
+ useLocalStorage,
+ useMemoryStorage,
+} from "@gnu-taler/web-util/browser";
+
+export interface Officer {
+ account: LockedAccount;
+ when: AbsoluteTime;
+}
+
+const codecForLockedAccount = codecForString() as Codec<LockedAccount>;
+
+export const codecForOfficer = (): Codec<Officer> =>
+ buildCodecForObject<Officer>()
+ .property("account", codecForLockedAccount) // FIXME
+ .property("when", codecForAbsoluteTime) // FIXME
+ .build("Officer");
+
+export type OfficerState = OfficerNotReady | OfficerReady;
+export type OfficerNotReady = OfficerNotFound | OfficerLocked;
+interface OfficerNotFound {
+ state: "not-found";
+ create: (password: string) => Promise<void>;
+}
+interface OfficerLocked {
+ state: "locked";
+ forget: () => void;
+ tryUnlock: (password: string) => Promise<void>;
+}
+interface OfficerReady {
+ state: "ready";
+ account: Account;
+ forget: () => void;
+ lock: () => void;
+}
+
+const OFFICER_KEY = buildStorageKey("officer", codecForOfficer());
+const ACCOUNT_KEY = buildStorageKey<Account>("account");
+
+export function useOfficer(): OfficerState {
+ const accountStorage = useMemoryStorage(ACCOUNT_KEY);
+ const officerStorage = useLocalStorage(OFFICER_KEY);
+
+ const officer = officerStorage.value;
+ const account = accountStorage.value;
+
+ if (officer === undefined) {
+ return {
+ state: "not-found",
+ create: async (pwd: string) => {
+ const { accountId, safe, signingKey } = await createNewAccount(pwd);
+ officerStorage.update({
+ account: safe,
+ when: AbsoluteTime.now(),
+ });
+
+ accountStorage.update({ accountId, signingKey });
+ },
+ };
+ }
+
+ if (account === undefined) {
+ return {
+ state: "locked",
+ forget: () => {
+ officerStorage.reset();
+ },
+ tryUnlock: async (pwd: string) => {
+ const ac = await unlockAccount(officer.account, pwd);
+ accountStorage.update(ac);
+ },
+ };
+ }
+
+ return {
+ state: "ready",
+ account: account,
+ lock: () => {
+ accountStorage.reset();
+ },
+ forget: () => {
+ officerStorage.reset();
+ accountStorage.reset();
+ },
+ };
+}