310 lines
6.7 KiB
JavaScript
310 lines
6.7 KiB
JavaScript
import express from "express";
|
|
import { isAdmin } from "../middleware/auth.js";
|
|
|
|
const router = express.Router();
|
|
|
|
// Apply admin check to all routes
|
|
router.use(isAdmin);
|
|
|
|
// In-memory stores (replace with database in production)
|
|
const activityLogs = [
|
|
{
|
|
id: "1",
|
|
action: "User login",
|
|
user: "Pastor John",
|
|
timestamp: new Date().toISOString(),
|
|
ip: "192.168.1.100",
|
|
status: "success",
|
|
},
|
|
{
|
|
id: "2",
|
|
action: "Song created",
|
|
user: "Sarah Miller",
|
|
timestamp: new Date().toISOString(),
|
|
details: "New song: Blessed Be Your Name",
|
|
status: "success",
|
|
},
|
|
{
|
|
id: "3",
|
|
action: "Failed login attempt",
|
|
user: "unknown@test.com",
|
|
timestamp: new Date().toISOString(),
|
|
ip: "203.45.67.89",
|
|
status: "failed",
|
|
},
|
|
];
|
|
|
|
const users = new Map([
|
|
[
|
|
"1",
|
|
{
|
|
id: "1",
|
|
name: "Pastor John",
|
|
email: "john@church.org",
|
|
role: "admin",
|
|
status: "active",
|
|
lastLogin: new Date().toISOString(),
|
|
},
|
|
],
|
|
[
|
|
"2",
|
|
{
|
|
id: "2",
|
|
name: "Sarah Miller",
|
|
email: "sarah@church.org",
|
|
role: "leader",
|
|
status: "active",
|
|
lastLogin: new Date().toISOString(),
|
|
},
|
|
],
|
|
]);
|
|
|
|
const devices = new Map([
|
|
[
|
|
"1",
|
|
{
|
|
id: "1",
|
|
name: "iPad Pro - Worship",
|
|
userId: "2",
|
|
type: "tablet",
|
|
lastActive: new Date().toISOString(),
|
|
status: "online",
|
|
},
|
|
],
|
|
[
|
|
"2",
|
|
{
|
|
id: "2",
|
|
name: "MacBook Pro",
|
|
userId: "1",
|
|
type: "desktop",
|
|
lastActive: new Date().toISOString(),
|
|
status: "online",
|
|
},
|
|
],
|
|
]);
|
|
|
|
// Dashboard stats
|
|
router.get("/stats", (req, res) => {
|
|
res.json({
|
|
totalUsers: users.size,
|
|
activeDevices: Array.from(devices.values()).filter(
|
|
(d) => d.status === "online",
|
|
).length,
|
|
actionsToday: activityLogs.filter((log) => {
|
|
const logDate = new Date(log.timestamp).toDateString();
|
|
return logDate === new Date().toDateString();
|
|
}).length,
|
|
securityAlerts: activityLogs.filter((log) => log.status === "failed")
|
|
.length,
|
|
});
|
|
});
|
|
|
|
// Get all users
|
|
router.get("/users", (req, res) => {
|
|
const result = Array.from(users.values());
|
|
res.json({ users: result, total: result.length });
|
|
});
|
|
|
|
// Get single user
|
|
router.get("/users/:id", (req, res) => {
|
|
const user = users.get(req.params.id);
|
|
if (!user) {
|
|
return res.status(404).json({ error: "User not found" });
|
|
}
|
|
res.json({ user });
|
|
});
|
|
|
|
// Create user
|
|
router.post("/users", (req, res) => {
|
|
const { name, email, role } = req.body;
|
|
|
|
if (!name || !email) {
|
|
return res.status(400).json({ error: "Name and email are required" });
|
|
}
|
|
|
|
const user = {
|
|
id: Date.now().toString(),
|
|
name,
|
|
email,
|
|
role: role || "volunteer",
|
|
status: "active",
|
|
lastLogin: null,
|
|
createdAt: new Date().toISOString(),
|
|
};
|
|
|
|
users.set(user.id, user);
|
|
|
|
// Log activity
|
|
activityLogs.push({
|
|
id: Date.now().toString(),
|
|
action: "User created",
|
|
user: req.user.name,
|
|
timestamp: new Date().toISOString(),
|
|
details: `Created user: ${name}`,
|
|
status: "success",
|
|
});
|
|
|
|
res.status(201).json({ message: "User created", user });
|
|
});
|
|
|
|
// Update user
|
|
router.put("/users/:id", (req, res) => {
|
|
const user = users.get(req.params.id);
|
|
if (!user) {
|
|
return res.status(404).json({ error: "User not found" });
|
|
}
|
|
|
|
const { name, email, role, status } = req.body;
|
|
|
|
const updatedUser = {
|
|
...user,
|
|
name: name || user.name,
|
|
email: email || user.email,
|
|
role: role || user.role,
|
|
status: status || user.status,
|
|
};
|
|
|
|
users.set(user.id, updatedUser);
|
|
|
|
res.json({ message: "User updated", user: updatedUser });
|
|
});
|
|
|
|
// Delete user
|
|
router.delete("/users/:id", (req, res) => {
|
|
const user = users.get(req.params.id);
|
|
if (!user) {
|
|
return res.status(404).json({ error: "User not found" });
|
|
}
|
|
|
|
if (user.role === "admin") {
|
|
return res.status(403).json({ error: "Cannot delete admin user" });
|
|
}
|
|
|
|
users.delete(req.params.id);
|
|
|
|
res.json({ message: "User deleted" });
|
|
});
|
|
|
|
// Get devices
|
|
router.get("/devices", (req, res) => {
|
|
const result = Array.from(devices.values()).map((device) => ({
|
|
...device,
|
|
user: users.get(device.userId)?.name || "Unknown",
|
|
}));
|
|
res.json({ devices: result, total: result.length });
|
|
});
|
|
|
|
// Revoke device
|
|
router.delete("/devices/:id", (req, res) => {
|
|
const device = devices.get(req.params.id);
|
|
if (!device) {
|
|
return res.status(404).json({ error: "Device not found" });
|
|
}
|
|
|
|
devices.delete(req.params.id);
|
|
|
|
res.json({ message: "Device revoked" });
|
|
});
|
|
|
|
// Get activity logs
|
|
router.get("/logs", (req, res) => {
|
|
const { action, status, limit = 50 } = req.query;
|
|
|
|
let result = [...activityLogs];
|
|
|
|
if (action) {
|
|
result = result.filter((log) =>
|
|
log.action.toLowerCase().includes(action.toLowerCase()),
|
|
);
|
|
}
|
|
|
|
if (status) {
|
|
result = result.filter((log) => log.status === status);
|
|
}
|
|
|
|
// Sort by timestamp (newest first)
|
|
result.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
|
|
|
|
// Limit results
|
|
result = result.slice(0, parseInt(limit));
|
|
|
|
res.json({ logs: result, total: result.length });
|
|
});
|
|
|
|
// Get roles
|
|
router.get("/roles", (req, res) => {
|
|
const roles = [
|
|
{
|
|
id: "admin",
|
|
name: "Administrator",
|
|
description: "Full access to all features",
|
|
permissions: ["all"],
|
|
userCount: Array.from(users.values()).filter((u) => u.role === "admin")
|
|
.length,
|
|
},
|
|
{
|
|
id: "leader",
|
|
name: "Worship Leader",
|
|
description: "Manage songs and worship lists",
|
|
permissions: [
|
|
"songs.read",
|
|
"songs.write",
|
|
"lists.read",
|
|
"lists.write",
|
|
"profiles.read",
|
|
],
|
|
userCount: Array.from(users.values()).filter((u) => u.role === "leader")
|
|
.length,
|
|
},
|
|
{
|
|
id: "tech",
|
|
name: "Tech Team",
|
|
description: "View and present songs",
|
|
permissions: ["songs.read", "lists.read"],
|
|
userCount: Array.from(users.values()).filter((u) => u.role === "tech")
|
|
.length,
|
|
},
|
|
{
|
|
id: "volunteer",
|
|
name: "Volunteer",
|
|
description: "Basic access",
|
|
permissions: ["songs.read"],
|
|
userCount: Array.from(users.values()).filter(
|
|
(u) => u.role === "volunteer",
|
|
).length,
|
|
},
|
|
];
|
|
|
|
res.json({ roles });
|
|
});
|
|
|
|
// Security settings
|
|
router.get("/security", (req, res) => {
|
|
res.json({
|
|
twoFactorRequired: false,
|
|
sessionTimeout: 3600, // 1 hour
|
|
passwordMinLength: 8,
|
|
passwordRequireNumber: true,
|
|
ipWhitelist: [],
|
|
failedLoginAlerts: 3,
|
|
});
|
|
});
|
|
|
|
router.put("/security", (req, res) => {
|
|
// Update security settings
|
|
const {
|
|
twoFactorRequired,
|
|
sessionTimeout,
|
|
passwordMinLength,
|
|
passwordRequireNumber,
|
|
ipWhitelist,
|
|
} = req.body;
|
|
|
|
// In a real app, save to database
|
|
|
|
res.json({ message: "Security settings updated" });
|
|
});
|
|
|
|
export default router;
|