• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / blurts-server / 45ba77d7-fd3c-4064-90eb-157d6aa10611

pending completion
45ba77d7-fd3c-4064-90eb-157d6aa10611

push

circleci

Robert Helmer
update the queue adr

282 of 1631 branches covered (17.29%)

Branch coverage included in aggregate %.

959 of 4375 relevant lines covered (21.92%)

3.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/utils/breach-resolution.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
import { getMessage } from './fluent.js'
6

7
/**
8
 * Equivalent of Typescript "enum"
9
 * These enum types map to HIBP's breach data types, defined in HIBP's API
10
 * Always reference enum instead of strings to avoid spelling error / typos (ie. BreachDataTypes.Passwords)
11
 */
12
const BreachDataTypes = {
×
13
  Passwords: 'passwords',
14
  Email: 'email-addresses',
15
  SSN: 'social-security-numbers',
16
  CreditCard: 'partial-credit-card-data',
17
  BankAccount: 'bank-account-numbers',
18
  PIN: 'pins',
19
  IP: 'ip-addresses',
20
  Address: 'physical-addresses',
21
  DoB: 'dates-of-birth',
22
  Phone: 'phone-numbers',
23
  SecurityQuestions: 'security-questions-and-answers',
24
  HistoricalPasswords: 'historical-passwords',
25
  General: 'general'
26
}
27

28
/**
29
 * TODO: Map from google doc: https://docs.google.com/document/d/1KoItFsTYVIBInIG2YmA7wSxkKS4vti_X0A0td_yaHVM/edit#
30
 * Hardcoded map of breach resolution data types
31
 *
32
 * @type { Record<keyof BreachDataTypes, { priority: number, header: string, body?: string, applicableCountryCodes?: string[] }> }
33
 */
34
const breachResolutionDataTypes = {
×
35
  [BreachDataTypes.Passwords]: {
36
    priority: 1,
37
    header: 'breach-checklist-pw-header-2',
38
    body: 'breach-checklist-pw-body-2'
39
  },
40
  [BreachDataTypes.Email]: {
41
    priority: 2,
42
    header: 'breach-checklist-email-header-2',
43
    body: 'breach-checklist-email-body'
44
  },
45
  [BreachDataTypes.SSN]: {
46
    priority: 3,
47
    header: 'breach-checklist-ssn-header',
48
    body: 'breach-checklist-ssn-body-2',
49
    // The resolution involves American companies, and thus does not apply in other countries:
50
    applicableCountryCodes: ['us']
51
  },
52
  [BreachDataTypes.CreditCard]: {
53
    priority: 4,
54
    header: 'breach-checklist-cc-header',
55
    body: 'breach-checklist-cc-body'
56
  },
57
  [BreachDataTypes.BankAccount]: {
58
    priority: 5,
59
    header: 'breach-checklist-bank-header',
60
    body: 'breach-checklist-bank-body'
61
  },
62
  [BreachDataTypes.PIN]: {
63
    priority: 6,
64
    header: 'breach-checklist-pin-header',
65
    body: 'breach-checklist-pin-body'
66
  },
67
  [BreachDataTypes.IP]: {
68
    priority: 7,
69
    header: 'breach-checklist-ip-header-2',
70
    body: 'breach-checklist-ip-body'
71
  },
72
  [BreachDataTypes.Address]: {
73
    priority: 8,
74
    header: 'breach-checklist-address-header',
75
    body: 'breach-checklist-address-body'
76
  },
77
  [BreachDataTypes.DoB]: {
78
    priority: 9,
79
    header: 'breach-checklist-dob-header',
80
    body: 'breach-checklist-dob-body'
81
  },
82
  [BreachDataTypes.Phone]: {
83
    priority: 10,
84
    header: 'breach-checklist-phone-header-2'
85
  },
86
  [BreachDataTypes.SecurityQuestions]: {
87
    priority: 11,
88
    header: 'breach-checklist-sq-header-2',
89
    body: 'breach-checklist-sq-body'
90
  },
91
  [BreachDataTypes.HistoricalPasswords]: {
92
    priority: 12,
93
    header: 'breach-checklist-hp-header',
94
    body: 'breach-checklist-hp-body-2'
95
  },
96
  [BreachDataTypes.General]: {
97
    priority: 13,
98
    header: 'breach-checklist-general-header'
99
  }
100
}
101

102
/**
103
 * Append a field "breachChecklist" to the breaches array of each verified emails
104
 * The checklist serves the UI with relevant recommendations based on the array of datatypes leaked during a breach.
105
 *
106
 * @param {Array} userBreachData contains monitored verified emails array. Each email may contain a breaches array
107
 * @param {Partial<{ countryCode: string }>} options
108
 * @returns {*} void
109
 */
