101 lines
2.3 KiB
TypeScript
101 lines
2.3 KiB
TypeScript
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();
|
|
},
|
|
};
|
|
}
|