1 import { useEffect, useRef, useState } from 'react';
3 import { useUser } from '@proton/account/user/hooks';
4 import { useGetUserKeys } from '@proton/account/userKeys/hooks';
5 import useConfig from '@proton/components/hooks/useConfig';
6 import { getAuditResult, getKTLocalStorage, storeAuditResult } from '@proton/key-transparency/lib';
7 import type { KeyTransparencyState } from '@proton/shared/lib/interfaces';
8 import { getPrimaryKey } from '@proton/shared/lib/keys';
9 import noop from '@proton/utils/noop';
11 const useKTState = (): [boolean, KeyTransparencyState, React.Dispatch<React.SetStateAction<KeyTransparencyState>>] => {
12 const [ktState, setKTState] = useState<KeyTransparencyState>({
13 selfAuditResult: undefined,
15 const [loaded, setLoaded] = useState(false);
16 const firstUpdate = useRef(true);
18 const [{ ID: userID }] = useUser();
19 const { APP_NAME: appName } = useConfig();
20 const getUserKeys = useGetUserKeys();
23 const loadState = async () => {
24 // Loads the kt state from local storage and decrypts it with the user keys.
25 const userKeys = await getUserKeys();
26 const userPrivateKeys = userKeys.map(({ privateKey }) => privateKey);
27 const ktLSAPIPromise = getKTLocalStorage(appName);
28 const ktLSAPI = await ktLSAPIPromise;
29 const selfAuditResult = await getAuditResult(userID, userPrivateKeys, ktLSAPI);
30 if (selfAuditResult) {
31 setKTState({ selfAuditResult });
36 .finally(() => setLoaded(true));
40 const storeState = async () => {
41 if (!ktState.selfAuditResult) {
44 // Encrypts the kt state with the primary user key and stores it in local storage.
45 const userKeys = await getUserKeys();
46 const ktLSAPIPromise = getKTLocalStorage(appName);
47 const ktLSAPI = await ktLSAPIPromise;
48 const { publicKey: userPrimaryPublicKey } = getPrimaryKey(userKeys) || {};
49 if (userPrimaryPublicKey) {
50 await storeAuditResult(userID, ktState.selfAuditResult, userPrimaryPublicKey, ktLSAPI);
54 if (firstUpdate.current) {
55 // Skip the first loaded state update since it is already stored.
56 firstUpdate.current = false;
58 // A kt state update happened, store it in local storage.
59 void storeState().catch(noop);
62 }, [loaded, ktState]);
64 return [loaded, ktState, setKTState];
67 export default useKTState;