Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / calendar / author.ts
blobc31059cd070c290a7bfd675d68de1aba92622331
1 import type { PublicKeyReference } from '@proton/crypto';
2 import { captureMessage } from '@proton/shared/lib/helpers/sentry';
3 import type { ContactEmail } from '@proton/shared/lib/interfaces/contacts';
4 import type { GetVerificationPreferences } from '@proton/shared/lib/interfaces/hooks/GetVerificationPreferences';
5 import isTruthy from '@proton/utils/isTruthy';
6 import unique from '@proton/utils/unique';
8 import { canonicalizeInternalEmail } from '../helpers/email';
9 import type { CalendarEvent, CalendarEventData } from '../interfaces/calendar';
10 import type { SimpleMap } from '../interfaces/utils';
11 import { CALENDAR_CARD_TYPE } from './constants';
13 const { SIGNED, ENCRYPTED_AND_SIGNED } = CALENDAR_CARD_TYPE;
15 export const withNormalizedAuthor = (x: CalendarEventData) => ({
16     ...x,
17     Author: canonicalizeInternalEmail(x.Author),
18 });
19 export const withNormalizedAuthors = (x: CalendarEventData[]) => {
20     if (!x) {
21         return [];
22     }
23     return x.map(withNormalizedAuthor);
26 interface GetAuthorPublicKeysMap {
27     event: CalendarEvent;
28     getVerificationPreferences: GetVerificationPreferences;
29     contactEmailsMap: SimpleMap<ContactEmail>;
32 export const getAuthorPublicKeysMap = async ({
33     event,
34     getVerificationPreferences,
35     contactEmailsMap,
36 }: GetAuthorPublicKeysMap) => {
37     const publicKeysMap: SimpleMap<PublicKeyReference | PublicKeyReference[]> = {};
38     const authors = unique(
39         [...event.SharedEvents, ...event.CalendarEvents]
40             .map(({ Author, Type }) => {
41                 if (![SIGNED, ENCRYPTED_AND_SIGNED].includes(Type)) {
42                     // no need to fetch keys in this case
43                     return;
44                 }
45                 return canonicalizeInternalEmail(Author);
46             })
47             .filter(isTruthy)
48     );
50     const promises = authors.map(async (author) => {
51         try {
52             const { verifyingKeys } = await getVerificationPreferences({ email: author, contactEmailsMap });
53             publicKeysMap[author] = verifyingKeys;
54         } catch (error: any) {
55             // We're seeing too many unexpected offline errors in the GET /keys route.
56             // We log them to Sentry and ignore them here (no verification will take place in these cases)
57             const { ID, CalendarID } = event;
58             const errorMessage = error?.message || 'Unknown error';
59             captureMessage('Unexpected error verifying event signature', {
60                 extra: { message: errorMessage, eventID: ID, calendarID: CalendarID },
61             });
62         }
63     });
64     await Promise.all(promises);
66     return publicKeysMap;