aboutsummaryrefslogtreecommitdiff
path: root/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts
blob: 2ed3758464ccd63324ece612c71173a3fb1ed333 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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();
    },
  };
}