fix: exempt /api/clubs/me from tenant validation

- Add path exemption in TenantValidationMiddleware for /api/clubs/me
- Change authorization policy from RequireMember to RequireViewer
- Fix KEYCLOAK_CLIENT_ID in docker-compose.yml (workclub-app)
- Resolves frontend chicken-and-egg problem for club discovery

Verified:
- /api/clubs/me returns 200 OK without X-Tenant-Id header
- /api/tasks still requires X-Tenant-Id (400 Bad Request)
- Other endpoints unaffected
This commit is contained in:
WorkClub Automation
2026-03-05 21:32:34 +01:00
parent b286e5cb34
commit 18be0fb183
3 changed files with 12 additions and 2 deletions

View File

@@ -11,7 +11,7 @@ public static class ClubEndpoints
var group = app.MapGroup("/api/clubs"); var group = app.MapGroup("/api/clubs");
group.MapGet("/me", GetMyClubs) group.MapGet("/me", GetMyClubs)
.RequireAuthorization("RequireMember") .RequireAuthorization("RequireViewer")
.WithName("GetMyClubs"); .WithName("GetMyClubs");
group.MapGet("/current", GetCurrentClub) group.MapGet("/current", GetCurrentClub)

View File

@@ -22,6 +22,14 @@ public class TenantValidationMiddleware
return; return;
} }
// Exempt /api/clubs/me from tenant validation - this is the bootstrap endpoint
if (context.Request.Path.StartsWithSegments("/api/clubs/me"))
{
_logger.LogInformation("TenantValidationMiddleware: Exempting {Path} from tenant validation", context.Request.Path);
await _next(context);
return;
}
if (!context.Request.Headers.TryGetValue("X-Tenant-Id", out var tenantIdHeader) || if (!context.Request.Headers.TryGetValue("X-Tenant-Id", out var tenantIdHeader) ||
string.IsNullOrWhiteSpace(tenantIdHeader)) string.IsNullOrWhiteSpace(tenantIdHeader))
{ {

View File

@@ -79,12 +79,14 @@ services:
context: ./frontend context: ./frontend
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
container_name: workclub_frontend container_name: workclub_frontend
extra_hosts:
- "localhost:host-gateway"
environment: environment:
NEXT_PUBLIC_API_URL: "http://localhost:5001" NEXT_PUBLIC_API_URL: "http://localhost:5001"
API_INTERNAL_URL: "http://dotnet-api:8080" API_INTERNAL_URL: "http://dotnet-api:8080"
NEXTAUTH_URL: "http://localhost:3000" NEXTAUTH_URL: "http://localhost:3000"
NEXTAUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32" NEXTAUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32"
KEYCLOAK_CLIENT_ID: "workclub-api" KEYCLOAK_CLIENT_ID: "workclub-app"
KEYCLOAK_CLIENT_SECRET: "dev-secret-workclub-api-change-in-production" KEYCLOAK_CLIENT_SECRET: "dev-secret-workclub-api-change-in-production"
KEYCLOAK_ISSUER: "http://localhost:8080/realms/workclub" KEYCLOAK_ISSUER: "http://localhost:8080/realms/workclub"
ports: ports: