فهرست منبع

Merge pull request #11390 from overleaf/jpa-cleanup-sessions

[web] scripts: add a script for cleaning up sessions with 2fa artifact

GitOrigin-RevId: 134c2ad2c96defa54e89bbed7d7b20005c803aea
Eric Mc Sween 3 سال پیش
والد
کامیت
b11cb7d1e9
1فایلهای تغییر یافته به همراه78 افزوده شده و 0 حذف شده
  1. 78 0
      services/web/scripts/clear_sessions_2fa.js

+ 78 - 0
services/web/scripts/clear_sessions_2fa.js

@@ -0,0 +1,78 @@
+const { promisify, promiseMapWithLimit } = require('../app/src/util/promises')
+const rClient = require('../app/src/Features/User/UserSessionsRedis').client()
+
+const args = require('minimist')(process.argv.slice(2))
+const CURSOR = args.cursor
+const COMMIT = args.commit === 'true'
+const CONCURRENCY = parseInt(args.concurrency, 10) || 50
+const LOG_EVERY_IN_S = parseInt(args['log-every-in-s'], 10) || 5
+
+function shouldDelete(session) {
+  if (session.twoFactorAuthenticationPendingUser) {
+    // twoFactorAuthenticationPendingUserId migration
+    return true
+  }
+
+  // default: keep
+  return false
+}
+
+async function processSession(key) {
+  if (!key || !key.startsWith('sess:')) {
+    throw new Error(`unexpected session key: ${key}`)
+  }
+
+  const blob = await rClient.get(key)
+  if (!blob) return false // expired or deleted
+  const session = JSON.parse(blob)
+
+  if (shouldDelete(session)) {
+    const deleteLabel = COMMIT ? 'delete' : 'would delete'
+    console.warn(deleteLabel, key)
+    if (COMMIT) {
+      await rClient.del(key)
+    }
+    return true
+  }
+  return false
+}
+
+async function main() {
+  console.warn({ COMMIT, CONCURRENCY, CURSOR, LOG_EVERY_IN_S })
+  console.warn('starting in 10s')
+  await promisify(setTimeout)(10_000)
+
+  let processed = 0
+  let deleted = 0
+  function logProgress() {
+    const deletedLabel = COMMIT ? 'deleted' : 'would have deleted'
+    console.log(
+      `processed ${processed} | ${deletedLabel} ${deleted} | cursor ${cursor}`
+    )
+  }
+
+  let cursor = CURSOR
+  let lastLog = 0
+  while (cursor !== '0') {
+    let keys
+    ;[cursor, keys] = await rClient.scan(cursor || 0, 'MATCH', 'sess:*')
+
+    const results = await promiseMapWithLimit(CONCURRENCY, keys, processSession)
+    processed += keys.length
+    for (const r of results) {
+      if (r) deleted++
+    }
+    if (Date.now() - lastLog >= LOG_EVERY_IN_S * 1000) {
+      logProgress()
+      lastLog = Date.now()
+    }
+  }
+  logProgress()
+  console.log('Done.')
+  await rClient.disconnect()
+}
+
+main().catch(err => {
+  console.error(err)
+  process.exit(1)
+})