using System.Security.Claims; using Socialize.Infrastructure.Security; namespace Socialize.Modules.Workspaces.Handlers; public record WorkspaceMemberDto( Guid Id, string DisplayName, string Email, string? PortraitUrl, IReadOnlyCollection Roles); public class GetWorkspaceMembersHandler( AppDbContext dbContext, AccessScopeService accessScopeService) : EndpointWithoutRequest> { public override void Configure() { Get("/api/workspaces/{workspaceId:guid}/members"); Options(o => o.WithTags("Workspaces")); } public override async Task HandleAsync(CancellationToken ct) { Guid workspaceId = Route("workspaceId"); if (!accessScopeService.CanManageWorkspace(User, workspaceId)) { await SendForbiddenAsync(ct); return; } string workspaceClaimValue = workspaceId.ToString(); List users = await dbContext.Users .Where(candidate => dbContext.UserClaims.Any(claim => claim.UserId == candidate.Id && claim.ClaimType == KnownClaims.WorkspaceScope && claim.ClaimValue == workspaceClaimValue)) .OrderBy(candidate => candidate.Lastname) .ThenBy(candidate => candidate.Firstname) .ThenBy(candidate => candidate.Email) .ToListAsync(ct); List userIds = users .Select(candidate => candidate.Id) .ToList(); Dictionary> rolesByUserId = await dbContext.UserRoles .Where(candidate => userIds.Contains(candidate.UserId)) .Join( dbContext.Roles, userRole => userRole.RoleId, role => role.Id, (userRole, role) => new { userRole.UserId, role.Name }) .GroupBy(candidate => candidate.UserId) .ToDictionaryAsync( group => group.Key, group => (IReadOnlyCollection)group .Select(candidate => candidate.Name) .Where(name => !string.IsNullOrWhiteSpace(name)) .Cast() .OrderBy(name => name) .ToArray(), ct); List members = users .Select(candidate => new WorkspaceMemberDto( candidate.Id, BuildDisplayName(candidate), candidate.Email ?? string.Empty, candidate.PortraitUrl, rolesByUserId.GetValueOrDefault(candidate.Id) ?? Array.Empty())) .ToList(); await SendOkAsync(members, ct); } private static string BuildDisplayName(User user) { if (!string.IsNullOrWhiteSpace(user.Alias)) { return user.Alias; } string fullName = $"{user.Firstname} {user.Lastname}".Trim(); if (!string.IsNullOrWhiteSpace(fullName)) { return fullName; } return user.Email ?? user.UserName ?? user.Id.ToString(); } }