feat: public events/polls, friends graph, captcha, SSE hardening, and admin UX
Ship product gaps: register/vote pages, friend add/accept/decline/remove, email verify TTL, captcha on login/forgot, soft-fail user actions, SSE abort/shared client, Commando Centrum error toasts, admin delete for events/polls, and IT/NL i18n fills. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
2ff08e5127
commit
ed7db6e048
76 files changed
+4834
-1376
No files matched your search
+12
-3
@@ -67,9 +67,10 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
const password = String(credentials?.password ?? "");
|
||||
if (!username || !password) return null;
|
||||
|
||||
const ip = await clientIp();
|
||||
|
||||
// Throttle login attempts per IP (10 per 5 min) against credential stuffing.
|
||||
if (!(await rateLimit(`login:${await clientIp()}`, 10, 5 * 60_000)).ok)
|
||||
return null;
|
||||
if (!(await rateLimit(`login:${ip}`, 10, 5 * 60_000)).ok) return null;
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { username } });
|
||||
if (!user) {
|
||||
@@ -90,6 +91,14 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
});
|
||||
if (!res.valid) return null;
|
||||
|
||||
if (
|
||||
(await siteSettings.getBool("require_email_verification", false)) &&
|
||||
user.mail &&
|
||||
user.mailVerified !== "1"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (res.upgradedHash) {
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
@@ -117,7 +126,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
await prisma.websiteLoginLogs.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
ip: await clientIp(),
|
||||
ip,
|
||||
userAgent: ua,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user