feat: public events/polls, friends graph, captcha, SSE hardening, and admin UX
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 2m55s

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:
SimoandCursor committed 2026-07-21 21:08:33 +02:00
1 parent 2ff08e5127
commit ed7db6e048
76 files changed
+4834 -1376

No files matched your search

+12 -3
View File
@@ -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(),
},