• 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/scripts/convertBreachResolutions.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
/**
6
 * Executes once
7
 * The purpose of the script is to convert all `subscriber.breaches_resolved` to `subscriber.breaches_resolution`
8
 * with the goal of deprecating the column
9
 */
10

11
import Knex from 'knex'
12
import knexConfig from '../db/knexfile.js'
13
import { getAllBreachesFromDb } from '../utils/hibp.js'
14
import { getAllEmailsAndBreaches } from '../utils/breaches.js'
15
import { setBreachResolution } from '../db/tables/subscribers.js'
16
import { BreachDataTypes } from '../utils/breach-resolution.js'
17
const knex = Knex(knexConfig)
×
18

19
const LIMIT = 50 // with millions of records, we have to load a few at a time
×
20
let offset = 0 // looping through all records with offset
×
21
let subscribersArr = []
×
22

23
// load all breaches for ref
24
const allBreaches = await getAllBreachesFromDb()
×
25
if (allBreaches && allBreaches.length > 0) console.log('breaches loaded successfully! ', allBreaches.length)
×
26

27
// find all subscribers who resolved any breaches in the past, convert those
28
// records into the new v2 format
29
do {
×
30
  console.log(`Converting breaches_resolved to breach_resolution - start: ${offset} limit: ${LIMIT}`)
×
31
  subscribersArr = await knex
×
32
    .select('id', 'primary_email', 'breaches_resolved', 'breach_resolution')
33
    .from('subscribers')
34
    .whereNotNull('breaches_resolved')
35
    .limit(LIMIT)
36
    .offset(offset)
37

38
  console.log(`Loaded # of subscribers: ${subscribersArr.length}`)
×
39

40
  for (const subscriber of subscribersArr) {
×
41
    let { breaches_resolved: v1, breach_resolution: v2 } = subscriber
×
42
    console.debug({ v1 })
×
43
    console.debug({ v2 })
×
44

45
    let isV2Changed = false // use a boolean to track if v2 has been changed, only upsert if so
×
46

47
    // fetch subscriber all breaches / email
48
    const subscriberBreachesEmail = await getAllEmailsAndBreaches(subscriber, allBreaches)
×
49
    console.debug(JSON.stringify(subscriberBreachesEmail.verifiedEmails))
×
50

51
    for (const [email, resolvedRecencyIndices] of Object.entries(v1)) {
×
52
      console.debug({ email })
×
53
      console.debug({ resolvedRecencyIndices })
×
54
      for (const recencyIndex of resolvedRecencyIndices) {
×
55
        console.debug({ recencyIndex })
×
56
        // find subscriber's relevant recency index breach information
57
        const ve = subscriberBreachesEmail.verifiedEmails?.filter(ve => ve.email === email)[0] || {}
×
58
        const subBreach = ve.breaches?.filter(b => Number(b.recencyIndex) === Number(recencyIndex))[0] || null
×
59
        console.debug({ subBreach })
×
60

61
        if (!subBreach || !subBreach.DataClasses) {
×
62
          console.warn(`SKIP: Cannot find subscribers breach and data types - recency: ${recencyIndex} email: ${email}`)
×
63
          continue
×
64
        }
65

66
        // if email does not exist in v2, we need to add it to the object
67
        // format: {email: { recencyIndex: { isResolved: true, resolutionsChecked: [DataTypes]}}}
68
        if (!v2) v2 = {}
×
69
        if (!v2[email]) {
×
70
          v2[email] = {
×
71
            [recencyIndex]: {
72
              isResolved: true,
73
              resolutionsChecked: subBreach?.DataClasses || [BreachDataTypes.General]
×
74
            }
75
          }
76

77
          isV2Changed = true
×
78
        }
79
        if (v2[email][recencyIndex]?.isResolved) {
×
80
          console.log(`recencyIndex ${recencyIndex} exists in v2 and is resolved, no changes`)
×
81
        } else {
82
          console.log(`recencyIndex ${recencyIndex} either does not exist or is not resolved, overwriting`)
×
83
          v2[email][recencyIndex] = {
×
84
            isResolved: true,
85
            resolutionsChecked: subBreach?.DataClasses
86
          }
87
          isV2Changed = true
×
88
        }
89
      }
90
    }
91

92
    // check if v2 is changed, if so, upsert the new v2
93
    if (isV2Changed) {
×
94
      await setBreachResolution(subscriber, v2)
×
95
    }
96
  }
97
  offset += LIMIT
×
98
} while (subscribersArr.length === LIMIT)
99

100
// breaking out of do..while loop
101
console.log('Reaching the end of the table, offset ended at', offset)
×
102
process.exit()
×
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