clear_sessions_2fa.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. const { promisify, promiseMapWithLimit } = require('@overleaf/promise-utils')
  2. const rClient = require('../app/src/Features/User/UserSessionsRedis').client()
  3. const args = require('minimist')(process.argv.slice(2))
  4. const CURSOR = args.cursor
  5. const COMMIT = args.commit === 'true'
  6. const CONCURRENCY = parseInt(args.concurrency, 10) || 50
  7. const LOG_EVERY_IN_S = parseInt(args['log-every-in-s'], 10) || 5
  8. function shouldDelete(session) {
  9. if (session.twoFactorAuthenticationPendingUser) {
  10. // twoFactorAuthenticationPendingUserId migration
  11. return true
  12. }
  13. // default: keep
  14. return false
  15. }
  16. async function processSession(key) {
  17. if (!key || !key.startsWith('sess:')) {
  18. throw new Error(`unexpected session key: ${key}`)
  19. }
  20. const blob = await rClient.get(key)
  21. if (!blob) return false // expired or deleted
  22. const session = JSON.parse(blob)
  23. if (shouldDelete(session)) {
  24. const deleteLabel = COMMIT ? 'delete' : 'would delete'
  25. console.warn(deleteLabel, key)
  26. if (COMMIT) {
  27. await rClient.del(key)
  28. }
  29. return true
  30. }
  31. return false
  32. }
  33. async function main() {
  34. console.warn({ COMMIT, CONCURRENCY, CURSOR, LOG_EVERY_IN_S })
  35. console.warn('starting in 10s')
  36. await promisify(setTimeout)(10_000)
  37. let processed = 0
  38. let deleted = 0
  39. function logProgress() {
  40. const deletedLabel = COMMIT ? 'deleted' : 'would have deleted'
  41. console.log(
  42. `processed ${processed} | ${deletedLabel} ${deleted} | cursor ${cursor}`
  43. )
  44. }
  45. let cursor = CURSOR
  46. let lastLog = 0
  47. while (cursor !== '0') {
  48. let keys
  49. ;[cursor, keys] = await rClient.scan(cursor || 0, 'MATCH', 'sess:*')
  50. const results = await promiseMapWithLimit(CONCURRENCY, keys, processSession)
  51. processed += keys.length
  52. for (const r of results) {
  53. if (r) deleted++
  54. }
  55. if (Date.now() - lastLog >= LOG_EVERY_IN_S * 1000) {
  56. logProgress()
  57. lastLog = Date.now()
  58. }
  59. }
  60. logProgress()
  61. console.log('Done.')
  62. await rClient.disconnect()
  63. }
  64. main().catch(err => {
  65. console.error(err)
  66. process.exit(1)
  67. })