fix: code review findings — auth-settings HTTP method, authorization, redirect
- Change auth-settings endpoint from PUT to PATCH (matches partial update semantics and frontend hook)
- Add @PreAuthorize("SCOPE_tenant:manage") to updateAuthSettings endpoint
- Consolidate MFA/passkey 403 redirect handling in API client
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import net.siegeln.cameleer.saas.certificate.TenantCaCertService;
|
|||||||
import net.siegeln.cameleer.saas.config.TenantContext;
|
import net.siegeln.cameleer.saas.config.TenantContext;
|
||||||
import net.siegeln.cameleer.saas.tenant.TenantService;
|
import net.siegeln.cameleer.saas.tenant.TenantService;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
import org.springframework.security.oauth2.jwt.Jwt;
|
import org.springframework.security.oauth2.jwt.Jwt;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
@@ -239,7 +240,8 @@ public class TenantPortalController {
|
|||||||
return ResponseEntity.ok(portalService.getAuthSettings());
|
return ResponseEntity.ok(portalService.getAuthSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/auth-settings")
|
@PreAuthorize("hasAuthority('SCOPE_tenant:manage')")
|
||||||
|
@PatchMapping("/auth-settings")
|
||||||
public ResponseEntity<Void> updateAuthSettings(@RequestBody Map<String, Object> updates) {
|
public ResponseEntity<Void> updateAuthSettings(@RequestBody Map<String, Object> updates) {
|
||||||
portalService.updateTenantSettings(updates);
|
portalService.updateTenantSettings(updates);
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
|
|||||||
@@ -65,13 +65,11 @@ async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T>
|
|||||||
|
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
const errorHeader = response.headers.get('X-Cameleer-Error');
|
const errorHeader = response.headers.get('X-Cameleer-Error');
|
||||||
if (errorHeader === 'APP_MFA_REQUIRED') {
|
if (errorHeader === 'APP_MFA_REQUIRED' || errorHeader === 'APP_PASSKEY_REQUIRED') {
|
||||||
window.location.href = '/platform/tenant/settings?mfa=required';
|
const param = errorHeader === 'APP_PASSKEY_REQUIRED' ? 'passkey=required' : 'mfa=required';
|
||||||
throw new ApiError(403, '{"message":"MFA enrollment required"}');
|
window.location.href = `/platform/tenant/settings?${param}`;
|
||||||
}
|
const msg = errorHeader === 'APP_PASSKEY_REQUIRED' ? 'Passkey enrollment required' : 'MFA enrollment required';
|
||||||
if (errorHeader === 'APP_PASSKEY_REQUIRED') {
|
throw new ApiError(403, JSON.stringify({ message: msg }));
|
||||||
window.location.href = '/platform/tenant/settings?passkey=required';
|
|
||||||
throw new ApiError(403, '{"message":"Passkey enrollment required"}');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user