First commit

This commit is contained in:
2026-09-30 01:49:35 +02:00
commit 6edd03aace
109 changed files with 27020 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
import jwt from "jsonwebtoken";
import { JWT_SECRET, TOKEN_TTL } from "../config/auth.js";
import User from "../models/User.js";
/** Issues a session token for an account. */
export function signToken(user) {
return jwt.sign(
{ sub: user._id.toString(), username: user.username },
JWT_SECRET,
{ expiresIn: TOKEN_TTL }
);
}
/**
* Reads the `Authorization: Bearer <token>` header and puts the account on
* `req.user`; anything else and the request stops here with 401. The message
* bodies are what the frontend keys off: a 401 means the session it holds is
* no good, so it drops it and asks the person to sign in again.
*/
export function requireAuth(req, res, next) {
const [scheme, token] = String(req.headers.authorization || "").split(" ");
if (scheme !== "Bearer" || !token) {
return res.status(401).json({ message: "Please sign in to do that." });
}
let session;
try {
session = jwt.verify(token, JWT_SECRET);
} catch {
return res
.status(401)
.json({ message: "That session has expired — please sign in again." });
}
req.user = { id: session.sub, username: session.username };
next();
}
/**
* Runs after `requireAuth` and lets an admin through alone. The role is read
* from the account rather than trusted from the token, so taking it away works
* the next time the dashboard is asked for — a token issued while the account
* was an admin is no good once it is not.
*/
export async function requireAdmin(req, res, next) {
try {
const account = await User.findById(req.user.id);
if (!account) {
return res.status(401).json({ message: "No such account any more." });
}
if (account.role !== "admin") {
return res.status(403).json({ message: "This is for administrators." });
}
req.user.role = account.role;
next();
} catch (err) {
next(err);
}
}