Files
meal-tracker/server/routes/admin.js

98 lines
3.2 KiB
JavaScript

import { getDb } from '../models/db.js';
import bcrypt from 'bcryptjs';
function isAdmin(req, res, next) {
const userId = req.headers['x-user-id'];
if (!userId) {
return res.status(401).json({ error: 'Not authenticated' });
}
const db = getDb();
const user = db.prepare('SELECT username FROM users WHERE id = ?').get(userId);
if (!user || user.username !== 'admin') {
return res.status(403).json({ error: 'Admin access required' });
}
next();
}
export default function setupRoutes(app) {
// Get all users
app.get('/api/admin/users', isAdmin, (req, res) => {
const db = getDb();
const users = db.prepare('SELECT id, username, created_at FROM users ORDER BY created_at DESC').all();
res.json(users);
});
// Get all entries (admin view)
app.get('/api/admin/entries', isAdmin, (req, res) => {
const db = getDb();
const entries = db.prepare(`
SELECT e.*, u.username
FROM entries e
JOIN users u ON e.user_id = u.id
ORDER BY e.created_at DESC
LIMIT 100
`).all();
res.json(entries);
});
// Get stats
app.get('/api/admin/stats', isAdmin, (req, res) => {
const db = getDb();
const totalUsers = db.prepare('SELECT COUNT(*) as count FROM users').get().count;
const totalEntries = db.prepare('SELECT COUNT(*) as count FROM entries').get().count;
const todayEntries = db.prepare("SELECT COUNT(*) as count FROM entries WHERE date(created_at) = date('now')").get().count;
const topFoods = db.prepare(`SELECT name, COUNT(*) as count FROM entries GROUP BY name ORDER BY count DESC LIMIT 5`).all();
const todayCalories = db.prepare("SELECT COALESCE(SUM(calories), 0) as total FROM entries WHERE date(created_at) = date('now')").get().total;
res.json({ totalUsers, totalEntries, todayEntries, todayCalories, topFoods });
});
// Get activity log
app.get('/api/admin/activity', isAdmin, (req, res) => {
const db = getDb();
const limit = parseInt(req.query.limit) || 50;
const activity = db.prepare(`
SELECT al.*, u.username
FROM activity_log al
LEFT JOIN users u ON al.user_id = u.id
ORDER BY al.created_at DESC
LIMIT ?
`).all(limit);
res.json(activity);
});
// Delete user
app.delete('/api/admin/users/:id', isAdmin, (req, res) => {
const db = getDb();
const { id } = req.params;
const userId = req.headers['x-user-id'];
if (userId == id) {
return res.status(400).json({ error: 'Cannot delete yourself' });
}
db.prepare('DELETE FROM entries WHERE user_id = ?').run(id);
db.prepare('DELETE FROM activity_log WHERE user_id = ?').run(id);
db.prepare('DELETE FROM users WHERE id = ?').run(id);
res.json({ success: true });
});
// Reset password
app.post('/api/admin/users/:id/reset-password', isAdmin, (req, res) => {
const db = getDb();
const { id } = req.params;
const { password } = req.body;
const hash = bcrypt.hashSync(password, 10);
db.prepare('UPDATE users SET password = ? WHERE id = ?').run(hash, id);
db.prepare('INSERT INTO activity_log (user_id, action, details) VALUES (?, ?, ?)').run(id, 'password_reset', 'Password reset by admin');
res.json({ success: true });
});
}