fix: add rate limter error

This commit is contained in:
Bereket Engida
2024-09-24 02:41:01 +03:00
parent bc82bf3d30
commit 6c9782202f
10 changed files with 70 additions and 49 deletions

View File

@@ -74,7 +74,7 @@ export function OrganizationCard(props: { session: Session | null }) {
);
return (
<Card className="rounded-none md:rounded-sm !bg-none border-none">
<Card>
<CardHeader>
<CardTitle>Organization</CardTitle>
<div className="flex justify-between">

View File

@@ -1,27 +1,29 @@
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
import { redirect } from "next/navigation"
import UserCard from "./user-card"
import { OrganizationCard } from "./organization-card"
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
import UserCard from "./user-card";
import { OrganizationCard } from "./organization-card";
export default async function DashboardPage() {
const [session, activeSessions] = await Promise.all([
auth.api.getSession({
headers: headers()
}),
auth.api.listSessions({
headers: headers()
})
]).catch(e => {
throw redirect("/sign-in")
})
return (
<div className="w-full">
<div className="flex gap-4 flex-col">
<UserCard session={JSON.parse(JSON.stringify(session))} activeSessions={JSON.parse(JSON.stringify(activeSessions))} />
<OrganizationCard session={JSON.parse(JSON.stringify(session))} />
</div>
</div>
)
}
const [session, activeSessions] = await Promise.all([
auth.api.getSession({
headers: headers(),
}),
auth.api.listSessions({
headers: headers(),
}),
]).catch((e) => {
throw redirect("/sign-in");
});
return (
<div className="w-full">
<div className="flex gap-4 flex-col">
<UserCard
session={JSON.parse(JSON.stringify(session))}
activeSessions={JSON.parse(JSON.stringify(activeSessions))}
/>
<OrganizationCard session={JSON.parse(JSON.stringify(session))} />
</div>
</div>
);
}

View File

@@ -89,7 +89,7 @@ export default function UserCard(props: {
const [isSignOut, setIsSignOut] = useState<boolean>(false);
return (
<Card className="rounded-none md:rounded-sm !bg-none border-none">
<Card>
<CardHeader>
<CardTitle>User</CardTitle>
</CardHeader>
@@ -407,6 +407,7 @@ function ChangePassword() {
toast.error("Passwords do not match");
return;
}
a;
if (newPassword.length < 8) {
toast.error("Password must be at least 8 characters");
return;

View File

@@ -4,6 +4,7 @@ import {
passkeyClient,
twoFactorClient,
} from "better-auth/client/plugins";
import { toast } from "sonner";
export const client = createAuthClient({
plugins: [
@@ -14,7 +15,11 @@ export const client = createAuthClient({
passkeyClient(),
],
fetchOptions: {
credentials: "include",
onError(e) {
if (e.error.status === 429) {
toast.error("Too many requests. Please try again later.");
}
},
},
});

View File

@@ -41,6 +41,8 @@ export const auth = betterAuth({
plugins: [
rateLimiter({
enabled: true,
max: 1000,
}),
organization({
async sendInvitationEmail(data) {

View File

@@ -51,7 +51,6 @@ export const getSession = <Option extends BetterAuthOptions>() =>
requireHeaders: true,
},
async (ctx) => {
console.log("called");
try {
const sessionCookieToken = await ctx.getSignedCookie(
ctx.context.authCookies.sessionToken.name,
@@ -213,7 +212,6 @@ export const revokeSession = createAuthEndpoint(
},
async (ctx) => {
const id = ctx.body.id;
console.log(id);
try {
await ctx.context.internalAdapter.deleteSession(id);
} catch (error) {

View File

@@ -20,6 +20,7 @@ export const getClientConfig = <O extends ClientOptions>(options?: O) => {
.filter((pl) => pl !== undefined) || []),
],
});
const plugins = options?.plugins || [];
let pluginsActions = {} as Record<string, any>;
let pluginsAtoms = {} as Record<string, Atom<any>>;

View File

@@ -61,11 +61,17 @@ export const csrfPlugin = {
"CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth).",
);
}
if (error.status === 429) {
return new Response(null, {
status: 429,
statusText: "Too Many Requests",
});
return new Response(
JSON.stringify({
message: "Too many requests. Please try again later.",
}),
{
status: 429,
statusText: "Too Many Requests",
},
);
}
throw new BetterAuthError(
"Failed to fetch CSRF token: " + error.message,

View File

@@ -207,22 +207,27 @@ export const rateLimiter = (options: RateLimitOptions) => {
rateLimit.lastRequest >= windowStart &&
rateLimit.count >= opts.max
) {
return new Response(null, {
status: 429,
statusText: "Too Many Requests",
headers: {
"X-RateLimit-Window": opts.window.toString(),
"X-RateLimit-Max": opts.max.toString(),
"X-RateLimit-Remaining": (
opts.max - rateLimit.count
).toString(),
"X-RateLimit-Reset": (
rateLimit.lastRequest +
opts.window * 1000 -
now
).toString(),
return new Response(
JSON.stringify({
message: "Too many requests. Please try again later.",
}),
{
status: 429,
statusText: "Too Many Requests",
headers: {
"X-RateLimit-Window": opts.window.toString(),
"X-RateLimit-Max": opts.max.toString(),
"X-RateLimit-Remaining": (
opts.max - rateLimit.count
).toString(),
"X-RateLimit-Reset": (
rateLimit.lastRequest +
opts.window * 1000 -
now
).toString(),
},
},
});
);
}
if (rateLimit.lastRequest < windowStart) {

View File

@@ -12,6 +12,7 @@
[x] fix the issue with the client triggers not working fot 2 consecutive calls
[ ] add a way to specify on the client to use the base path as the whole path
[x] implement magic links
[ ] rate limiter error handling
## Docs