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
This commit is contained in:
26
backend/migrations/add_session_impersonation.js
Normal file
26
backend/migrations/add_session_impersonation.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// Migration: Add impersonate_user_id column to sessions table
|
||||
// Allows Admin users to temporarily view the app as another user.
|
||||
// When set, requireAuth() overrides req.user with the target user's identity.
|
||||
|
||||
const pool = require('../db');
|
||||
|
||||
async function run() {
|
||||
console.log('[Migration] add_session_impersonation: starting...');
|
||||
|
||||
// Add impersonate_user_id column (nullable FK to users)
|
||||
await pool.query(`
|
||||
ALTER TABLE sessions
|
||||
ADD COLUMN IF NOT EXISTS impersonate_user_id INTEGER REFERENCES users(id) ON DELETE SET NULL
|
||||
`);
|
||||
|
||||
console.log('[Migration] add_session_impersonation: column added.');
|
||||
console.log('[Migration] add_session_impersonation: done.');
|
||||
await pool.end();
|
||||
}
|
||||
|
||||
// Run directly if invoked as a script
|
||||
if (require.main === module) {
|
||||
run().catch(err => { console.error(err); process.exit(1); });
|
||||
}
|
||||
|
||||
module.exports = run;
|
||||
Reference in New Issue
Block a user