1 import type { PrivateKeyReference, PublicKeyReference, SessionKey } from '@proton/crypto';
3 import type { SimpleMap } from '../interfaces';
4 import type { VcalVeventComponent } from '../interfaces/calendar';
5 import { CALENDAR_CARD_TYPE } from './constants';
9 getEncryptedSessionKey,
10 getEncryptedSessionKeysMap,
12 } from './crypto/encrypt';
13 import { formatData } from './formatData';
14 import { getVeventParts } from './veventHelper';
16 const { ENCRYPTED_AND_SIGNED, SIGNED, CLEAR_TEXT } = CALENDAR_CARD_TYPE;
19 * Split the properties of the component into parts.
21 const getParts = (eventComponent: VcalVeventComponent) => {
22 return getVeventParts(eventComponent);
26 * Create a calendar event by encrypting and serializing an internal vcal component.
28 interface CreateCalendarEventArguments {
29 eventComponent: VcalVeventComponent;
30 cancelledOccurrenceVevent?: VcalVeventComponent;
31 publicKey: PublicKeyReference;
32 privateKey: PrivateKeyReference;
33 sharedSessionKey?: SessionKey;
34 calendarSessionKey?: SessionKey;
35 isCreateEvent: boolean;
36 isSwitchCalendar: boolean;
37 hasDefaultNotifications: boolean;
39 removedAttendeesEmails?: string[];
40 addedAttendeesPublicKeysMap?: SimpleMap<PublicKeyReference>;
42 export const createCalendarEvent = async ({
44 cancelledOccurrenceVevent,
47 sharedSessionKey: oldSharedSessionKey,
48 calendarSessionKey: oldCalendarSessionKey,
51 hasDefaultNotifications,
53 removedAttendeesEmails = [],
54 addedAttendeesPublicKeysMap,
55 }: CreateCalendarEventArguments) => {
56 const { sharedPart, calendarPart, notificationsPart, attendeesPart } = getParts(eventComponent);
57 const cancelledOccurrenceSharedPart = cancelledOccurrenceVevent
58 ? getParts(cancelledOccurrenceVevent).sharedPart
61 const isCreateOrSwitchCalendar = isCreateEvent || isSwitchCalendar;
62 const isAttendeeSwitchingCalendar = isSwitchCalendar && isAttendee;
63 // If there is no encrypted calendar part, a calendar session key is not needed.
64 const shouldHaveCalendarKey = !!calendarPart[ENCRYPTED_AND_SIGNED];
66 const [calendarSessionKey, sharedSessionKey] = await Promise.all([
67 shouldHaveCalendarKey ? oldCalendarSessionKey || createSessionKey(publicKey) : undefined,
68 oldSharedSessionKey || createSessionKey(publicKey),
72 encryptedCalendarSessionKey,
73 encryptedSharedSessionKey,
77 calendarEncryptedPart,
78 attendeesEncryptedPart,
79 attendeesEncryptedSessionKeysMap,
80 cancelledOccurrenceSignedPart,
81 ] = await Promise.all([
82 // If we're updating an event (but not switching calendar), no need to encrypt again the session keys
83 isCreateOrSwitchCalendar && calendarSessionKey
84 ? getEncryptedSessionKey(calendarSessionKey, publicKey)
86 isCreateOrSwitchCalendar ? getEncryptedSessionKey(sharedSessionKey, publicKey) : undefined,
87 // attendees are not allowed to change the SharedEventContent, so they shouldn't send it (API will complain otherwise)
88 isAttendeeSwitchingCalendar ? undefined : signPart(sharedPart[SIGNED], privateKey),
89 isAttendeeSwitchingCalendar
91 : encryptPart(sharedPart[ENCRYPTED_AND_SIGNED], privateKey, sharedSessionKey),
92 signPart(calendarPart[SIGNED], privateKey),
94 ? encryptPart(calendarPart[ENCRYPTED_AND_SIGNED], privateKey, calendarSessionKey)
96 // attendees are not allowed to change the SharedEventContent, so they shouldn't send it (API will complain otherwise)
97 isAttendeeSwitchingCalendar
99 : encryptPart(attendeesPart[ENCRYPTED_AND_SIGNED], privateKey, sharedSessionKey),
100 getEncryptedSessionKeysMap(sharedSessionKey, addedAttendeesPublicKeysMap),
101 cancelledOccurrenceSharedPart ? signPart(cancelledOccurrenceSharedPart[SIGNED], privateKey) : undefined,
107 cancelledOccurrenceSignedPart,
108 sharedSessionKey: encryptedSharedSessionKey,
110 calendarEncryptedPart,
111 calendarSessionKey: encryptedCalendarSessionKey,
112 notificationsPart: hasDefaultNotifications ? undefined : notificationsPart,
113 colorPart: eventComponent.color?.value,
114 attendeesEncryptedPart,
115 attendeesClearPart: isAttendeeSwitchingCalendar ? undefined : attendeesPart[CLEAR_TEXT],
116 removedAttendeesEmails,
117 attendeesEncryptedSessionKeysMap,