fix(invite): address review cycle 2 feedback
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m32s
CI / Unit & Component Tests (pull_request) Failing after 2m31s
CI / OCR Service Tests (pull_request) Successful in 31s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
CI / OCR Service Tests (push) Successful in 36s
CI / Backend Unit Tests (push) Failing after 2m43s

- Narrow isTrustedProxy to RFC 1918 172.16-31.x.x (was 172.x.x.x)
- Add @Valid/@NotBlank/@Email to RegisterRequest and @Valid to AuthController
- Add FK constraint on invite_token_group_ids.group_id → user_groups(id)
- Add back-to-login link and <main> landmark to register error state
- Add component test suite for register/+page.svelte (11 tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-19 09:30:57 +02:00
parent 9fc4993fca
commit 88012a1193
6 changed files with 140 additions and 9 deletions

View File

@@ -49,9 +49,21 @@ public class RateLimitInterceptor implements HandlerInterceptor {
}
private boolean isTrustedProxy(String ip) {
return ip.equals("127.0.0.1") || ip.equals("::1")
|| ip.startsWith("10.")
|| ip.startsWith("172.")
|| ip.startsWith("192.168.");
if (ip.equals("127.0.0.1") || ip.equals("::1") || ip.startsWith("10.") || ip.startsWith("192.168.")) {
return true;
}
// Only RFC 1918 172.16.0.0/12 (172.16172.31), not all of 172.x
if (ip.startsWith("172.")) {
String[] parts = ip.split("\\.");
if (parts.length >= 2) {
try {
int second = Integer.parseInt(parts[1]);
return second >= 16 && second <= 31;
} catch (NumberFormatException ignored) {
return false;
}
}
}
return false;
}
}

View File

@@ -1,5 +1,6 @@
package org.raddatz.familienarchiv.controller;
import jakarta.validation.Valid;
import org.raddatz.familienarchiv.dto.ForgotPasswordRequest;
import org.raddatz.familienarchiv.dto.InvitePrefillDTO;
import org.raddatz.familienarchiv.dto.RegisterRequest;
@@ -50,7 +51,7 @@ public class AuthController {
}
@PostMapping("/register")
public ResponseEntity<AppUser> register(@RequestBody RegisterRequest request) {
public ResponseEntity<AppUser> register(@Valid @RequestBody RegisterRequest request) {
AppUser user = inviteService.redeemInvite(request);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}

View File

@@ -1,11 +1,17 @@
package org.raddatz.familienarchiv.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class RegisterRequest {
@NotBlank
private String code;
@NotBlank
@Email
private String email;
@NotBlank
private String password;
private String firstName;
private String lastName;

View File

@@ -17,6 +17,6 @@ CREATE INDEX idx_invite_tokens_code ON invite_tokens(code);
CREATE TABLE invite_token_group_ids (
invite_token_id UUID NOT NULL REFERENCES invite_tokens(id),
group_id UUID NOT NULL,
group_id UUID NOT NULL REFERENCES user_groups(id),
PRIMARY KEY (invite_token_id, group_id)
);