110
function appendBreachResolutionChecklist (userBreachData, options = {}) {
×
111
  const { verifiedEmails } = userBreachData
×
112
  for (const { breaches } of verifiedEmails) {
×
113
    breaches.forEach(b => {
×
114
      const dataClasses = b.DataClasses
×
115
      const args = {
×
116
        companyName: b.Name,
117
        firefoxRelayLink: `<a href="https://relay.firefox.com/?utm_medium=mozilla-websites&utm_source=monitor&utm_campaign=&utm_content=breach-resolution" target="_blank">${getMessage('breach-checklist-link-firefox-relay')}</a>`,
118
        passwordManagerLink: `<a href="https://www.mozilla.org/firefox/features/password-manager/?utm_medium=mozilla-websites&utm_source=monitor&utm_campaign=&utm_content=breach-resolution" target="_blank">${getMessage('breach-checklist-link-password-manager')}</a>`,
119
        mozillaVpnLink: `<a href="https://www.mozilla.org/products/vpn/?utm_medium=mozilla-websites&utm_source=monitor&utm_campaign=&utm_content=breach-resolution" target="_blank">${getMessage('breach-checklist-link-mozilla-vpn')}</a>`,
120
        equifaxLink: '<a href="https://www.equifax.com/personal/credit-report-services/credit-freeze/" target="_blank">Equifax</a>',
121
        experianLink: '<a href="https://www.experian.com/freeze/center.html" target="_blank">Experian</a>',
122
        transUnionLink: '<a href="https://www.transunion.com/credit-freeze" target="_blank">TransUnion</a>'
123
      }
124
      b.breachChecklist = getResolutionRecsPerBreach(dataClasses, args, { ...options, hideBreachLink: b.Domain.length <= 0 })
×
125
    })
126
  }
127
}
128

129
/**
130
 * Get a subset of the breach resolution data types map
131
 * based on the array of datatypes leaked during a breach
132
 *
133
 * @param {Array} dataTypes datatypes leaked during the breach
134
 * @param {object} args contains necessary variables for the fluent file
135
 *  - companyName
136
 *  - breachedCompanyUrl
137
 * @param {Partial<{ countryCode: string, hideBreachLink: boolean }>} options
138
 * @returns {Map} map of relevant breach resolution recommendations
139
 */
140
function getResolutionRecsPerBreach (dataTypes, args, options = {}) {
×
141
  const filteredBreachRecs = {}
×
142

143
  // filter breachResolutionDataTypes based on relevant data types passed in
144
  for (const [key, value] of Object.entries(breachResolutionDataTypes)) {
×
145
    if (
×
146
      dataTypes.includes(key) &&
×
147
      // Hide the security question or password resolution if we can't link to the breached site:
148
      (![BreachDataTypes.Passwords, BreachDataTypes.SecurityQuestions].includes(key) || !options.hideBreachLink) &&
149
      // Hide resolutions that apply to other countries than the user's:
150
      (!options.countryCode || !Array.isArray(value.applicableCountryCodes) || value.applicableCountryCodes.includes(options.countryCode.toLowerCase()))
151
    ) {
152
      filteredBreachRecs[key] = getRecommendationFromResolution(value, args)
×
153
    }
154
  }
155

156
  // If we did not have any recommendations, add a generic recommendation:
157
  if (Object.keys(filteredBreachRecs).length === 0) {
×
158
    filteredBreachRecs[BreachDataTypes.General] = getRecommendationFromResolution(breachResolutionDataTypes[BreachDataTypes.General], args)
×
159
  }
160

161
  // loop through the breach recs
162
  return filteredBreachRecs
×
163
}
164

165
// find fluent text based on fluent ids
166
function getRecommendationFromResolution (resolution, args) {
167
  let { header, body, priority } = resolution
×
168
  header = header ? getMessage(header, args) : ''
×
169
  body = body ? getMessage(body, args) : ''
×
170
  return { header, body, priority }
×
171
}
172

173
/**
174
 * Take breach DataTypes array from HIBP and filter based on BreachDataTypes enums above
175
 *
176
 * @param {Array} originalDataTypes breach DataTypes array from HIBP
177
 * @returns {Array} filtered breach data types
178
 */
179
function filterBreachDataTypes (originalDataTypes) {
180
  const relevantDataTypes = Object.values(BreachDataTypes)
×
181
  return originalDataTypes.filter(d => relevantDataTypes.includes(d))
×
182
}
183

184
export { BreachDataTypes, appendBreachResolutionChecklist, filterBreachDataTypes }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc