overleaf/services/web/scripts/clear_sessions_set_must_reconfirm.js
Antoine Clausse 25d8e053be [web] Update revokeAllUserSessions and rename it to removeSessionsFromRedis (#18360)
* Fix `revokeAllUserSessions` call in `_cleanupUser`

The user object should be passed, not the _id

* Change `revokeAllUserSessions` signature, take `req` and `stayLoggedIn` arguments

* Update uses of `revokeAllUserSessions`

* Fix promisified `revokeAllUserSessions` args

* Update tests

* Destroy or Regenerate the session in the end of `revokeAllUserSessions`

Per https://github.com/overleaf/internal/issues/17036#issuecomment-1938398570

* Revert "Destroy or Regenerate the session in the end of `revokeAllUserSessions`"

This reverts commit fe30734dbe45b27d2931d2e43a711d591bb85787.

* Rename `revokeAllUserSessions` to `removeSessionsFromRedis`

* Fixup tests

* Fix: add optional chaining in `req.sessionID` (!!)

GitOrigin-RevId: d41676bf00f463230af495e09c65fb9ee521f49f
2024-05-20 08:04:12 +00:00

87 lines
2.4 KiB
JavaScript

const fs = require('fs')
const { ObjectId, waitForDb } = require('../app/src/infrastructure/mongodb')
const async = require('async')
const UserUpdater = require('../app/src/Features/User/UserUpdater')
const UserSessionsManager = require('../app/src/Features/User/UserSessionsManager')
const ASYNC_LIMIT = 10
const processLogger = {
failedClear: [],
failedSet: [],
success: [],
printSummary: () => {
console.log(
{
success: processLogger.success,
failedClear: processLogger.failedClear,
failedSet: processLogger.failedSet,
},
`\nDONE. ${processLogger.success.length} successful. ${processLogger.failedClear.length} failed to clear sessions. ${processLogger.failedSet.length} failed to set must_reconfirm.`
)
},
}
function _validateUserIdList(userIds) {
if (!Array.isArray(userIds)) throw new Error('users is not an array')
userIds.forEach(userId => {
if (!ObjectId.isValid(userId)) throw new Error('user ID not valid')
})
}
function _handleUser(userId, callback) {
UserUpdater.updateUser(userId, { $set: { must_reconfirm: true } }, error => {
if (error) {
console.log(`Failed to set must_reconfirm ${userId}`, error)
processLogger.failedSet.push(userId)
return callback()
} else {
UserSessionsManager.removeSessionsFromRedis(
{ _id: userId },
null,
null,
error => {
if (error) {
console.log(`Failed to clear sessions for ${userId}`, error)
processLogger.failedClear.push(userId)
} else {
processLogger.success.push(userId)
}
return callback()
}
)
}
})
}
async function _loopUsers(userIds) {
await new Promise((resolve, reject) => {
async.eachLimit(userIds, ASYNC_LIMIT, _handleUser, error => {
if (error) return reject(error)
resolve()
})
})
}
const fileName = process.argv[2]
if (!fileName) throw new Error('missing filename')
const usersFile = fs.readFileSync(fileName, 'utf8')
const userIds = usersFile
.trim()
.split('\n')
.map(id => id.trim())
async function processUsers(userIds) {
console.log('---Starting set_must_reconfirm script---')
await waitForDb()
_validateUserIdList(userIds)
console.log(`---Starting to process ${userIds.length} users---`)
await _loopUsers(userIds)
processLogger.printSummary()
process.exit()
}
processUsers(userIds)