AeThex-OS/server/routes.ts
sirpiglr 5f40710e82 Add new admin dashboard sections and enhance Aegis monitor functionality
Introduce new admin routes for sites, logs, and achievements, refactor Aegis monitor to display real data from alerts and auth_logs, and implement JWT token generation for authentication.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 279f1558-c0e3-40e4-8217-be7e9f4c6eca
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 48e7daad-43dd-4684-8441-ff2ea20129e1
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/b984cb14-1d19-4944-922b-bc79e821ed35/279f1558-c0e3-40e4-8217-be7e9f4c6eca/HbU8yEz
Replit-Helium-Checkpoint-Created: true
2025-12-15 23:00:05 +00:00

274 lines
7.7 KiB
TypeScript

import type { Express, Request, Response, NextFunction } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { loginSchema } from "@shared/schema";
import bcrypt from "bcrypt";
import crypto from "crypto";
// Extend session type
declare module 'express-session' {
interface SessionData {
userId?: string;
isAdmin?: boolean;
token?: string;
}
}
// Auth middleware - requires any authenticated user
function requireAuth(req: Request, res: Response, next: NextFunction) {
if (!req.session.userId) {
return res.status(401).json({ error: "Unauthorized" });
}
next();
}
// Admin middleware - requires authenticated admin user
function requireAdmin(req: Request, res: Response, next: NextFunction) {
if (!req.session.userId) {
return res.status(401).json({ error: "Unauthorized" });
}
if (!req.session.isAdmin) {
return res.status(403).json({ error: "Admin access required" });
}
next();
}
// Generate JWT-like token
function generateToken(userId: string, username: string): string {
const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString('base64url');
const payload = Buffer.from(JSON.stringify({
userId,
username,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600 // 1 hour
})).toString('base64url');
const signature = crypto.createHmac('sha256', process.env.SESSION_SECRET || 'dev-secret')
.update(`${header}.${payload}`)
.digest('base64url');
return `${header}.${payload}.${signature}`;
}
export async function registerRoutes(
httpServer: Server,
app: Express
): Promise<Server> {
// ========== AUTH ROUTES ==========
// Login - creates JWT token and stores in sessions table
app.post("/api/auth/login", async (req, res) => {
try {
const result = loginSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: "Invalid credentials" });
}
const { username, password } = result.data;
const user = await storage.getUserByUsername(username);
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}
const isValid = await bcrypt.compare(password, user.password);
if (!isValid) {
return res.status(401).json({ error: "Invalid credentials" });
}
// Generate token like your other apps
const token = generateToken(user.id, user.username);
const expiresAt = new Date(Date.now() + 3600 * 1000); // 1 hour
// Store session in sessions table (like your other apps)
await storage.createSession({
user_id: user.id,
username: user.username,
token,
expires_at: expiresAt.toISOString()
});
// Also set express session for this app
req.session.regenerate((err) => {
if (err) {
return res.status(500).json({ error: "Session error" });
}
req.session.userId = user.id;
req.session.isAdmin = user.is_admin ?? false;
req.session.token = token;
res.json({
success: true,
token,
user: {
id: user.id,
username: user.username,
isAdmin: user.is_admin
}
});
});
} catch (err: any) {
console.error('Login error:', err);
res.status(500).json({ error: err.message });
}
});
// Logout
app.post("/api/auth/logout", (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).json({ error: "Logout failed" });
}
res.clearCookie('connect.sid');
res.json({ success: true });
});
});
// Get current session
app.get("/api/auth/session", async (req, res) => {
if (!req.session.userId) {
return res.json({ authenticated: false });
}
const user = await storage.getUser(req.session.userId);
if (!user) {
return res.json({ authenticated: false });
}
res.json({
authenticated: true,
user: {
id: user.id,
username: user.username,
isAdmin: user.is_admin
}
});
});
// ========== PUBLIC API ROUTES ==========
// Get ecosystem metrics (public - for dashboard)
app.get("/api/metrics", async (req, res) => {
try {
const metrics = await storage.getMetrics();
res.json(metrics);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// ========== ADMIN-PROTECTED API ROUTES ==========
// Get all profiles (admin only)
app.get("/api/profiles", requireAdmin, async (req, res) => {
try {
const profiles = await storage.getProfiles();
res.json(profiles);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get single profile (admin only)
app.get("/api/profiles/:id", requireAdmin, async (req, res) => {
try {
const profile = await storage.getProfile(req.params.id);
if (!profile) {
return res.status(404).json({ error: "Profile not found" });
}
res.json(profile);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Update profile (admin only)
app.patch("/api/profiles/:id", requireAdmin, async (req, res) => {
try {
const profile = await storage.updateProfile(req.params.id, req.body);
if (!profile) {
return res.status(404).json({ error: "Profile not found" });
}
res.json(profile);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get all projects (admin only)
app.get("/api/projects", requireAdmin, async (req, res) => {
try {
const projects = await storage.getProjects();
res.json(projects);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get single project (admin only)
app.get("/api/projects/:id", requireAdmin, async (req, res) => {
try {
const project = await storage.getProject(req.params.id);
if (!project) {
return res.status(404).json({ error: "Project not found" });
}
res.json(project);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// ========== NEW ADMIN ROUTES ==========
// Get all aethex sites (admin only)
app.get("/api/sites", requireAdmin, async (req, res) => {
try {
const sites = await storage.getSites();
res.json(sites);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get auth logs (admin only)
app.get("/api/auth-logs", requireAdmin, async (req, res) => {
try {
const logs = await storage.getAuthLogs();
res.json(logs);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get achievements (admin only)
app.get("/api/achievements", requireAdmin, async (req, res) => {
try {
const achievements = await storage.getAchievements();
res.json(achievements);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get applications (admin only)
app.get("/api/applications", requireAdmin, async (req, res) => {
try {
const applications = await storage.getApplications();
res.json(applications);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
// Get alerts for Aegis (admin only)
app.get("/api/alerts", requireAdmin, async (req, res) => {
try {
const alerts = await storage.getAlerts();
res.json(alerts);
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
return httpServer;
}