Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / lib / auth / switch.ts
blobb445cf1e207a7468363dbbff72ff05bbf70c5602
1 import type { Api, ApiAuth } from '@proton/pass/types';
2 import { partition } from '@proton/pass/utils/array/partition';
3 import { revoke } from '@proton/shared/lib/api/auth';
4 import noop from '@proton/utils/noop';
6 import { getActiveSessions } from './session';
8 export type SwitchableSession = {
9     /** Fallsback to `Username` if address `DisplayName` is not set */
10     DisplayName: string;
11     lastUsedAt?: number;
12     LocalID: number;
13     PrimaryEmail: string;
14     UID: string;
15     UserID: string;
18 type AuthSwitchConfig = {
19     api: Api;
20     onSwitch: (LocalID: number) => void;
21     getSessions: () => SwitchableSession[];
22     onActiveSession: (session: SwitchableSession) => void;
23     onInactiveSession: (session: SwitchableSession) => void;
24     onSessionsSynced: (sessions: SwitchableSession[]) => void;
27 export const createAuthSwitchService = (config: AuthSwitchConfig) => {
28     const { api } = config;
30     return {
31         /** Revoke may be called on a session different then
32          * what the authentication store is actually configured
33          * with : as such, pass the `UID` to the revoke call.
34          * The API call is flagged as side-effects free to avoid
35          * mutating the API state of the current active session. */
36         revoke: (auth: ApiAuth) => {
37             api({ ...revoke(), sideEffects: false, auth }).catch(noop);
38             const localSessions = config.getSessions();
39             const revoked = localSessions.find((session) => session.UID === auth.UID);
40             if (revoked) config.onInactiveSession(revoked);
41         },
43         switch: config.onSwitch,
45         sync: async (options: { revalidate: boolean }): Promise<SwitchableSession[]> => {
46             const localSessions = config.getSessions();
47             const activeSessions = options.revalidate ? await getActiveSessions(api) : null;
49             if (!activeSessions) {
50                 config.onSessionsSynced(localSessions);
51                 return localSessions;
52             }
54             const sessions = new Map(activeSessions.map((session) => [session.LocalID, session]));
55             const [localActive, inactive] = partition(localSessions, ({ LocalID }) => sessions.has(LocalID!));
57             const active = localActive.map((session) => {
58                 const { DisplayName, Username, PrimaryEmail = '' } = sessions.get(session.LocalID)!;
59                 return {
60                     ...session,
61                     /** Fallback to `Username` if no `DisplayName` set
62                      * for the session's email address */
63                     DisplayName: DisplayName ?? Username,
64                     PrimaryEmail,
65                 };
66             });
68             active.forEach(config.onActiveSession);
69             inactive.forEach(config.onInactiveSession);
71             config.onSessionsSynced(active);
73             return active;
74         },
75     };
78 export type AuthSwitchService = ReturnType<typeof createAuthSwitchService>;