first commit
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
using Fitness_core_BE.Exceptions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Fitness_core_BE.Helpers
|
||||
{
|
||||
public class UserRoleHelper
|
||||
{
|
||||
// Admins/Customer/Client are central-bucket; Staff and CustomerSubscriptions are
|
||||
// tenant-bucket.
|
||||
private readonly CentralDbContext _central;
|
||||
private readonly TenantDbContext _context;
|
||||
|
||||
public UserRoleHelper(CentralDbContext central, TenantDbContext context)
|
||||
{
|
||||
_central = central;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<Guid?> GetAdminId(Guid userId)
|
||||
{
|
||||
var admin = await _central.Admins
|
||||
.AsNoTracking()
|
||||
.Where(a => a.FKUserId == userId && a.IsActive)
|
||||
.Select(a => a.AdminId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return admin == Guid.Empty ? null : admin;
|
||||
}
|
||||
public async Task<Guid> GetCusId(Guid userId)
|
||||
{
|
||||
var cus = await _central.Customer
|
||||
.AsNoTracking()
|
||||
.Where(a => a.FKUserId == userId && a.IsActive)
|
||||
.Select(a => a.CusId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (cus == Guid.Empty)
|
||||
throw new NotFoundException("Customer not found or inactive");
|
||||
|
||||
return cus;
|
||||
}
|
||||
|
||||
public async Task<Guid?> GetStaffId(Guid userId)
|
||||
{
|
||||
var staff = await _context.Staff
|
||||
.AsNoTracking()
|
||||
.Where(s => s.FKUserId == userId && s.IsActive)
|
||||
.Select(s => s.StaffId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return staff == Guid.Empty ? null : staff;
|
||||
}
|
||||
|
||||
public async Task<Guid> GetClientId(Guid userId)
|
||||
{
|
||||
var clientId = await _central.Client
|
||||
.AsNoTracking()
|
||||
.Where(c => c.FKUserId == userId)
|
||||
.Select(c => c.ClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
// Staff can use the same tenant-scoped dashboard and real-time hub.
|
||||
if (clientId == Guid.Empty)
|
||||
{
|
||||
clientId = await _context.Staff
|
||||
.AsNoTracking()
|
||||
.Where(s => s.FKUserId == userId && s.IsActive)
|
||||
.Select(s => s.FKClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
if (clientId == Guid.Empty)
|
||||
throw new NotFoundException("Client not found");
|
||||
|
||||
return clientId;
|
||||
}
|
||||
|
||||
// Strict owner lookup used by RBAC decisions. GetClientId intentionally falls
|
||||
// back to a staff member's tenant so normal tenant-scoped data queries work;
|
||||
// that fallback must never make staff users appear to be gym owners.
|
||||
public async Task<Guid?> GetOwnedClientId(Guid userId)
|
||||
{
|
||||
var clientId = await _central.Client
|
||||
.AsNoTracking()
|
||||
.Where(c => c.FKUserId == userId)
|
||||
.Select(c => c.ClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return clientId == Guid.Empty ? null : clientId;
|
||||
}
|
||||
|
||||
// Single-club deployment: exactly one Client row exists, so any caller that just needs
|
||||
// "the club" (rather than a specific user's club) can use this instead of a per-user
|
||||
// lookup. Used by TenantResolutionAttribute's Customer branch, which used to read a
|
||||
// caller-supplied X-Tenant-Id header to pick from many gyms -- there's only one now.
|
||||
public async Task<Guid> GetDefaultClientId()
|
||||
{
|
||||
var clientId = await _central.Client
|
||||
.AsNoTracking()
|
||||
.Select(c => c.ClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (clientId == Guid.Empty)
|
||||
throw new NotFoundException("Club is not configured yet");
|
||||
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public async Task<Guid> GetClientIdByCusId(Guid cusId)
|
||||
{
|
||||
var clientId = await _context.CustomerSubscriptions
|
||||
.AsNoTracking()
|
||||
.Where(s => s.FKCustomerId == cusId && s.IsActive)
|
||||
.Select(s => s.CustomerPlan.FKClientId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (clientId == Guid.Empty)
|
||||
throw new NotFoundException("No active subscription found for customer");
|
||||
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public async Task<string> GetUserType(Guid userId)
|
||||
{
|
||||
var isAdmin = await _central.Admins
|
||||
.AsNoTracking()
|
||||
.AnyAsync(a => a.FKUserId == userId && a.IsActive);
|
||||
if (isAdmin)
|
||||
return "Admin";
|
||||
var isCustomer = await _central.Customer
|
||||
.AsNoTracking()
|
||||
.AnyAsync(c => c.FKUserId == userId && c.IsActive);
|
||||
if (isCustomer)
|
||||
return "Customer";
|
||||
var isClient = await _central.Client
|
||||
.AsNoTracking()
|
||||
.AnyAsync(cl => cl.FKUserId == userId);
|
||||
if (isClient)
|
||||
return "Client";
|
||||
|
||||
var isStaff = await _context.Staff
|
||||
.AsNoTracking()
|
||||
.AnyAsync(s => s.FKUserId == userId && s.IsActive);
|
||||
if (isStaff)
|
||||
return "Staff";
|
||||
throw new NotFoundException("User role not found or inactive");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user