Initial commit - Church Music Database
This commit is contained in:
309
new-site/backend/api/admin.js
Normal file
309
new-site/backend/api/admin.js
Normal file
@@ -0,0 +1,309 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user