Switch auth to plain-text password env var (remove bcrypt)
- Replace ADMIN_PASSWORD_HASH with ADMIN_PASSWORD in auth route and docker-compose - Remove bcryptjs / @types/bcryptjs dependencies - Delete scripts/hashPassword.ts (no longer needed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { Router, Request, Response, NextFunction } from 'express';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { AppError, ok } from '../types/index';
|
||||
import { authMiddleware } from '../middleware/authMiddleware';
|
||||
@@ -13,7 +12,7 @@ const COOKIE_OPTS = {
|
||||
path: '/',
|
||||
};
|
||||
|
||||
authRouter.post('/login', async (req: Request, res: Response, next: NextFunction) => {
|
||||
authRouter.post('/login', (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { username, password } = req.body as { username?: string; password?: string };
|
||||
|
||||
@@ -22,17 +21,13 @@ authRouter.post('/login', async (req: Request, res: Response, next: NextFunction
|
||||
}
|
||||
|
||||
const adminUsername = process.env.ADMIN_USERNAME;
|
||||
const adminHash = process.env.ADMIN_PASSWORD_HASH;
|
||||
const adminPassword = process.env.ADMIN_PASSWORD;
|
||||
|
||||
if (!adminUsername || !adminHash) {
|
||||
if (!adminUsername || !adminPassword) {
|
||||
throw new AppError('Server not configured: admin credentials missing', 500, 'CONFIG_ERROR');
|
||||
}
|
||||
|
||||
const usernameMatch = username === adminUsername;
|
||||
// Always run bcrypt to prevent timing attacks even if username is wrong
|
||||
const passwordMatch = await bcrypt.compare(password, adminHash);
|
||||
|
||||
if (!usernameMatch || !passwordMatch) {
|
||||
if (username !== adminUsername || password !== adminPassword) {
|
||||
throw new AppError('Invalid username or password', 401, 'INVALID_CREDENTIALS');
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,15 @@ modulesRouter.delete('/:id', async (req: Request, res: Response, next: NextFunct
|
||||
}
|
||||
});
|
||||
|
||||
modulesRouter.post('/:id/move', async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { rackId, uPosition } = req.body as { rackId: string; uPosition: number };
|
||||
res.json(ok(await moduleService.moveModule(req.params.id, rackId, uPosition)));
|
||||
} catch (e) {
|
||||
next(e);
|
||||
}
|
||||
});
|
||||
|
||||
modulesRouter.get('/:id/ports', async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
res.json(ok(await moduleService.getModulePorts(req.params.id)));
|
||||
|
||||
@@ -135,6 +135,42 @@ export async function deleteModule(id: string) {
|
||||
return prisma.module.delete({ where: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a module to a new rack and/or U-position.
|
||||
* Ports and VLAN assignments move with the module (they're linked by moduleId).
|
||||
*/
|
||||
export async function moveModule(
|
||||
id: string,
|
||||
targetRackId: string,
|
||||
targetUPosition: number
|
||||
) {
|
||||
const existing = await prisma.module.findUnique({ where: { id } });
|
||||
if (!existing) throw new AppError('Module not found', 404, 'NOT_FOUND');
|
||||
|
||||
const targetRack = await prisma.rack.findUnique({ where: { id: targetRackId } });
|
||||
if (!targetRack) throw new AppError('Target rack not found', 404, 'NOT_FOUND');
|
||||
|
||||
if (targetUPosition < 1 || targetUPosition + existing.uSize - 1 > targetRack.totalU) {
|
||||
throw new AppError(
|
||||
`Module does not fit within target rack (U1–U${targetRack.totalU})`,
|
||||
400,
|
||||
'OUT_OF_BOUNDS'
|
||||
);
|
||||
}
|
||||
|
||||
// Collision check in target rack, excluding self (handles same-rack moves)
|
||||
const excludeInTarget = targetRackId === existing.rackId ? id : undefined;
|
||||
if (await hasCollision(targetRackId, targetUPosition, existing.uSize, excludeInTarget)) {
|
||||
throw new AppError('U-slot collision in target rack', 409, 'COLLISION');
|
||||
}
|
||||
|
||||
return prisma.module.update({
|
||||
where: { id },
|
||||
data: { rackId: targetRackId, uPosition: targetUPosition },
|
||||
include: moduleInclude,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getModulePorts(id: string) {
|
||||
const existing = await prisma.module.findUnique({ where: { id } });
|
||||
if (!existing) throw new AppError('Module not found', 404, 'NOT_FOUND');
|
||||
|
||||
Reference in New Issue
Block a user