feat: add organization domain foundation
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
using FastEndpoints;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Socialize.Api.Data;
|
||||
using Socialize.Api.Modules.Identity.Data;
|
||||
using Socialize.Api.Modules.Organizations.Data;
|
||||
using Socialize.Api.Modules.Organizations.Services;
|
||||
using Socialize.Api.Modules.Workspaces.Handlers;
|
||||
|
||||
namespace Socialize.Api.Modules.Organizations.Handlers;
|
||||
|
||||
public class GetOrganizationHandler(
|
||||
AppDbContext dbContext,
|
||||
OrganizationAccessService organizationAccessService)
|
||||
: EndpointWithoutRequest<OrganizationDto>
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Get("/api/organizations/{organizationId:guid}");
|
||||
Options(o => o.WithTags("Organizations"));
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(CancellationToken ct)
|
||||
{
|
||||
Guid organizationId = Route<Guid>("organizationId");
|
||||
|
||||
Organization? organization = await dbContext.Organizations
|
||||
.SingleOrDefaultAsync(candidate => candidate.Id == organizationId, ct);
|
||||
if (organization is null)
|
||||
{
|
||||
await SendNotFoundAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await organizationAccessService.CanAccessOrganizationAsync(User, organizationId, ct))
|
||||
{
|
||||
await SendForbiddenAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
IReadOnlyCollection<string> currentUserPermissions = await organizationAccessService.GetUserOrganizationPermissionsAsync(
|
||||
User,
|
||||
organizationId,
|
||||
ct);
|
||||
|
||||
IReadOnlyCollection<OrganizationMemberDto> members = await GetMembersAsync(organizationId, ct);
|
||||
IReadOnlyCollection<WorkspaceDto> workspaces = await GetWorkspacesAsync(organizationId, ct);
|
||||
|
||||
await SendOkAsync(
|
||||
OrganizationDto.FromOrganization(
|
||||
organization,
|
||||
currentUserPermissions,
|
||||
members,
|
||||
workspaces),
|
||||
ct);
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyCollection<OrganizationMemberDto>> GetMembersAsync(
|
||||
Guid organizationId,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var rows = await dbContext.OrganizationMemberships
|
||||
.Where(membership => membership.OrganizationId == organizationId)
|
||||
.Join(
|
||||
dbContext.Users,
|
||||
membership => membership.UserId,
|
||||
user => user.Id,
|
||||
(membership, user) => new { Membership = membership, User = user })
|
||||
.OrderBy(row => row.User.Lastname)
|
||||
.ThenBy(row => row.User.Firstname)
|
||||
.ThenBy(row => row.User.Email)
|
||||
.ToListAsync(ct);
|
||||
|
||||
return rows
|
||||
.Select(row => new OrganizationMemberDto(
|
||||
row.User.Id,
|
||||
BuildDisplayName(row.User),
|
||||
row.User.Email ?? string.Empty,
|
||||
row.User.PortraitUrl,
|
||||
row.Membership.Role,
|
||||
OrganizationPermissionRules.GetPermissionsForRole(row.Membership.Role),
|
||||
row.Membership.CreatedAt))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyCollection<WorkspaceDto>> GetWorkspacesAsync(
|
||||
Guid organizationId,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var workspaces = await dbContext.Workspaces
|
||||
.Where(workspace => workspace.OrganizationId == organizationId)
|
||||
.OrderBy(workspace => workspace.Name)
|
||||
.ToListAsync(ct);
|
||||
|
||||
return workspaces
|
||||
.Select(workspace => WorkspaceDto.FromWorkspace(workspace, []))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user