mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-19 14:57:20 +00:00
Introduces authentication via JWT, session management with CSRF protection, and new admin routes for managing users, projects, and monitoring security. Enhances dashboard and home pages with dynamic metrics fetched from the backend. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 279f1558-c0e3-40e4-8217-be7e9f4c6eca Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: dcd55177-c240-4288-8fc0-652032c758f2 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/b984cb14-1d19-4944-922b-bc79e821ed35/279f1558-c0e3-40e4-8217-be7e9f4c6eca/2riq6Ir Replit-Helium-Checkpoint-Created: true
190 lines
5.1 KiB
TypeScript
190 lines
5.1 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";
|
|
|
|
// Extend session type
|
|
declare module 'express-session' {
|
|
interface SessionData {
|
|
userId?: string;
|
|
isAdmin?: boolean;
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
|
|
export async function registerRoutes(
|
|
httpServer: Server,
|
|
app: Express
|
|
): Promise<Server> {
|
|
|
|
// ========== AUTH ROUTES ==========
|
|
|
|
// Login
|
|
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" });
|
|
}
|
|
|
|
// Regenerate session on login to prevent session fixation
|
|
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;
|
|
|
|
res.json({
|
|
success: true,
|
|
user: {
|
|
id: user.id,
|
|
username: user.username,
|
|
isAdmin: user.is_admin
|
|
}
|
|
});
|
|
});
|
|
} catch (err: any) {
|
|
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 });
|
|
}
|
|
});
|
|
|
|
return httpServer;
|
|
}
|