refactor: don't apply strict rate limit on /me and /status endpoints
This commit is contained in:
parent
1bb9ccb33b
commit
7951a87332
2 changed files with 42 additions and 30 deletions
|
|
@ -46,9 +46,12 @@ const app = new Hono()
|
||||||
.use(secureHeaders())
|
.use(secureHeaders())
|
||||||
.use(
|
.use(
|
||||||
rateLimiter({
|
rateLimiter({
|
||||||
windowMs: 15 * 60 * 1000,
|
windowMs: 60 * 5 * 1000,
|
||||||
limit: 100,
|
limit: 1000,
|
||||||
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
|
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
|
||||||
|
skip: () => {
|
||||||
|
return config.__prod__ === false;
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.get("healthcheck", (c) => c.json({ status: "ok" }))
|
.get("healthcheck", (c) => c.json({ status: "ok" }))
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import {
|
||||||
} from "./auth.dto";
|
} from "./auth.dto";
|
||||||
import { authService } from "./auth.service";
|
import { authService } from "./auth.service";
|
||||||
import { toMessage } from "../../utils/errors";
|
import { toMessage } from "../../utils/errors";
|
||||||
|
import { config } from "~/server/core/config";
|
||||||
|
|
||||||
const COOKIE_NAME = "session_id";
|
const COOKIE_NAME = "session_id";
|
||||||
const COOKIE_OPTIONS = {
|
const COOKIE_OPTIONS = {
|
||||||
|
|
@ -30,15 +31,17 @@ const COOKIE_OPTIONS = {
|
||||||
path: "/",
|
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()
|
export const authController = new Hono()
|
||||||
.use(
|
.post("/register", authRateLimiter, registerDto, validator("json", registerBodySchema), async (c) => {
|
||||||
rateLimiter({
|
|
||||||
windowMs: 15 * 60 * 1000,
|
|
||||||
limit: 5,
|
|
||||||
keyGenerator: (c) => c.req.header("x-forwarded-for") ?? "",
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.post("/register", registerDto, validator("json", registerBodySchema), async (c) => {
|
|
||||||
const body = c.req.valid("json");
|
const body = c.req.valid("json");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -65,7 +68,7 @@ export const authController = new Hono()
|
||||||
return c.json<RegisterDto>({ success: false, message: toMessage(error) }, 400);
|
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");
|
const body = c.req.valid("json");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -89,7 +92,7 @@ export const authController = new Hono()
|
||||||
return c.json<LoginDto>({ success: false, message: toMessage(error) }, 401);
|
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);
|
const sessionId = getCookie(c, COOKIE_NAME);
|
||||||
|
|
||||||
if (sessionId) {
|
if (sessionId) {
|
||||||
|
|
@ -123,26 +126,32 @@ export const authController = new Hono()
|
||||||
const hasUsers = await authService.hasUsers();
|
const hasUsers = await authService.hasUsers();
|
||||||
return c.json<GetStatusDto>({ hasUsers });
|
return c.json<GetStatusDto>({ hasUsers });
|
||||||
})
|
})
|
||||||
.post("/change-password", changePasswordDto, validator("json", changePasswordBodySchema), async (c) => {
|
.post(
|
||||||
const sessionId = getCookie(c, COOKIE_NAME);
|
"/change-password",
|
||||||
|
authRateLimiter,
|
||||||
|
changePasswordDto,
|
||||||
|
validator("json", changePasswordBodySchema),
|
||||||
|
async (c) => {
|
||||||
|
const sessionId = getCookie(c, COOKIE_NAME);
|
||||||
|
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
|
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = await authService.verifySession(sessionId);
|
const session = await authService.verifySession(sessionId);
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
deleteCookie(c, COOKIE_NAME, COOKIE_OPTIONS);
|
deleteCookie(c, COOKIE_NAME, COOKIE_OPTIONS);
|
||||||
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
|
return c.json<ChangePasswordDto>({ success: false, message: "Not authenticated" }, 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = c.req.valid("json");
|
const body = c.req.valid("json");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authService.changePassword(session.user.id, body.currentPassword, body.newPassword);
|
await authService.changePassword(session.user.id, body.currentPassword, body.newPassword);
|
||||||
return c.json<ChangePasswordDto>({ success: true, message: "Password changed successfully" });
|
return c.json<ChangePasswordDto>({ success: true, message: "Password changed successfully" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json<ChangePasswordDto>({ success: false, message: toMessage(error) }, 400);
|
return c.json<ChangePasswordDto>({ success: false, message: toMessage(error) }, 400);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue