feat: pivot to social media workflow app
This commit is contained in:
100
backend/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs
Normal file
100
backend/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Socialize.Infrastructure.Security;
|
||||
using Socialize.Modules.Identity.Contracts;
|
||||
using Socialize.Modules.Workspaces.Data;
|
||||
|
||||
namespace Socialize.Modules.Workspaces.Handlers;
|
||||
|
||||
public record CreateWorkspaceInviteRequest(
|
||||
string Email,
|
||||
string Role);
|
||||
|
||||
public class CreateWorkspaceInviteRequestValidator
|
||||
: Validator<CreateWorkspaceInviteRequest>
|
||||
{
|
||||
private static readonly string[] AllowedRoles =
|
||||
[
|
||||
KnownRoles.Client,
|
||||
KnownRoles.Provider,
|
||||
KnownRoles.WorkspaceMember,
|
||||
];
|
||||
|
||||
public CreateWorkspaceInviteRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Email).NotEmpty().MaximumLength(256).EmailAddress();
|
||||
RuleFor(x => x.Role).NotEmpty().Must(role => AllowedRoles.Contains(role));
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateWorkspaceInviteHandler(
|
||||
AppDbContext dbContext,
|
||||
AccessScopeService accessScopeService)
|
||||
: Endpoint<CreateWorkspaceInviteRequest, WorkspaceInviteDto>
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Post("/api/workspaces/{workspaceId:guid}/invites");
|
||||
Options(o => o.WithTags("Workspaces"));
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(CreateWorkspaceInviteRequest request, CancellationToken ct)
|
||||
{
|
||||
Guid workspaceId = Route<Guid>("workspaceId");
|
||||
|
||||
if (!accessScopeService.CanManageWorkspace(User, workspaceId))
|
||||
{
|
||||
await SendForbiddenAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
bool workspaceExists = await dbContext.Workspaces
|
||||
.AnyAsync(workspace => workspace.Id == workspaceId, ct);
|
||||
|
||||
if (!workspaceExists)
|
||||
{
|
||||
AddError("workspaceId", "The selected workspace does not exist.");
|
||||
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
string normalizedEmail = request.Email.Trim().ToLowerInvariant();
|
||||
string normalizedRole = request.Role.Trim();
|
||||
|
||||
bool duplicateInvite = await dbContext.WorkspaceInvites.AnyAsync(
|
||||
invite => invite.WorkspaceId == workspaceId &&
|
||||
invite.Email == normalizedEmail &&
|
||||
invite.Status == "Pending",
|
||||
ct);
|
||||
|
||||
if (duplicateInvite)
|
||||
{
|
||||
AddError(request => request.Email, "A pending invite already exists for this email in the selected workspace.");
|
||||
await SendErrorsAsync(StatusCodes.Status409Conflict, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
WorkspaceInvite invite = new()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
WorkspaceId = workspaceId,
|
||||
Email = normalizedEmail,
|
||||
Role = normalizedRole,
|
||||
Status = "Pending",
|
||||
InvitedByUserId = User.GetUserId(),
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
dbContext.WorkspaceInvites.Add(invite);
|
||||
await dbContext.SaveChangesAsync(ct);
|
||||
|
||||
await SendAsync(
|
||||
new WorkspaceInviteDto(
|
||||
invite.Id,
|
||||
invite.WorkspaceId,
|
||||
invite.Email,
|
||||
invite.Role,
|
||||
invite.Status,
|
||||
invite.CreatedAt),
|
||||
StatusCodes.Status201Created,
|
||||
ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user