test: add 25 tests for vendor + portal services and controllers
VendorTenantServiceTest (8): create/provision, suspend, delete, renew VendorTenantControllerTest (7): CRUD, auth, conflict handling TenantPortalServiceTest (5): dashboard, license, settings TenantPortalControllerTest (5): dashboard, license, settings, auth Fix TenantIsolationInterceptor bugs found by tests: - org_id resolution now runs before portal path check - path matching uses URI minus context path (not getServletPath) - portal path returns 403 sendError instead of empty 200 Total: 50 tests, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,19 +34,19 @@ public class TenantIsolationInterceptor implements HandlerInterceptor {
|
||||
var authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (!(authentication instanceof JwtAuthenticationToken jwtAuth)) return true;
|
||||
|
||||
String path = request.getRequestURI();
|
||||
// Strip context-path prefix to get the application-relative path.
|
||||
// getServletPath() returns empty string in MockMvc, so use getRequestURI() minus contextPath.
|
||||
String contextPath = request.getContextPath();
|
||||
String uri = request.getRequestURI();
|
||||
String path = (contextPath != null && !contextPath.isEmpty() && uri.startsWith(contextPath))
|
||||
? uri.substring(contextPath.length()) : uri;
|
||||
|
||||
// Vendor endpoints: platform:admin already enforced by Spring Security
|
||||
if (path.startsWith("/platform/api/vendor/")) {
|
||||
if (path.startsWith("/api/vendor/")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tenant portal endpoints: tenant resolved from JWT org context (no path variable)
|
||||
if (path.startsWith("/platform/api/tenant/")) {
|
||||
return TenantContext.getTenantId() != null;
|
||||
}
|
||||
|
||||
// 1. Resolve: JWT organization_id -> TenantContext
|
||||
// 1. Resolve: JWT organization_id -> TenantContext (applies to all non-vendor paths)
|
||||
Jwt jwt = jwtAuth.getToken();
|
||||
String orgId = jwt.getClaimAsString("organization_id");
|
||||
if (orgId != null) {
|
||||
@@ -54,6 +54,15 @@ public class TenantIsolationInterceptor implements HandlerInterceptor {
|
||||
.ifPresent(tenant -> TenantContext.setTenantId(tenant.getId()));
|
||||
}
|
||||
|
||||
// Tenant portal endpoints: tenant resolved from JWT org context (no path variable)
|
||||
if (path.startsWith("/api/tenant/")) {
|
||||
if (TenantContext.getTenantId() == null) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "No organization context");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Validate: read path variables from Spring's HandlerMapping
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> pathVars = (Map<String, String>) request.getAttribute(
|
||||
|
||||
Reference in New Issue
Block a user