using Fitness_core_BE.Infra.Tenancy; using Microsoft.AspNetCore.Mvc.Filters; namespace Fitness_core_BE.Helpers { // Resolves the request's TenantId into the scoped ITenantContext, so downstream // repos/services can read it instead of re-deriving ClientId ad hoc. Must run AFTER // CustomMiddlewareAttribute (order 0, populates HttpContext.Items["UserId"]) and BEFORE // RequiresPermissionAttribute (order 10) — Order = 5 guarantees this regardless of // attribute declaration order on the method, same technique RequiresPermissionAttribute // itself uses. // // Single-club deployment: everyone (Client owner, Staff, Customer) resolves to the same // one Client row. GYM's split served many gyms, so a Customer's active gym was picked // per-request from a caller-supplied X-Tenant-Id header, independently verified against // the DB. There's only one gym here, so that header/verification step is gone — a // Customer always resolves to the one club, the same way Client/Staff already did. // Admin: platform-wide, no tenant. [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public class TenantResolutionAttribute : Attribute, IAsyncActionFilter, IOrderedFilter { public int Order => 5; public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var httpContext = context.HttpContext; var userRoleHelper = httpContext.RequestServices.GetRequiredService(); var tenantContext = httpContext.RequestServices.GetRequiredService(); var userId = DataExtractor.GetUserIdFromContext(httpContext); var userType = await userRoleHelper.GetUserType(userId); if (userType == "Admin") { tenantContext.SetTenant(null, isPlatformAdmin: true); await next(); return; } if (userType == "Client" || userType == "Staff") { var clientId = await userRoleHelper.GetClientId(userId); tenantContext.SetTenant(clientId, isPlatformAdmin: false); await next(); return; } // Customer -- resolves to the one club, no header needed. var defaultClientId = await userRoleHelper.GetDefaultClientId(); tenantContext.SetTenant(defaultClientId, isPlatformAdmin: false); await next(); } } }