feat: implement comprehensive admin functionality
- Add admin role system with role and isAdmin fields to users table - Create admin_actions audit log table for tracking all admin operations - Implement admin CLI tool for user management (create, promote, demote, list, check) - Add admin authentication with role-based access control - Create admin service layer with system statistics and user management - Implement user impersonation system with proper security checks - Add admin API endpoints for user management and system statistics - Create admin dashboard UI with overview, users, and action logs - Fix admin stats endpoint and user deletion with proper foreign key handling - Add admin link to navigation bar for admin users Database: - Add role and isAdmin columns to users table - Create admin_actions table for audit trail - Migration script: add-admin-functionality.js CLI: - src/backend/scripts/admin-cli.js - Admin user management tool Backend: - src/backend/services/admin.service.js - Admin business logic - Updated auth.service.js with admin helper functions - Enhanced index.js with admin routes and middleware - Export sqlite connection from config for raw SQL operations Frontend: - src/frontend/src/routes/admin/+page.svelte - Admin dashboard - Updated api.js with adminAPI functions - Added Admin link to navigation bar Security: - Admin-only endpoints with role verification - Audit logging for all admin actions - Impersonation with 1-hour token expiration - Foreign key constraint handling for user deletion - Cannot delete self or other admins - Last admin protection
This commit is contained in:
103
src/backend/migrations/add-admin-functionality.js
Normal file
103
src/backend/migrations/add-admin-functionality.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Migration: Add admin functionality to users table and create admin_actions table
|
||||
*
|
||||
* This script adds role-based access control (RBAC) for admin functionality:
|
||||
* - Adds 'role' and 'isAdmin' columns to users table
|
||||
* - Creates admin_actions table for audit logging
|
||||
* - Adds indexes for performance
|
||||
*/
|
||||
|
||||
import Database from 'bun:sqlite';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
// ES module equivalent of __dirname
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const dbPath = join(__dirname, '../award.db');
|
||||
const sqlite = new Database(dbPath);
|
||||
|
||||
async function migrate() {
|
||||
console.log('Starting migration: Add admin functionality...');
|
||||
|
||||
try {
|
||||
// Check if role column already exists in users table
|
||||
const columnExists = sqlite.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM pragma_table_info('users')
|
||||
WHERE name = 'role'
|
||||
`).get();
|
||||
|
||||
if (columnExists.count > 0) {
|
||||
console.log('Admin columns already exist in users table. Skipping...');
|
||||
} else {
|
||||
// Add role column to users table
|
||||
sqlite.exec(`
|
||||
ALTER TABLE users
|
||||
ADD COLUMN role TEXT NOT NULL DEFAULT 'user'
|
||||
`);
|
||||
|
||||
// Add isAdmin column to users table
|
||||
sqlite.exec(`
|
||||
ALTER TABLE users
|
||||
ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0
|
||||
`);
|
||||
|
||||
console.log('Added role and isAdmin columns to users table');
|
||||
}
|
||||
|
||||
// Check if admin_actions table already exists
|
||||
const tableExists = sqlite.query(`
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='admin_actions'
|
||||
`).get();
|
||||
|
||||
if (tableExists) {
|
||||
console.log('Table admin_actions already exists. Skipping...');
|
||||
} else {
|
||||
// Create admin_actions table
|
||||
sqlite.exec(`
|
||||
CREATE TABLE admin_actions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
admin_id INTEGER NOT NULL,
|
||||
action_type TEXT NOT NULL,
|
||||
target_user_id INTEGER,
|
||||
details TEXT,
|
||||
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
|
||||
FOREIGN KEY (admin_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (target_user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||
)
|
||||
`);
|
||||
|
||||
// Create indexes for admin_actions
|
||||
sqlite.exec(`
|
||||
CREATE INDEX idx_admin_actions_admin_id ON admin_actions(admin_id)
|
||||
`);
|
||||
|
||||
sqlite.exec(`
|
||||
CREATE INDEX idx_admin_actions_action_type ON admin_actions(action_type)
|
||||
`);
|
||||
|
||||
sqlite.exec(`
|
||||
CREATE INDEX idx_admin_actions_created_at ON admin_actions(created_at)
|
||||
`);
|
||||
|
||||
console.log('Created admin_actions table with indexes');
|
||||
}
|
||||
|
||||
console.log('Migration complete! Admin functionality added to database.');
|
||||
} catch (error) {
|
||||
console.error('Migration failed:', error);
|
||||
sqlite.close();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
sqlite.close();
|
||||
}
|
||||
|
||||
// Run migration
|
||||
migrate().then(() => {
|
||||
console.log('Migration script completed successfully');
|
||||
process.exit(0);
|
||||
});
|
||||
Reference in New Issue
Block a user