// routes/auth.js const express = require("express") const router = express.Router() const requireAuth = require("../middleware/requireAuth.js") const { validate } = require("../middleware/validate.middleware") const authService = require("../services/auth.service") const { endpoints } = require("@shared/contracts") const { mapLoginRequestToLoginInput, mapLoginResultToResponse } = require("../adapters/responses/login.adapter") const { mapRegisterRequestToRegisterInput, mapRegisterResultToResponse } = require("../adapters/responses/register.adapter") const { mapMeRequestToUserId, mapMeResultToResponse } = require("../adapters/responses/me.adapter") const { auth } = endpoints // NOT: app.js’de cookie-parser olmali: // const cookieParser = require("cookie-parser") // app.use(cookieParser()) function getCookieOptions() { const isProd = process.env.NODE_ENV === "production" return { httpOnly: true, secure: isProd, sameSite: "lax", path: "/", } } function parseExpiresInToMs(value) { if (!value) return 15 * 60 * 1000 if (typeof value === "number" && Number.isFinite(value)) return value * 1000 const str = String(value).trim().toLowerCase() const match = str.match(/^(\d+)(ms|s|m|h|d)?$/) if (!match) return 15 * 60 * 1000 const n = Number(match[1]) const unit = match[2] || "s" const mult = unit === "ms" ? 1 : unit === "s" ? 1000 : unit === "m" ? 60 * 1000 : unit === "h" ? 60 * 60 * 1000 : unit === "d" ? 24 * 60 * 60 * 1000 : 1000 return n * mult } function setRefreshCookie(res, refreshToken) { const opts = getCookieOptions() const maxAgeMs = Number(process.env.REFRESH_COOKIE_MAX_AGE_MS || 1000 * 60 * 60 * 24 * 30) res.cookie("rt", refreshToken, { ...opts, maxAge: maxAgeMs }) } function setAccessCookie(res, accessToken) { const opts = getCookieOptions() const maxAgeMs = parseExpiresInToMs(process.env.ACCESS_TOKEN_EXPIRES_IN || "15m") res.cookie("at", accessToken, { ...opts, maxAge: maxAgeMs }) } function clearRefreshCookie(res) { const opts = getCookieOptions() res.clearCookie("rt", { ...opts }) } function clearAccessCookie(res) { const opts = getCookieOptions() res.clearCookie("at", { ...opts }) } router.post( "/register", validate(auth.registerRequestSchema, "body", "validatedRegisterInput"), async (req, res) => { try { const input = mapRegisterRequestToRegisterInput(req.validatedRegisterInput) const result = await authService.register({ ...input, meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null }, }) // refresh + access cookie set if (result.refreshToken) setRefreshCookie(res, result.refreshToken) if (result.accessToken) setAccessCookie(res, result.accessToken) const response = auth.authResponseSchema.parse(mapRegisterResultToResponse(result)) res.json(response) } catch (err) { const status = err.statusCode || 500 res.status(status).json({ message: err.message || "Kayit islemi basarisiz." }) } } ) router.post( "/login", validate(auth.loginRequestSchema, "body", "validatedLoginInput"), async (req, res) => { try { const input = mapLoginRequestToLoginInput(req.validatedLoginInput) const result = await authService.login({ ...input, meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null }, }) // refresh + access cookie set setRefreshCookie(res, result.refreshToken) setAccessCookie(res, result.accessToken) const response = auth.authResponseSchema.parse(mapLoginResultToResponse(result)) res.json(response) } catch (err) { const status = err.statusCode || 500 res.status(status).json({ message: err.statusCode ? err.message : "Giris islemi basarisiz.", }) } } ) router.post("/refresh", async (req, res) => { try { const refreshToken = req.cookies?.rt if (!refreshToken) return res.status(401).json({ message: "Refresh token yok" }) const result = await authService.refresh({ refreshToken, meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null }, }) // rotate -> yeni refresh + access cookie setRefreshCookie(res, result.refreshToken) setAccessCookie(res, result.accessToken) const response = auth.authResponseSchema.parse(mapLoginResultToResponse(result)) res.json(response) } catch (err) { clearRefreshCookie(res) clearAccessCookie(res) const status = err.statusCode || 401 res.status(status).json({ message: err.message || "Refresh basarisiz" }) } }) router.post("/logout", async (req, res) => { try { const refreshToken = req.cookies?.rt if (refreshToken) { await authService.logout({ refreshToken, meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null }, }) } clearRefreshCookie(res) clearAccessCookie(res) res.status(204).send() } catch (err) { clearRefreshCookie(res) clearAccessCookie(res) const status = err.statusCode || 500 res.status(status).json({ message: err.message || "Cikis basarisiz" }) } }) router.get("/me", requireAuth, async (req, res) => { try { const userId = mapMeRequestToUserId(req) const user = await authService.getMe(userId) const response = auth.meResponseSchema.parse(mapMeResultToResponse(user)) res.json(response) } catch (err) { const status = err.statusCode || 500 res.status(status).json({ message: err.message || "Sunucu hatasi" }) } }) module.exports = router