feat: add passkey and auth settings endpoints to TenantPortalController

This commit is contained in:
hsiegeln
2026-04-27 08:45:52 +02:00
parent 5bf94c6d4e
commit b3104dc410

View File

@@ -22,6 +22,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@RestController
@@ -185,6 +186,65 @@ public class TenantPortalController {
}
}
// --- Passkey endpoints ---
@GetMapping("/mfa/webauthn")
public ResponseEntity<List<TenantPortalService.PasskeyCredential>> listPasskeys(
@AuthenticationPrincipal Jwt jwt) {
return ResponseEntity.ok(portalService.listPasskeys(jwt.getSubject()));
}
@PatchMapping("/mfa/webauthn/{id}/name")
public ResponseEntity<Void> renamePasskey(@AuthenticationPrincipal Jwt jwt,
@PathVariable String id,
@RequestBody Map<String, String> body) {
String name = body.get("name");
if (name == null || name.isBlank()) {
return ResponseEntity.badRequest().build();
}
try {
portalService.renamePasskey(jwt.getSubject(), id, name);
return ResponseEntity.noContent().build();
} catch (IllegalArgumentException e) {
return ResponseEntity.notFound().build();
}
}
@DeleteMapping("/mfa/webauthn/{id}")
public ResponseEntity<Void> deletePasskey(@AuthenticationPrincipal Jwt jwt,
@PathVariable String id) {
try {
portalService.deletePasskey(jwt.getSubject(), id);
return ResponseEntity.noContent().build();
} catch (IllegalArgumentException e) {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/mfa/method-preference")
public ResponseEntity<Void> updateMfaMethodPreference(@AuthenticationPrincipal Jwt jwt,
@RequestBody Map<String, String> body) {
String preference = body.get("preference");
if (preference == null || !Set.of("totp", "webauthn").contains(preference)) {
return ResponseEntity.badRequest().build();
}
portalService.updateMfaMethodPreference(jwt.getSubject(), preference);
return ResponseEntity.noContent().build();
}
// --- Auth settings endpoints ---
@GetMapping("/auth-settings")
public ResponseEntity<TenantPortalService.AuthSettingsData> getAuthSettings() {
return ResponseEntity.ok(portalService.getAuthSettings());
}
@PutMapping("/auth-settings")
public ResponseEntity<Void> updateAuthSettings(@RequestBody Map<String, Object> updates) {
portalService.updateTenantSettings(updates);
return ResponseEntity.ok().build();
}
@PatchMapping("/settings")
public ResponseEntity<Void> updateSettings(@RequestBody Map<String, Object> updates) {
portalService.updateTenantSettings(updates);
@@ -199,8 +259,19 @@ public class TenantPortalController {
}
var tenant = tenantOpt.get();
Map<String, Object> settings = tenant.getSettings() != null ? tenant.getSettings() : Map.of();
boolean mfaRequired = Boolean.TRUE.equals(settings.get("mfaRequired"));
return ResponseEntity.ok(Map.of("mfaRequired", mfaRequired));
String mfaMode = settings.containsKey("mfaMode")
? String.valueOf(settings.get("mfaMode"))
: (Boolean.TRUE.equals(settings.get("mfaRequired")) ? "required" : "off");
boolean passkeyEnabled = Boolean.TRUE.equals(settings.get("passkeyEnabled"));
String passkeyMode = settings.containsKey("passkeyMode")
? String.valueOf(settings.get("passkeyMode"))
: "optional";
return ResponseEntity.ok(Map.of(
"mfaRequired", "required".equals(mfaMode),
"mfaMode", mfaMode,
"passkeyEnabled", passkeyEnabled,
"passkeyMode", passkeyMode
));
}
// --- CA Certificate management ---