mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-07-30 17:59:13 -04:00
92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import chalk from 'chalk'
|
|
import * as admin from 'firebase-admin'
|
|
import {initAdmin} from 'shared/init-admin'
|
|
import {isProd} from 'common/envs/is-prod'
|
|
|
|
// Deletes ALL Firebase Auth users. DEV ONLY.
|
|
//
|
|
// Used by ./scripts/dev_db_clear_firebase.sh as part of the dev DB reset flow.
|
|
// This is destructive and irreversible, so it hard-refuses to run against prod:
|
|
// - bails if ENVIRONMENT is not 'dev'
|
|
// - bails if isProd() is true
|
|
// - bails if the initialized Firebase project is the prod project
|
|
//
|
|
// Firebase project ids (see common/envs/is-prod.ts + init-admin.ts):
|
|
const DEV_FIREBASE_PROJECT_ID = 'compass-57c3c'
|
|
|
|
async function main() {
|
|
// 1. Refuse anything that isn't an explicit dev run.
|
|
const env = process.env.ENVIRONMENT?.toUpperCase()
|
|
if (env !== 'DEV') {
|
|
throw new Error(
|
|
`Refusing to clear Firebase users: ENVIRONMENT is "${process.env.ENVIRONMENT ?? '(unset)'}", expected "dev". ` +
|
|
`This script is DEV ONLY.`,
|
|
)
|
|
}
|
|
|
|
initAdmin()
|
|
|
|
// 2. Belt-and-suspenders: refuse if the resolved config looks like prod.
|
|
if (isProd()) {
|
|
throw new Error(
|
|
'Refusing to clear Firebase users: isProd() returned true. This script is DEV ONLY.',
|
|
)
|
|
}
|
|
|
|
const projectId = admin.app().options.projectId
|
|
console.log({projectId})
|
|
if (projectId !== DEV_FIREBASE_PROJECT_ID) {
|
|
throw new Error(
|
|
`Refusing to clear Firebase users: initialized Firebase project is the PROD project ` +
|
|
`("${projectId}"). This script is DEV ONLY.`,
|
|
)
|
|
}
|
|
|
|
const auth = admin.app().auth()
|
|
console.log(
|
|
chalk.cyan(`Clearing all Firebase Auth users on project "${projectId ?? '(unknown)'}"…`),
|
|
)
|
|
|
|
let totalDeleted = 0
|
|
let totalFailed = 0
|
|
|
|
// listUsers returns up to 1000 per page; deleteUsers accepts up to 1000 uids.
|
|
// Re-list from the start after each delete batch instead of paging, since
|
|
// deletions shift the page tokens.
|
|
for (;;) {
|
|
const {users} = await auth.listUsers(1000)
|
|
if (users.length === 0) break
|
|
|
|
const uids = users.map((u) => u.uid)
|
|
const result = await auth.deleteUsers(uids)
|
|
|
|
totalDeleted += result.successCount
|
|
totalFailed += result.failureCount
|
|
|
|
for (const err of result.errors) {
|
|
console.error(chalk.red(` [ERROR] uid=${uids[err.index]} — ${err.error.message}`))
|
|
}
|
|
|
|
console.log(
|
|
chalk.blue(
|
|
` Deleted ${result.successCount}/${uids.length} in this batch (running total: ${totalDeleted})`,
|
|
),
|
|
)
|
|
|
|
// If a whole batch fails, stop to avoid an infinite loop.
|
|
if (result.successCount === 0) break
|
|
}
|
|
|
|
console.log(chalk.cyan('\n── Firebase clear complete ─────────────────────────'))
|
|
console.log(chalk.green(` Deleted : ${totalDeleted}`))
|
|
console.log(chalk.red(` Failed : ${totalFailed}`))
|
|
console.log(chalk.cyan('────────────────────────────────────────────────────'))
|
|
|
|
process.exit(totalFailed > 0 ? 1 : 0)
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(chalk.red(err instanceof Error ? err.message : err))
|
|
process.exit(1)
|
|
})
|