| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import path from 'node:path'
- import fs from 'node:fs'
- import AnalyticsManager from '../app/src/Features/Analytics/AnalyticsManager.mjs'
- import { waitForDb, db } from '../app/src/infrastructure/mongodb.mjs'
- import { Subscription } from '../app/src/models/Subscription.mjs'
- import minimist from 'minimist'
- import { promiseMapWithLimit } from '@overleaf/promise-utils'
- import _ from 'lodash'
- import { scriptRunner } from './lib/ScriptRunner.mjs'
- /**
- * This script is used to remove some users from the IEEEPublications group.
- *
- * Parameters:
- * --filename: the filename of the JSON file containing emails of users that
- * should **not** be removed
- * --commit: if present, the script will commit the changes to the database.
- *
- * Usage:
- * - dry run:
- * node scripts/remove_unwanted_ieee_collabratec_users.mjs --filename=emails-to-keep.json
- * - commit:
- * node scripts/remove_unwanted_ieee_collabratec_users.mjs --filename=emails-to-keep.json --commit
- */
- let COMMIT = false
- let EMAILS_FILENAME
- /**
- * The IEEE have provided us with a list of active users that should not be removed
- * This method retrieves those users.
- */
- function getActiveUserEmails(filename) {
- const data = fs.readFileSync(path.join(import.meta.dirname, filename), 'utf8')
- const emailsArray = JSON.parse(data)
- const emailsSet = new Set(emailsArray)
- console.log(
- `Read ${emailsSet.size} (${emailsArray.length} in array) emails from ${filename}`
- )
- return emailsSet
- }
- async function getIEEEUsers() {
- const results = await db.subscriptions
- .aggregate([
- { $match: { teamName: 'IEEEPublications' } },
- { $unwind: '$member_ids' },
- {
- $lookup: {
- from: 'users',
- localField: 'member_ids',
- foreignField: '_id',
- as: 'member_details',
- },
- },
- {
- $project: {
- _id: 1,
- teamName: 1,
- 'member_details._id': 1,
- 'member_details.email': 1,
- 'member_details.emails.email': 1,
- },
- },
- ])
- .toArray()
- return results
- .map(subscription => subscription.member_details[0])
- .filter(Boolean)
- }
- async function main() {
- const start = performance.now()
- if (!EMAILS_FILENAME) {
- throw new Error('No email filename provided')
- }
- await waitForDb()
- const subscription = await Subscription.findOne({
- teamName: 'IEEEPublications',
- })
- if (!subscription) {
- console.error(`No IEEEPublications group subscription found so quitting`)
- return
- }
- /**
- * @type {string[]}
- */
- const oldMemberIds = subscription.member_ids.map(id => id.toString())
- console.log(
- `Found ${oldMemberIds.length} members_ids in IEEEPublications group`
- )
- const usersArray = await getIEEEUsers()
- console.log(
- `Found ${usersArray.length} users in IEEEPublications group. (${oldMemberIds.length - usersArray.length} missing)`
- )
- const activeUsers = getActiveUserEmails(EMAILS_FILENAME)
- const activeUsersFound = new Set()
- /**
- * @type {string[]}
- */
- const memberIdsToRemove = []
- let index = 0
- // Then go through each IEEEPublications group member to see if we need to remove them
- await promiseMapWithLimit(10, usersArray, async userDetails => {
- if (index % 1000 === 0)
- console.log(
- `progress: ${index} / ${usersArray.length} (${memberIdsToRemove.length} to remove)`
- )
- index = index + 1
- if (COMMIT) {
- await AnalyticsManager.setUserPropertyForUser(
- userDetails._id.toString(),
- 'ieee-retirement',
- true
- )
- }
- for (const email of userDetails.emails) {
- if (activeUsers.has(email.email)) {
- activeUsersFound.add(email.email)
- return
- }
- }
- memberIdsToRemove.push(userDetails._id.toString())
- })
- console.log(`Found ${memberIdsToRemove.length} users to remove`)
- /**
- * @type {string[]}
- */
- const memberIdsToKeep = _.difference(oldMemberIds, memberIdsToRemove)
- console.log(`Keeping ${memberIdsToKeep.length} users`)
- if (COMMIT) {
- await Subscription.updateOne(
- { teamName: 'IEEEPublications' },
- { member_ids: memberIdsToKeep }
- )
- }
- console.log(`Found ${activeUsersFound.size} active users`)
- const activeUsersNotFound = Array.from(activeUsers).filter(
- user => !activeUsersFound.has(user)
- )
- console.log(`${activeUsersNotFound.length} IEEE active users not found:`)
- console.log(activeUsersNotFound)
- const subscriptionAfter = await Subscription.findOne({
- teamName: 'IEEEPublications',
- })
- console.log(
- `There are now ${subscriptionAfter?.member_ids?.length} member_ids in IEEEPublications group`
- )
- const end = performance.now()
- console.log(`Took ${end - start} ms`)
- }
- const setup = () => {
- const argv = minimist(process.argv.slice(2))
- COMMIT = argv.commit !== undefined
- EMAILS_FILENAME = argv.filename
- if (!COMMIT) {
- console.warn('Doing dry run. Add --commit to commit changes')
- }
- }
- setup()
- try {
- await scriptRunner(main)
- process.exit(0)
- } catch (error) {
- console.error(error)
- process.exit(1)
- }
|