mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-04 22:59:01 +02:00
Add script for backfilling hashed emails
GitOrigin-RevId: a4eb25ed4db8519bfab8360e9dd50bbfcf4313ae
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import minimist from 'minimist'
|
||||
import logger from '@overleaf/logger'
|
||||
import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
|
||||
import AnalyticsManager from '../../app/src/Features/Analytics/AnalyticsManager.js'
|
||||
import { db } from '../../app/src/infrastructure/mongodb.js'
|
||||
import { gracefulShutdown } from '../../app/src/infrastructure/GracefulShutdown.js'
|
||||
|
||||
/**
|
||||
* @typedef {(import('../../app/src/Features/Analytics/types').EmailChangePayload)} EmailChangePayload
|
||||
*/
|
||||
|
||||
async function getConfiguration() {
|
||||
const { commit, endDate, verbose } = minimist(process.argv.slice(2), {
|
||||
boolean: ['commit', 'verbose'],
|
||||
string: ['endDate'],
|
||||
})
|
||||
// Check endDate is valid
|
||||
if (endDate) {
|
||||
if (Number.isNaN(new Date(endDate).getTime())) {
|
||||
logger.error({ endDate }, 'endDate is not a valid date')
|
||||
usage()
|
||||
await shutdown()
|
||||
}
|
||||
}
|
||||
return {
|
||||
commit,
|
||||
endDate,
|
||||
verbose,
|
||||
}
|
||||
}
|
||||
|
||||
function usage() {
|
||||
console.log(
|
||||
'Usage: node scripts/analytics/backfill_hashed_emails.mjs [--commit] [--endDate date]'
|
||||
)
|
||||
console.log('--commit: actually perform the updates (default: dry run)')
|
||||
console.log('--verbose: enable verbose logging')
|
||||
console.log(
|
||||
'--endDate: only process emails created before this date (ISO format)'
|
||||
)
|
||||
}
|
||||
|
||||
function processBatch(users) {
|
||||
for (const user of users) {
|
||||
if (user.emails) {
|
||||
for (const emailDocument of user.emails) {
|
||||
if (endDate && emailDocument.createdAt > new Date(endDate)) {
|
||||
logger.debug(
|
||||
{
|
||||
email: emailDocument.email,
|
||||
createdAt: emailDocument.createdAt,
|
||||
},
|
||||
'Skipping email created after endDate'
|
||||
)
|
||||
continue
|
||||
}
|
||||
/** @type {EmailChangePayload} */
|
||||
const payload = {
|
||||
userId: user._id,
|
||||
email: emailDocument.email,
|
||||
createdAt: emailDocument.createdAt,
|
||||
action: 'created',
|
||||
emailConfirmedAt: emailDocument.confirmedAt,
|
||||
emailCreatedAt: emailDocument.createdAt,
|
||||
isPrimary: user.email === emailDocument.email,
|
||||
}
|
||||
logger.debug(
|
||||
{
|
||||
payload,
|
||||
id: user._id,
|
||||
email: emailDocument.email,
|
||||
userEmail: user.email,
|
||||
},
|
||||
'Registering email creation'
|
||||
)
|
||||
if (commit) {
|
||||
AnalyticsManager.registerEmailChange(payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function shutdown() {
|
||||
await gracefulShutdown()
|
||||
}
|
||||
|
||||
const { commit, endDate, verbose } = await getConfiguration()
|
||||
logger.logger.level(verbose ? 'debug' : 'info')
|
||||
|
||||
const query = {}
|
||||
|
||||
if (endDate) {
|
||||
logger.debug({ endDate }, 'Processing emails created before endDate')
|
||||
query.emails = {
|
||||
$exists: true,
|
||||
$elemMatch: { createdAt: { $lte: new Date(endDate) } },
|
||||
}
|
||||
} else {
|
||||
logger.debug({}, 'Processing all emails')
|
||||
}
|
||||
|
||||
if (!commit) {
|
||||
logger.info({}, 'Dry run mode (no changes will be made)')
|
||||
}
|
||||
|
||||
try {
|
||||
const processed = await batchedUpdate(
|
||||
db.users,
|
||||
query,
|
||||
processBatch,
|
||||
{
|
||||
email: 1,
|
||||
emails: 1,
|
||||
_id: 1,
|
||||
},
|
||||
{
|
||||
readPreference: 'secondaryPreferred',
|
||||
}
|
||||
)
|
||||
|
||||
logger.info({ processed }, 'Emails processed')
|
||||
} catch (error) {
|
||||
logger.error({ error }, 'Error during processing')
|
||||
}
|
||||
await shutdown()
|
||||
Reference in New Issue
Block a user