Files
cve-dashboard/backend/migrations/run-all.js
Jordan Ramos 8c789ce765 Add View As (impersonation) feature for Admin users
Allow Admin users to temporarily view the app as another user to verify
permissions and team scoping without switching accounts.

Backend:
- Migration: add impersonate_user_id column to sessions table
- requireAuth(): when impersonation is active, override req.user with
  target user's identity; store real admin identity in req.realUser
- POST /api/auth/impersonate: start impersonation (Admin only, cannot
  impersonate self or other Admins)
- POST /api/auth/stop-impersonate: end impersonation, revert to real user
- GET /api/auth/me: returns impersonating flag and realUser when active
- Audit logging on impersonate start/stop

Frontend:
- AuthContext: add impersonating, realUser state; startImpersonation()
  and stopImpersonation() helpers
- ImpersonationBanner: fixed amber banner showing target user identity
  with Exit button
- UserManagement: Eye icon button on each non-Admin user row to start
  View As (visible only to Admin, hidden for self and other Admins)
- App.js: mount ImpersonationBanner at top of authenticated view
2026-06-24 12:57:57 -06:00

71 lines
2.2 KiB
JavaScript

#!/usr/bin/env node
// Run all Postgres-compatible migrations in order.
// Each migration is idempotent (safe to re-run).
// Used by CI/CD pipeline during deploy to ensure schema is up to date.
//
// Usage: cd backend && node migrations/run-all.js
const { execSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const MIGRATIONS_DIR = __dirname;
// Only run migrations that use the Postgres pool (not legacy SQLite ones).
// Add new migrations to this list as they're created.
const POSTGRES_MIGRATIONS = [
'add_decom_workflow_type.js',
'add_fp_submissions_dismissed.js',
'add_fp_submissions_requeued_at.js',
'add_vcl_reporting_columns.js',
'add_vcl_vertical_metadata.js',
'add_vcl_multi_vertical.js',
'add_compliance_item_history.js',
'add_jira_sync_columns_pg.js',
'add_flexible_jira_ticket_creation.js',
'add_multi_item_jira_ticket.js',
'drop_jira_status_check_constraint.js',
'add_compliance_history_metric_id.js',
'add_archer_templates_table.js',
'add_queue_remediation_notes_table.js',
'add_remediate_workflow_type.js',
'add_notifications_table.js',
'add_ivanti_findings_ipv6_columns.js',
'add_user_ivanti_identity.js',
'add_atlas_known_column.js',
'add_session_impersonation.js',
];
async function runAll() {
console.log(`[Migrations] Running ${POSTGRES_MIGRATIONS.length} Postgres migration(s)...`);
let succeeded = 0;
let failed = 0;
for (const file of POSTGRES_MIGRATIONS) {
const fullPath = path.join(MIGRATIONS_DIR, file);
if (!fs.existsSync(fullPath)) {
console.error(` [FAIL] ${file}: file not found`);
failed++;
continue;
}
try {
console.log(` [run] ${file}`);
execSync(`node ${fullPath}`, {
cwd: path.join(MIGRATIONS_DIR, '..'),
stdio: 'inherit',
timeout: 30000,
});
succeeded++;
} catch (err) {
console.error(` [FAIL] ${file}: exit code ${err.status}`);
failed++;
}
}
console.log(`[Migrations] Done: ${succeeded} applied, ${failed} failed`);
if (failed > 0) process.exit(1);
}
runAll();