1 import { useCallback } from 'react';
3 import { useGetKTActivation } from '@proton/components/containers/keyTransparency/useKTActivation';
4 import useApi from '@proton/components/hooks/useApi';
5 import type { SelfAuditResult } from '@proton/key-transparency/lib';
6 import { AddressAuditStatus, ktSentryReport } from '@proton/key-transparency/lib';
7 import metrics from '@proton/metrics';
8 import { getSilentApi } from '@proton/shared/lib/api/helpers/customConfig';
9 import type { TelemetryReport } from '@proton/shared/lib/api/telemetry';
10 import { TelemetryKeyTransparencyErrorEvents, TelemetryMeasurementGroups } from '@proton/shared/lib/api/telemetry';
11 import { sendMultipleTelemetryReports } from '@proton/shared/lib/helpers/metrics';
12 import type { SimpleMap } from '@proton/shared/lib/interfaces';
13 import { KeyTransparencyActivation } from '@proton/shared/lib/interfaces';
14 import { getWarningReason } from '@proton/shared/lib/keyTransparency/telemetry';
16 const useReportSelfAuditErrors = () => {
17 const normalApi = useApi();
18 const getKTActivation = useGetKTActivation();
20 const reportSelfAuditErrors = useCallback(async (selfAuditResult: SelfAuditResult) => {
21 const failedAddressAuditsResults = selfAuditResult.addressAuditResults.filter(
22 ({ status }) => status !== AddressAuditStatus.Success
24 const failedLocalStorageAuditsOwn = selfAuditResult.localStorageAuditResultsOwnAddress.filter(
25 ({ success }) => !success
27 const failedLocalStorageAuditsOther = selfAuditResult.localStorageAuditResultsOtherAddress.filter(
28 ({ success }) => !success
31 const failedAddressAudits = failedAddressAuditsResults.map(({ email, status, warningDetails }) => ({
36 const failedLSAuditsOwn = failedLocalStorageAuditsOwn.map(({ email }) => email);
37 const failedLSAuditsOther = failedLocalStorageAuditsOther.map(({ email }) => email);
39 const tooManyRetries = selfAuditResult.error?.tooManyRetries;
42 failedAddressAudits.filter(({ status }) => status === AddressAuditStatus.Failure).length ||
43 failedLSAuditsOwn.length ||
44 failedLSAuditsOther.length ||
47 ktSentryReport('Self audit would display an error', {
51 tooManyRetries: selfAuditResult.error?.tooManyRetries,
55 if (failedAddressAudits.length || failedLSAuditsOwn.length || failedLSAuditsOther.length || tooManyRetries) {
56 const reports: TelemetryReport[] = [];
59 measurementGroup: TelemetryMeasurementGroups.keyTransparency,
60 event: TelemetryKeyTransparencyErrorEvents.self_audit_error,
63 const ktActivation = await getKTActivation();
64 const visibility = ktActivation === KeyTransparencyActivation.SHOW_UI ? 'visible' : 'hidden';
67 const dimensions: SimpleMap<string> = {
68 type: 'too_many_retries',
70 reason: 'too_many_retries',
71 visibility: visibility,
77 void metrics.crypto_keytransparency_errors_total.increment({
80 visibility: visibility,
84 failedAddressAuditsResults.forEach(({ status, warningDetails }) => {
85 const isWarning = status === AddressAuditStatus.Warning;
86 const dimensions: SimpleMap<string> = {
88 result: isWarning ? 'warning' : 'failure',
89 reason: getWarningReason(warningDetails),
90 visibility: visibility,
96 void metrics.crypto_keytransparency_errors_total.increment({
97 level: isWarning ? 'warning' : 'error',
99 visibility: visibility,
102 failedLocalStorageAuditsOwn.forEach(() => {
103 const dimensions: SimpleMap<string> = {
104 type: 'local_storage_own_keys',
106 reason: 'local_key_changes_not_applied',
107 visibility: visibility,
114 void metrics.crypto_keytransparency_errors_total.increment({
117 visibility: visibility,
120 failedLocalStorageAuditsOther.forEach(() => {
121 const dimensions: SimpleMap<string> = {
122 type: 'local_storage_other_keys',
124 reason: 'past_keys_not_authentic',
125 visibility: visibility,
131 void metrics.crypto_keytransparency_errors_total.increment({
133 type: 'public-key-audit',
134 visibility: visibility,
138 void sendMultipleTelemetryReports({
139 api: getSilentApi(normalApi),
145 return reportSelfAuditErrors;
148 export default useReportSelfAuditErrors;