Initial commit baby!

This commit is contained in:
Rich Teslow
2026-04-13 18:15:41 -07:00
parent 10e6227931
commit 6b0fc9fdf1
99 changed files with 34064 additions and 3 deletions
+58
View File
@@ -0,0 +1,58 @@
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
export interface AuthPayload {
userId: number;
username: string;
role: string;
}
declare global {
namespace Express {
interface Request {
user?: AuthPayload;
}
}
}
const JWT_SECRET = process.env.JWT_SECRET || 'changeme';
export function signToken(payload: AuthPayload): string {
return jwt.sign(payload, JWT_SECRET, { expiresIn: '24h' });
}
export function verifyToken(token: string): AuthPayload {
return jwt.verify(token, JWT_SECRET) as AuthPayload;
}
export function requireAuth(req: Request, res: Response, next: NextFunction): void {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
res.status(401).json({ error: 'No token provided' });
return;
}
const token = authHeader.slice(7);
try {
req.user = verifyToken(token);
next();
} catch {
res.status(401).json({ error: 'Invalid or expired token' });
}
}
export function requireAdmin(req: Request, res: Response, next: NextFunction): void {
if (!req.user || req.user.role !== 'admin') {
res.status(403).json({ error: 'Admin access required' });
return;
}
next();
}
export function requireWrite(req: Request, res: Response, next: NextFunction): void {
if (!req.user || req.user.role === 'viewer') {
res.status(403).json({ error: 'Write access denied for viewer role' });
return;
}
next();
}
+18
View File
@@ -0,0 +1,18 @@
import { Request, Response, NextFunction } from 'express';
export function errorHandler(
err: Error,
req: Request,
res: Response,
_next: NextFunction
): void {
console.error(`[${req.method} ${req.path}]`, err.message);
if (res.headersSent) return;
const status = (err as { status?: number }).status || 500;
res.status(status).json({
error: err.message || 'Internal server error',
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
});
}