1 import type { FetchedBreaches } from '@proton/components';
2 import { isBreached, isMonitored } from '@proton/pass/lib/items/item.predicates';
5 BreachAddressGetResponse,
6 BreachCustomEmailGetResponse,
7 BreachDomainPeekResponse,
10 } from '@proton/pass/types';
11 import { deobfuscate } from '@proton/pass/utils/obfuscate/xor';
13 import type { AddressBreachDTO, MonitorAddress, MonitorDomain } from './types';
14 import { AddressType, BreachFlag } from './types';
16 export const getDuplicatePasswords = (logins: ItemRevision<'login'>[]): UniqueItem[][] => {
17 const duplicatesMap = new Map<string, UniqueItem[]>();
18 const seenMap = new Map<string, UniqueItem>();
20 logins.forEach(({ data, itemId, shareId }) => {
21 if (!data.content.password.v) return;
23 const password = deobfuscate(data.content.password);
24 const seen = seenMap.get(password);
25 let duplicates = duplicatesMap.get(password);
27 if (!seen && !duplicates) return seenMap.set(password, { itemId, shareId });
30 duplicates = duplicates ?? [];
31 duplicates.push(seen);
32 duplicatesMap.set(password, duplicates);
33 seenMap.delete(password);
36 duplicates?.push({ itemId, shareId });
39 return Array.from(duplicatesMap.values());
42 export const getAddressId = (address: AddressBreachDTO): string => {
43 switch (address.type) {
44 case AddressType.CUSTOM:
45 case AddressType.PROTON:
46 return address.addressId;
47 case AddressType.ALIAS:
48 return `${address.shareId}:${address.itemId}`;
52 export const isBreachedMonitored = ({ Flags }: BreachCustomEmailGetResponse | BreachAddressGetResponse): boolean =>
53 (Flags & BreachFlag.MonitorDisabled) !== BreachFlag.MonitorDisabled;
55 export const intoCustomMonitorAddress = (breach: BreachCustomEmailGetResponse): MonitorAddress<AddressType.CUSTOM> => ({
56 addressId: breach.CustomEmailID,
57 breachCount: breach.BreachCounter,
58 breached: breach.BreachCounter > 0,
60 monitored: isBreachedMonitored(breach),
61 type: AddressType.CUSTOM,
62 verified: breach.Verified,
66 export const intoProtonMonitorAddress = (breach: BreachAddressGetResponse): MonitorAddress<AddressType.PROTON> => ({
67 addressId: breach.AddressID,
68 breachCount: breach.BreachCounter,
69 breached: breach.BreachCounter > 0,
70 breachedAt: breach.LastBreachTime,
72 monitored: isBreachedMonitored(breach),
73 type: AddressType.PROTON,
76 export const intoAliasMonitorAddress = (item: ItemRevision<'alias'>): MonitorAddress<AddressType.ALIAS> => ({
78 shareId: item.shareId,
79 breached: isBreached(item),
80 email: item.aliasEmail!,
81 monitored: isMonitored(item),
82 type: AddressType.ALIAS,
85 export const intoMonitorDomain = ({ Domain, BreachTime }: BreachDomainPeekResponse): MonitorDomain => ({
87 breachedAt: BreachTime,
90 export const intoFetchedBreach = (breach: Breach): FetchedBreaches => ({
94 severity: breach.Severity,
95 createdAt: breach.CreatedAt,
96 publishedAt: breach.PublishedAt,
97 size: breach.Size ?? 0,
98 passwordLastChars: breach.PasswordLastChars ?? null,
99 exposedData: breach.ExposedData.map((data) => ({ code: data.Code, name: data.Name, values: data.Values ?? [] })),
100 actions: breach.Actions.map((action) => ({
107 isAggregated: breach.Source.IsAggregated,
108 domain: breach.Source.Domain ?? null,
112 resolvedState: breach.ResolvedState,