Initial scaffold: full-stack RackMapper application
Complete project scaffold with working auth, REST API, Prisma/SQLite schema, Docker config, and React frontend for both Rack Planner and Service Mapper modules. Both server and client pass TypeScript strict mode with zero errors. Initial migration applied. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
26
server/middleware/authMiddleware.ts
Normal file
26
server/middleware/authMiddleware.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { AppError, AuthenticatedRequest } from '../types/index';
|
||||
|
||||
export function authMiddleware(req: Request, res: Response, next: NextFunction): void {
|
||||
const token = (req.cookies as Record<string, string | undefined>)?.token;
|
||||
|
||||
if (!token) {
|
||||
next(new AppError('Unauthorized', 401, 'NO_TOKEN'));
|
||||
return;
|
||||
}
|
||||
|
||||
const secret = process.env.JWT_SECRET;
|
||||
if (!secret) {
|
||||
next(new AppError('Server misconfiguration: JWT_SECRET not set', 500, 'CONFIG_ERROR'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = jwt.verify(token, secret) as { sub: string };
|
||||
(req as AuthenticatedRequest).user = { sub: payload.sub };
|
||||
next();
|
||||
} catch {
|
||||
next(new AppError('Invalid or expired session', 401, 'INVALID_TOKEN'));
|
||||
}
|
||||
}
|
||||
22
server/middleware/errorHandler.ts
Normal file
22
server/middleware/errorHandler.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { AppError, err } from '../types/index';
|
||||
|
||||
export function errorHandler(
|
||||
error: Error,
|
||||
_req: Request,
|
||||
res: Response,
|
||||
_next: NextFunction
|
||||
): void {
|
||||
const statusCode = error instanceof AppError ? error.statusCode : 500;
|
||||
const code = error instanceof AppError ? error.code : 'INTERNAL_ERROR';
|
||||
const message =
|
||||
process.env.NODE_ENV === 'production' && statusCode === 500
|
||||
? 'Internal server error'
|
||||
: error.message;
|
||||
|
||||
if (statusCode === 500 && process.env.NODE_ENV !== 'production') {
|
||||
console.error('[ErrorHandler]', error);
|
||||
}
|
||||
|
||||
res.status(statusCode).json(err(message, code ? { code } : undefined));
|
||||
}
|
||||
Reference in New Issue
Block a user