feat: Fleet Forge UEM - device management, agent, remote desktop (VNC), TLS reverse proxy
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import type { Request, Response, NextFunction } from "express";
|
||||
import jwt from "jsonwebtoken";
|
||||
import type { AuthenticatedUser, Role } from "@fleetforge/shared";
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || "dev-secret";
|
||||
|
||||
const ROLE_HIERARCHY: Record<Role, number> = {
|
||||
owner: 4,
|
||||
admin: 3,
|
||||
operator: 2,
|
||||
read_only: 1,
|
||||
};
|
||||
|
||||
export function generateToken(user: AuthenticatedUser): string {
|
||||
return jwt.sign(
|
||||
{
|
||||
userId: user.userId,
|
||||
organizationId: user.organizationId,
|
||||
role: user.role,
|
||||
email: user.email,
|
||||
},
|
||||
JWT_SECRET,
|
||||
{ expiresIn: (process.env.JWT_EXPIRES_IN || "24h") as any }
|
||||
);
|
||||
}
|
||||
|
||||
export function verifyToken(token: string): AuthenticatedUser {
|
||||
return jwt.verify(token, JWT_SECRET) as AuthenticatedUser;
|
||||
}
|
||||
|
||||
export function authenticate(req: Request, res: Response, next: NextFunction) {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader?.startsWith("Bearer ")) {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
error: { code: "UNAUTHORIZED", message: "Missing or invalid token" },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = authHeader.substring(7);
|
||||
const user = verifyToken(token);
|
||||
(req as any).user = user;
|
||||
next();
|
||||
} catch {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
error: { code: "UNAUTHORIZED", message: "Invalid or expired token" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function authorize(...allowedRoles: Role[]) {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
const user = (req as any).user as AuthenticatedUser;
|
||||
if (!user) {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
error: { code: "UNAUTHORIZED", message: "Not authenticated" },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowedRoles.length > 0) {
|
||||
const hasRole = allowedRoles.some(
|
||||
(role) => ROLE_HIERARCHY[user.role] >= ROLE_HIERARCHY[role]
|
||||
);
|
||||
if (!hasRole) {
|
||||
res.status(403).json({
|
||||
success: false,
|
||||
error: { code: "FORBIDDEN", message: "Insufficient permissions" },
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user