refactor: don't apply strict rate limit on /me and /status endpoints

This commit is contained in:
Nicolas Meienberger 2025-12-18 12:09:34 +01:00
parent 1bb9ccb33b
commit 7951a87332
2 changed files with 42 additions and 30 deletions

View file

@ -46,9 +46,12 @@ const app = new Hono()
.use(secureHeaders())
.use(
rateLimiter({
windowMs: 15 * 60 * 1000,
limit: 100,
windowMs: 60 * 5 * 1000,
limit: 1000,
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
skip: () => {
return config.__prod__ === false;
},
}),
)
.get("healthcheck", (c) => c.json({ status: "ok" }))

View file

@ -21,6 +21,7 @@ import {
} from "./auth.dto";
import { authService } from "./auth.service";
import { toMessage } from "../../utils/errors";
import { config } from "~/server/core/config";
const COOKIE_NAME = "session_id";
const COOKIE_OPTIONS = {
@ -30,15 +31,17 @@ const COOKIE_OPTIONS = {
path: "/",
};
const authRateLimiter = rateLimiter({
windowMs: 15 * 60 * 1000,
limit: 20,
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
skip: () => {
return config.__prod__ === false;
},
});
export const authController = new Hono()
.use(
rateLimiter({
windowMs: 15 * 60 * 1000,
limit: 5,
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
}),
)
.post("/register", registerDto, validator("json", registerBodySchema), async (c) => {
.post("/register", authRateLimiter, registerDto, validator("json", registerBodySchema), async (c) => {
const body = c.req.valid("json");
try {
@ -65,7 +68,7 @@ export const authController = new Hono()
return c.json<RegisterDto>({ success: false, message: toMessage(error) }, 400);
}
})
.post("/login", loginDto, validator("json", loginBodySchema), async (c) => {
.post("/login", authRateLimiter, loginDto, validator("json", loginBodySchema), async (c) => {
const body = c.req.valid("json");
try {
@ -89,7 +92,7 @@ export const authController = new Hono()
return c.json<LoginDto>({ success: false, message: toMessage(error) }, 401);
}
})
.post("/logout", logoutDto, async (c) => {
.post("/logout", authRateLimiter, logoutDto, async (c) => {
const sessionId = getCookie(c, COOKIE_NAME);
if (sessionId) {
@ -123,26 +126,32 @@ export const authController = new Hono()
const hasUsers = await authService.hasUsers();
return c.json<GetStatusDto>({ hasUsers });
})
.post("/change-password", changePasswordDto, validator("json", changePasswordBodySchema), async (c) => {
const sessionId = getCookie(c, COOKIE_NAME);
.post(
"/change-password",
authRateLimiter,
changePasswordDto,
validator("json", changePasswordBodySchema),
async (c) => {
const sessionId = getCookie(c, COOKIE_NAME);
if (!sessionId) {
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
}
if (!sessionId) {
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
}
const session = await authService.verifySession(sessionId);
const session = await authService.verifySession(sessionId);
if (!session) {
deleteCookie(c, COOKIE_NAME, COOKIE_OPTIONS);
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
}
if (!session) {
deleteCookie(c, COOKIE_NAME, COOKIE_OPTIONS);
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
}
const body = c.req.valid("json");
const body = c.req.valid("json");
try {
await authService.changePassword(session.user.id, body.currentPassword, body.newPassword);
return c.json<ChangePasswordDto>({ success: true, message: "Password changed successfully" });
} catch (error) {
return c.json<ChangePasswordDto>({ success: false, message: toMessage(error) }, 400);
}
});
try {
await authService.changePassword(session.user.id, body.currentPassword, body.newPassword);
return c.json<ChangePasswordDto>({ success: true, message: "Password changed successfully" });
} catch (error) {
return c.json<ChangePasswordDto>({ success: false, message: toMessage(error) }, 400);
}
},
);