server/scripts/mfa-reset.ts
Rama main · réplica de lectura del repositorio original.
// 2단계 인증 초기화 — 인증 앱과 복구 코드를 모두 잃은 사람을 서버 관리자가 풀어 준다.
// 운영: npm run mfa:reset -w server -- 이메일
// OTP 를 끄고 복구 코드를 지우며, 코드를 기다리던 로그인은 지운다(다시 로그인). 기록(audit_log)에 남는다.
import { get, run, tx } from '../src/db.ts';
import { audit } from '../src/http.ts';
const email = String(process.argv[2] ?? '').trim().toLowerCase();
if (!email) {
console.error('사용법: npm run mfa:reset -w server -- 이메일');
process.exit(1);
}
const user = get<{ id: string; totp_secret: string | null }>('SELECT id, totp_secret FROM users WHERE email = ?', email);
if (!user) {
console.error(`그 이메일의 사용자가 없습니다: ${email}`);
process.exit(1);
}
if (!user.totp_secret) {
console.log(`${email} 은(는) 2단계 인증이 이미 꺼져 있습니다.`);
process.exit(0);
}
tx(() => {
run('UPDATE users SET totp_secret = NULL, totp_pending = NULL, totp_pending_at = NULL, totp_enabled_at = NULL, totp_last_step = 0, mfa_fails = 0, mfa_locked_until = 0, mfa_lock_level = 0 WHERE id = ?', user.id);
run('DELETE FROM totp_recovery WHERE user_id = ?', user.id);
run('DELETE FROM sessions WHERE user_id = ? AND mfa_ok = 0', user.id);
});
audit({ userId: null, action: 'mfa_reset', target: email, detail: { by: 'server-admin' } });
console.log(`${email} 의 2단계 인증을 껐습니다. 다시 로그인하면 Google 로그인만으로 들어옵니다.`);