File: /var/www/indoadvisory_new/web/webapp/routes/admin.js
const express = require('express');
const { db } = require('../config/database');
const { logAuditEvent } = require('../middleware/auth');
const router = express.Router();
// Admin Dashboard
router.get('/', async (req, res) => {
try {
// Get dashboard statistics
const stats = await Promise.all([
db.query('SELECT COUNT(*) as total FROM team_members WHERE is_active = true'),
db.query('SELECT COUNT(*) as total FROM clients WHERE is_active = true'),
db.query('SELECT COUNT(*) as total FROM articles WHERE is_published = true'),
db.query('SELECT COUNT(*) as total FROM inquiries WHERE status = $1', ['new']),
db.query(`
SELECT COUNT(*) as total
FROM audit_logs
WHERE created_at >= NOW() - INTERVAL '24 hours'
`),
db.query(`
SELECT action, COUNT(*) as count
FROM audit_logs
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY action
ORDER BY count DESC
LIMIT 5
`)
]);
// Recent activities
const recentActivities = await db.query(`
SELECT al.action, al.resource_type, al.created_at, u.name as user_name
FROM audit_logs al
LEFT JOIN users u ON al.user_id = u.id
ORDER BY al.created_at DESC
LIMIT 10
`);
// Recent inquiries
const recentInquiries = await db.query(`
SELECT id, name, email, subject, created_at, status
FROM inquiries
ORDER BY created_at DESC
LIMIT 5
`);
const dashboardStats = {
totalTeamMembers: parseInt(stats[0].rows[0].total),
totalClients: parseInt(stats[1].rows[0].total),
totalArticles: parseInt(stats[2].rows[0].total),
newInquiries: parseInt(stats[3].rows[0].total),
dailyActivities: parseInt(stats[4].rows[0].total),
topActions: stats[5].rows,
recentActivities: recentActivities.rows,
recentInquiries: recentInquiries.rows
};
res.render('admin/dashboard', {
title: res.locals.__('admin_dashboard'),
stats: dashboardStats
});
} catch (error) {
console.error('Dashboard error:', error);
req.flash('error', 'Error loading dashboard');
res.render('admin/dashboard', {
title: res.locals.__('admin_dashboard'),
stats: {
totalTeamMembers: 0,
totalClients: 0,
totalArticles: 0,
newInquiries: 0,
dailyActivities: 0,
topActions: [],
recentActivities: [],
recentInquiries: []
}
});
}
});
// Content Management
router.get('/content', async (req, res) => {
try {
// Get all settings for content management
const settings = await db.query(`
SELECT key, value_en, value_id, description, is_public
FROM settings
ORDER BY key
`);
res.render('admin/content', {
title: res.locals.__('admin_content'),
settings: settings.rows
});
} catch (error) {
console.error('Content management error:', error);
req.flash('error', 'Error loading content settings');
res.redirect('/admin');
}
});
// Update content settings
router.post('/content/:key', async (req, res) => {
try {
const { key } = req.params;
const { value_en, value_id, description, is_public } = req.body;
await db.query(`
UPDATE settings
SET value_en = $1, value_id = $2, description = $3, is_public = $4, updated_at = CURRENT_TIMESTAMP
WHERE key = $5
`, [value_en, value_id, description, is_public === 'on', key]);
await logAuditEvent(req.user.id, 'content_updated', 'setting', key, req, { key });
req.flash('success', 'Content updated successfully');
res.redirect('/admin/content');
} catch (error) {
console.error('Content update error:', error);
req.flash('error', 'Error updating content');
res.redirect('/admin/content');
}
});
// Inquiries Management
router.get('/inquiries', async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const offset = (page - 1) * limit;
const status = req.query.status || 'all';
let whereClause = '';
let params = [];
if (status !== 'all') {
whereClause = 'WHERE status = $1';
params.push(status);
params.push(limit, offset);
} else {
params.push(limit, offset);
}
const inquiries = await db.query(`
SELECT i.*, u.name as assigned_user_name
FROM inquiries i
LEFT JOIN users u ON i.assigned_to = u.id
${whereClause}
ORDER BY i.created_at DESC
LIMIT $${params.length - 1} OFFSET $${params.length}
`, params);
// Get total count for pagination
const countResult = await db.query(`
SELECT COUNT(*) as total FROM inquiries ${whereClause}
`, status !== 'all' ? [status] : []);
const totalInquiries = parseInt(countResult.rows[0].total);
const totalPages = Math.ceil(totalInquiries / limit);
res.render('admin/inquiries', {
title: res.locals.__('admin_inquiries'),
inquiries: inquiries.rows,
currentPage: page,
totalPages: totalPages,
currentStatus: status
});
} catch (error) {
console.error('Inquiries error:', error);
req.flash('error', 'Error loading inquiries');
res.redirect('/admin');
}
});
// Update inquiry status
router.post('/inquiries/:id/status', async (req, res) => {
try {
const { id } = req.params;
const { status, notes } = req.body;
await db.query(`
UPDATE inquiries
SET status = $1, notes = $2, assigned_to = $3, updated_at = CURRENT_TIMESTAMP
WHERE id = $4
`, [status, notes, req.user.id, id]);
await logAuditEvent(req.user.id, 'inquiry_updated', 'inquiry', id, req, { status, notes });
req.flash('success', 'Inquiry updated successfully');
res.redirect('/admin/inquiries');
} catch (error) {
console.error('Inquiry update error:', error);
req.flash('error', 'Error updating inquiry');
res.redirect('/admin/inquiries');
}
});
// Security & Audit Logs
router.get('/security', async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = 50;
const offset = (page - 1) * limit;
const logs = await db.query(`
SELECT al.*, u.name as user_name, u.email as user_email
FROM audit_logs al
LEFT JOIN users u ON al.user_id = u.id
ORDER BY al.created_at DESC
LIMIT $1 OFFSET $2
`, [limit, offset]);
// Get total count for pagination
const countResult = await db.query('SELECT COUNT(*) as total FROM audit_logs');
const totalLogs = parseInt(countResult.rows[0].total);
const totalPages = Math.ceil(totalLogs / limit);
// Get security stats
const securityStats = await db.query(`
SELECT
COUNT(CASE WHEN action LIKE '%login%' THEN 1 END) as login_attempts,
COUNT(CASE WHEN action = 'login_failed' THEN 1 END) as failed_logins,
COUNT(CASE WHEN action = 'login_success' THEN 1 END) as successful_logins,
COUNT(DISTINCT ip_address) as unique_ips,
COUNT(*) as total_activities
FROM audit_logs
WHERE created_at >= NOW() - INTERVAL '24 hours'
`);
res.render('admin/security', {
title: res.locals.__('admin_security'),
logs: logs.rows,
currentPage: page,
totalPages: totalPages,
stats: securityStats.rows[0]
});
} catch (error) {
console.error('Security logs error:', error);
req.flash('error', 'Error loading security logs');
res.redirect('/admin');
}
});
// Users Management
router.get('/users', async (req, res) => {
try {
const users = await db.query(`
SELECT id, email, name, role, is_active, last_login, created_at,
failed_login_attempts, locked_until
FROM users
ORDER BY created_at DESC
`);
res.render('admin/users', {
title: res.locals.__('admin_users'),
users: users.rows
});
} catch (error) {
console.error('Users management error:', error);
req.flash('error', 'Error loading users');
res.redirect('/admin');
}
});
// Toggle user active status
router.post('/users/:id/toggle', async (req, res) => {
try {
const { id } = req.params;
// Prevent users from deactivating themselves
if (id === req.user.id) {
req.flash('error', 'You cannot deactivate your own account');
return res.redirect('/admin/users');
}
const result = await db.query(`
UPDATE users
SET is_active = NOT is_active, updated_at = CURRENT_TIMESTAMP
WHERE id = $1
RETURNING is_active
`, [id]);
const newStatus = result.rows[0].is_active ? 'activated' : 'deactivated';
await logAuditEvent(req.user.id, `user_${newStatus}`, 'user', id, req);
req.flash('success', `User ${newStatus} successfully`);
res.redirect('/admin/users');
} catch (error) {
console.error('User toggle error:', error);
req.flash('error', 'Error updating user status');
res.redirect('/admin/users');
}
});
module.exports = router;