diff --git a/backend/WorkClub.Api/Services/ClubService.cs b/backend/WorkClub.Api/Services/ClubService.cs index 6d7df8a..4578479 100644 --- a/backend/WorkClub.Api/Services/ClubService.cs +++ b/backend/WorkClub.Api/Services/ClubService.cs @@ -1,6 +1,8 @@ using Microsoft.EntityFrameworkCore; +using Npgsql; using WorkClub.Application.Clubs.DTOs; using WorkClub.Application.Interfaces; +using WorkClub.Domain.Enums; using WorkClub.Infrastructure.Data; namespace WorkClub.Api.Services; @@ -23,35 +25,99 @@ public class ClubService public async Task> GetMyClubsAsync() { - var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirst("sub")?.Value; - if (string.IsNullOrEmpty(userIdClaim)) + var clubsClaim = _httpContextAccessor.HttpContext?.User.FindFirst("clubs")?.Value; + if (string.IsNullOrEmpty(clubsClaim)) { return new List(); } - var memberships = await _context.Members - .Where(m => m.ExternalUserId == userIdClaim) - .ToListAsync(); + var tenantIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(t => t.Trim()) + .Where(t => !string.IsNullOrEmpty(t) && Guid.TryParse(t, out _)) + .ToList(); - var clubIds = memberships.Select(m => m.ClubId).ToList(); - - var clubs = await _context.Clubs - .Where(c => clubIds.Contains(c.Id)) - .ToListAsync(); + if (tenantIds.Count == 0) + { + return new List(); + } var clubDtos = new List(); - foreach (var club in clubs) - { - var memberCount = await _context.Members - .Where(m => m.ClubId == club.Id) - .CountAsync(); + var connectionString = _context.Database.GetConnectionString(); - clubDtos.Add(new ClubListDto( - club.Id, - club.Name, - club.SportType.ToString(), - memberCount - )); + foreach (var tenantId in tenantIds) + { + await using var connection = new NpgsqlConnection(connectionString); + await connection.OpenAsync(); + + await using var transaction = await connection.BeginTransactionAsync(); + + // Set RLS context + using (var command = connection.CreateCommand()) + { + command.Transaction = transaction; + command.CommandText = $"SET LOCAL app.current_tenant_id = '{tenantId}'"; + await command.ExecuteNonQueryAsync(); + } + + Guid? clubId = null; + string? clubName = null; + int? sportTypeInt = null; + + // Fetch club details + using (var command = connection.CreateCommand()) + { + command.Transaction = transaction; + command.CommandText = @" + SELECT c.""Id"", c.""Name"", c.""SportType"" + FROM clubs AS c + WHERE c.""TenantId"" = @tenantId"; + + var parameter = command.CreateParameter(); + parameter.ParameterName = "@tenantId"; + parameter.Value = tenantId; + command.Parameters.Add(parameter); + + using (var reader = await command.ExecuteReaderAsync()) + { + if (await reader.ReadAsync()) + { + clubId = reader.GetGuid(0); + clubName = reader.GetString(1); + sportTypeInt = reader.GetInt32(2); + } + } + } + + // Fetch member count if club exists + if (clubId.HasValue && clubName != null && sportTypeInt.HasValue) + { + using (var memberCommand = connection.CreateCommand()) + { + memberCommand.Transaction = transaction; + memberCommand.CommandText = @" + SELECT COUNT(*) + FROM members AS m + WHERE m.""ClubId"" = @clubId"; + + var param = memberCommand.CreateParameter(); + param.ParameterName = "@clubId"; + param.Value = clubId; + memberCommand.Parameters.Add(param); + + var memberCountResult = await memberCommand.ExecuteScalarAsync(); + var memberCount = memberCountResult != null ? Convert.ToInt32(memberCountResult) : 0; + var sportTypeEnum = ((SportType)sportTypeInt.Value).ToString(); + + clubDtos.Add(new ClubListDto( + clubId.Value, + clubName, + sportTypeEnum, + memberCount + )); + } + } + + await transaction.CommitAsync(); } return clubDtos;