| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- const _ = require('lodash')
- const { formatTokenUsageStats } = require('./format-usage-stats')
- const LOG_EVERY_IN_S = parseInt(process.env.LOG_EVERY_IN_S || '5', 10)
- const DRY_RUN = !process.argv.includes('--dry-run=false')
- /**
- * @param {AccessTokenEncryptor} accessTokenEncryptor
- * @param {string} encryptedJson
- * @return {Promise<string>}
- */
- async function reEncryptTokens(accessTokenEncryptor, encryptedJson) {
- return await new Promise((resolve, reject) => {
- accessTokenEncryptor.decryptToJson(encryptedJson, (err, json) => {
- if (err) return reject(err)
- accessTokenEncryptor.encryptJson(json, (err, reEncryptedJson) => {
- if (err) return reject(err)
- resolve(reEncryptedJson)
- })
- })
- })
- }
- /**
- * @param {AccessTokenEncryptor} accessTokenEncryptor
- * @param {Collection} collection
- * @param {Object} paths
- * @param {Object} queryOptions
- * @return {Promise<{}>}
- */
- async function reEncryptTokensInCollection({
- accessTokenEncryptor,
- collection,
- paths,
- queryOptions,
- }) {
- const { collectionName } = collection
- const stats = {}
- let processed = 0
- let updatedNUsers = 0
- let lastLog = 0
- const logProgress = () => {
- if (DRY_RUN) {
- console.warn(
- `processed ${processed} | Would have updated ${updatedNUsers} users`
- )
- } else {
- console.warn(`processed ${processed} | Updated ${updatedNUsers} users`)
- }
- }
- const projection = { _id: 1 }
- for (const path of Object.values(paths)) {
- projection[path] = 1
- }
- const cursor = collection.find(
- {},
- {
- ...queryOptions,
- projection,
- }
- )
- for await (const doc of cursor) {
- processed++
- let update = null
- for (const [name, path] of Object.entries(paths)) {
- const blob = _.get(doc, path)
- if (!blob) continue
- // Schema: LABEL-VERSION:SALT:CIPHERTEXT:IV
- const [label] = blob.split(':')
- let [, version] = label.split('-')
- version = version || 'v2'
- const key = [name, version, collectionName, path, label].join(':')
- stats[key] = (stats[key] || 0) + 1
- if (version === 'v2') {
- update = update || {}
- update[path] = await reEncryptTokens(accessTokenEncryptor, blob)
- }
- }
- if (Date.now() - lastLog >= LOG_EVERY_IN_S * 1000) {
- logProgress()
- lastLog = Date.now()
- }
- if (update) {
- updatedNUsers++
- const { _id } = doc
- if (DRY_RUN) {
- console.log('Would upgrade tokens for user', _id, Object.keys(update))
- } else {
- console.log('Upgrading tokens for user', _id, Object.keys(update))
- await collection.updateOne({ _id }, { $set: update })
- }
- }
- }
- logProgress()
- formatTokenUsageStats(stats)
- }
- module.exports = {
- reEncryptTokensInCollection,
- }
|