chore(backend): add dev helper to provision a static-OTP mitra login
setup-test-mitra-otp.mjs adds a phone+mitra-scoped entry to the app_config.test_otp_bypass allowlist and ensures an ACTIVE mitra row (createMitra defaults inactive -> 403). Dev/QA convenience; the bypass is checked before Fazpass in requestOtp so it short-circuits even when FAZPASS_ENABLED=true. Idempotent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
85
backend/scripts/setup-test-mitra-otp.mjs
Normal file
85
backend/scripts/setup-test-mitra-otp.mjs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// Dev helper: provision a STATIC-OTP mitra login for local/QA testing.
|
||||||
|
//
|
||||||
|
// Uses the existing test-OTP-bypass allowlist (app_config.test_otp_bypass),
|
||||||
|
// the same mechanism shipped for Apple-reviewer QA. It:
|
||||||
|
// 1. ensures an ACTIVE mitra exists with the test phone (mitras default to
|
||||||
|
// is_active=false, which the mitra verify route rejects with 403),
|
||||||
|
// 2. adds a phone-scoped, mitra-scoped static OTP entry (bcrypt-hashed),
|
||||||
|
// 3. flips the global bypass kill-switch on.
|
||||||
|
//
|
||||||
|
// After running, log into the mitra app with PHONE + OTP below — no Fazpass,
|
||||||
|
// no console code-reading. Re-running is idempotent.
|
||||||
|
//
|
||||||
|
// Usage (from backend/): node scripts/setup-test-mitra-otp.mjs
|
||||||
|
// Override defaults: TEST_MITRA_PHONE=+628... TEST_MITRA_OTP=123456 node scripts/setup-test-mitra-otp.mjs
|
||||||
|
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { getDb } from '../src/db/client.js'
|
||||||
|
import {
|
||||||
|
getTestOtpBypass,
|
||||||
|
addTestOtpBypassEntry,
|
||||||
|
setTestOtpBypassEnabled,
|
||||||
|
} from '../src/services/config.service.js'
|
||||||
|
|
||||||
|
const PHONE = process.env.TEST_MITRA_PHONE || '+6281200000001'
|
||||||
|
const OTP = process.env.TEST_MITRA_OTP || '123456'
|
||||||
|
const LABEL = process.env.TEST_MITRA_LABEL || 'Dev static OTP (mitra)'
|
||||||
|
const DISPLAY_NAME = process.env.TEST_MITRA_NAME || 'Test Bestie'
|
||||||
|
// Far-future expiry — the allowlist requires a future expires_at per entry.
|
||||||
|
const EXPIRES_AT = '2099-01-01T00:00:00.000Z'
|
||||||
|
|
||||||
|
const sql = getDb()
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
// 1. Ensure an ACTIVE mitra with this phone (raw SQL — avoids importing
|
||||||
|
// mitra.service, which pulls in the valkey plugin and would leave an open
|
||||||
|
// handle keeping this script alive).
|
||||||
|
const [existing] = await sql`SELECT id, is_active FROM mitras WHERE phone = ${PHONE}`
|
||||||
|
if (!existing) {
|
||||||
|
const [m] = await sql`
|
||||||
|
INSERT INTO mitras (phone, display_name, is_active)
|
||||||
|
VALUES (${PHONE}, ${DISPLAY_NAME}, true)
|
||||||
|
RETURNING id
|
||||||
|
`
|
||||||
|
console.log(` created active mitra ${m.id} (${PHONE})`)
|
||||||
|
} else if (!existing.is_active) {
|
||||||
|
await sql`UPDATE mitras SET is_active = true WHERE id = ${existing.id}`
|
||||||
|
console.log(` mitra ${existing.id} existed — activated`)
|
||||||
|
} else {
|
||||||
|
console.log(` mitra ${existing.id} already exists and active`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Add the static-OTP allowlist entry (skip if one already exists for this
|
||||||
|
// phone+mitra — addTestOtpBypassEntry throws on duplicate).
|
||||||
|
const current = await getTestOtpBypass()
|
||||||
|
const exists = current.entries.some(e => e.phone === PHONE && e.user_type === 'mitra')
|
||||||
|
if (exists) {
|
||||||
|
console.log(' bypass entry already present for this phone+mitra — leaving as is')
|
||||||
|
console.log(' (to rotate the OTP: delete the entry in CC → Settings, then re-run)')
|
||||||
|
} else {
|
||||||
|
await addTestOtpBypassEntry({
|
||||||
|
phone: PHONE,
|
||||||
|
otp: OTP,
|
||||||
|
user_type: 'mitra',
|
||||||
|
label: LABEL,
|
||||||
|
expires_at: EXPIRES_AT,
|
||||||
|
})
|
||||||
|
console.log(` added bypass entry: ${PHONE} → otp ${OTP} (mitra)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Global kill-switch ON.
|
||||||
|
await setTestOtpBypassEnabled(true)
|
||||||
|
console.log(' bypass allowlist ENABLED')
|
||||||
|
|
||||||
|
console.log('\n✅ Static mitra OTP ready:')
|
||||||
|
console.log(` phone: ${PHONE}`)
|
||||||
|
console.log(` otp: ${exists ? '(unchanged — set on a previous run)' : OTP}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(() => sql.end({ timeout: 5 }))
|
||||||
|
.catch(async (err) => {
|
||||||
|
console.error('FAILED:', err.message)
|
||||||
|
await sql.end({ timeout: 5 })
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user