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
|
import {
AbsoluteTime,
Codec,
LockedAccount,
OfficerAccount,
buildCodecForObject,
codecForAbsoluteTime,
codecForString,
createNewOfficerAccount,
unlockOfficerAccount,
} from "@gnu-taler/taler-util";
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: OfficerAccount;
forget: () => void;
lock: () => void;
}
const OFFICER_KEY = buildStorageKey("officer", codecForOfficer());
const ACCOUNT_KEY = "account";
export function useOfficer(): OfficerState {
const accountStorage = useMemoryStorage<OfficerAccount>(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 { id, safe, signingKey } = await createNewOfficerAccount(pwd);
officerStorage.update({
account: safe,
when: AbsoluteTime.now(),
});
accountStorage.update({ id, signingKey });
},
};
}
if (account === undefined) {
return {
state: "locked",
forget: () => {
officerStorage.reset();
},
tryUnlock: async (pwd: string) => {
const ac = await unlockOfficerAccount(officer.account, pwd);
accountStorage.update(ac);
},
};
}
return {
state: "ready",
account: account,
lock: () => {
accountStorage.reset();
},
forget: () => {
officerStorage.reset();
accountStorage.reset();
},
};
}
|