revert revert revert feat(auth): bearer token desteği ve çoklu origin ayarı ekle

revert feat(auth): bearer token desteği ve çoklu origin ayarı ekle

- Authorization header ile Bearer token kimlik doğrulaması eklendi
- Token'ların localStorage'da saklanması desteği eklendi
- WEB_ALLOWED_ORIGINS ve WEB_ALLOWED_HOSTS konfigürasyonları eklendi
- Loop işlerinde profileId ve profileName alanları eklendi
- CORS ve Vite sunucusu için çoklu origin desteği sağlandı
This commit is contained in:
2026-01-05 17:38:42 +00:00
parent 56bba79587
commit a1ae6566bd
14 changed files with 85 additions and 18 deletions

View File

@@ -2,7 +2,10 @@ import { Request, Response, NextFunction } from "express";
import { verifyToken } from "./auth.service"
export const requireAuth = (req: Request, res: Response, next: NextFunction) => {
const token = req.cookies?.["qbuffer_token"];
const cookieToken = req.cookies?.["qbuffer_token"];
const authHeader = req.headers.authorization;
const bearer = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
const token = cookieToken || bearer;
if (!token) {
return res.status(401).json({ error: "Unauthorized" });
}

View File

@@ -5,6 +5,13 @@ import { isDev } from "../config"
const router = Router();
const getAuthToken = (req: any) => {
const cookieToken = req.cookies?.["qbuffer_token"];
const header = req.headers?.authorization as string | undefined;
const bearer = header?.startsWith("Bearer ") ? header.slice(7) : undefined;
return cookieToken || bearer;
};
const loginLimiter = rateLimit({
windowMs: 60_000,
max: 5,
@@ -28,7 +35,7 @@ router.post("/login", loginLimiter, async (req, res) => {
secure: !isDev,
maxAge: 60 * 24 * 60 * 60 * 1000,
});
return res.json({ username: user.username });
return res.json({ username: user.username, token });
});
router.post("/logout", (_req, res) => {
@@ -41,7 +48,7 @@ router.post("/logout", (_req, res) => {
});
router.get("/me", (req, res) => {
const token = req.cookies?.["qbuffer_token"];
const token = getAuthToken(req);
if (!token) {
return res.status(401).json({ error: "Unauthorized" });
}
@@ -54,7 +61,7 @@ router.get("/me", (req, res) => {
});
router.get("/socket-token", (req, res) => {
const token = req.cookies?.["qbuffer_token"];
const token = getAuthToken(req);
if (!token) {
return res.status(401).json({ error: "Unauthorized" });
}

View File

@@ -22,6 +22,7 @@ export const config = {
timerPollMs: envNumber(process.env.TIMER_POLL_MS, 60_000),
webPort: envNumber(process.env.WEB_PORT, 5173),
webOrigin: process.env.WEB_ORIGIN ?? "",
webAllowedOrigins: process.env.WEB_ALLOWED_ORIGINS ?? "",
dataDir: "/app/data",
dbPath: "/app/data/db.json",
logsPath: "/app/data/logs.json",

View File

@@ -45,7 +45,12 @@ const bootstrap = async () => {
if (isDev) {
const fallbackOrigin = `http://localhost:${config.webPort}`;
const origins = [config.webOrigin || fallbackOrigin, fallbackOrigin];
const originList = [config.webOrigin || fallbackOrigin, fallbackOrigin];
const allowed = config.webAllowedOrigins
.split(",")
.map((origin) => origin.trim())
.filter(Boolean);
const origins = [...originList, ...allowed];
app.use(
cors({
origin: origins,

View File

@@ -27,6 +27,8 @@ export const createLoopJob = async (
allowIp: string;
targetLoops: number;
delayMs: number;
profileName?: string;
profileId?: string;
}
): Promise<LoopJob> => {
const now = nowIso();
@@ -41,6 +43,8 @@ export const createLoopJob = async (
targetLoops: input.targetLoops,
doneLoops: 0,
delayMs: input.delayMs,
profileName: input.profileName,
profileId: input.profileId,
deleteDataBetweenLoops: true,
enforcementMode: "aggressive-soft",
status: "RUNNING",

View File

@@ -18,7 +18,7 @@ router.post("/start", async (req, res) => {
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
const { hash, allowIp, targetLoops, delayMs } = parsed.data;
const { hash, allowIp, targetLoops, delayMs, profileName, profileId } = parsed.data;
const db = await readDb();
if (targetLoops > db.settings.maxLoopLimit) {
return res.status(400).json({ error: "Target loops exceed max limit" });
@@ -64,6 +64,8 @@ router.post("/start", async (req, res) => {
allowIp,
targetLoops,
delayMs,
profileName,
profileId,
});
res.json(job);
});

View File

@@ -32,6 +32,8 @@ export interface LoopJob {
targetLoops: number;
doneLoops: number;
delayMs: number;
profileName?: string;
profileId?: string;
deleteDataBetweenLoops: boolean;
enforcementMode: EnforcementMode;
status: LoopStatus;
@@ -62,6 +64,8 @@ export interface Profile {
name: string;
allowIp: string;
delayMs: number;
profileName?: string;
profileId?: string;
targetLoops: number;
createdAt: string;
}