diff --git a/services/web/scripts/clear_sessions_2fa.js b/services/web/scripts/clear_sessions_2fa.js new file mode 100644 index 0000000000..73292eed7a --- /dev/null +++ b/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) +})