AI Implementation feature(873): Landing Page and Login/Register Modal 1.01 (#13)

This commit was merged in pull request #13.
This commit is contained in:
2026-07-21 21:19:40 +00:00
parent cd97e40030
commit 8dc8cee769
7 changed files with 104 additions and 60 deletions
@@ -18,4 +18,15 @@ export class RegistrationRateLimitService {
arr.push(now);
this.hits.set(ip, arr);
}
}
tryConsume(ip: string, now: number = Date.now()): boolean {
const arr = (this.hits.get(ip) ?? []).filter((t) => now - t < WINDOW_MS);
if (arr.length >= MAX_PER_WINDOW) {
this.hits.set(ip, arr);
return false;
}
arr.push(now);
this.hits.set(ip, arr);
return true;
}
}
+2 -4
View File
@@ -100,7 +100,7 @@ export class AuthService implements OnModuleInit {
async registerFirstAdmin(username: string, password: string, ip: string): Promise<LoginResponse> {
validatePassword(password, this.config);
if (!this.registrationRateLimit.isAllowed(ip)) {
if (!this.registrationRateLimit.tryConsume(ip)) {
throw new ApiError(ERROR_CODES.RATE_LIMITED, 'Too many registrations from this IP; try again later.', 429);
}
@@ -128,7 +128,6 @@ export class AuthService implements OnModuleInit {
});
await manager.save(user);
this.registrationRateLimit.record(ip);
return this.mintSession(manager, user);
});
}
@@ -136,7 +135,7 @@ export class AuthService implements OnModuleInit {
async registerPlayer(dto: RegisterDto, ip: string): Promise<LoginResponse> {
validatePassword(dto.password, this.config);
if (!this.registrationRateLimit.isAllowed(ip)) {
if (!this.registrationRateLimit.tryConsume(ip)) {
throw new ApiError(
ERROR_CODES.RATE_LIMITED,
'Too many registration attempts; please wait a minute before trying again.',
@@ -174,7 +173,6 @@ export class AuthService implements OnModuleInit {
});
await manager.save(user);
this.registrationRateLimit.record(ip);
return this.mintSession(manager, user);
});
}