feat: add release communications
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
using FastEndpoints;
|
||||
using Socialize.Api.Data;
|
||||
using Socialize.Api.Infrastructure.Security;
|
||||
using Socialize.Api.Modules.Identity.Contracts;
|
||||
using Socialize.Api.Modules.ReleaseCommunications.Contracts;
|
||||
using Socialize.Api.Modules.ReleaseCommunications.Data;
|
||||
using Socialize.Api.Modules.ReleaseCommunications.Services;
|
||||
|
||||
namespace Socialize.Api.Modules.ReleaseCommunications.Handlers;
|
||||
|
||||
internal record CreateDeveloperReleaseUpdateRequest(
|
||||
string Title,
|
||||
string Summary,
|
||||
string? Body,
|
||||
string Category,
|
||||
string Importance,
|
||||
string Audience,
|
||||
string? DeploymentLabel,
|
||||
string? BuildVersion,
|
||||
string? CommitRange);
|
||||
|
||||
internal class CreateDeveloperReleaseUpdateRequestValidator
|
||||
: Validator<CreateDeveloperReleaseUpdateRequest>
|
||||
{
|
||||
public CreateDeveloperReleaseUpdateRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty().MaximumLength(160);
|
||||
RuleFor(x => x.Summary).NotEmpty().MaximumLength(512);
|
||||
RuleFor(x => x.Body).MaximumLength(8000);
|
||||
RuleFor(x => x.Category).NotEmpty().MaximumLength(32);
|
||||
RuleFor(x => x.Importance).NotEmpty().MaximumLength(32);
|
||||
RuleFor(x => x.Audience).NotEmpty().MaximumLength(32);
|
||||
RuleFor(x => x.DeploymentLabel).MaximumLength(128);
|
||||
RuleFor(x => x.BuildVersion).MaximumLength(128);
|
||||
RuleFor(x => x.CommitRange).MaximumLength(256);
|
||||
}
|
||||
}
|
||||
|
||||
internal class CreateDeveloperReleaseUpdateHandler(AppDbContext dbContext)
|
||||
: Endpoint<CreateDeveloperReleaseUpdateRequest, ReleaseUpdateDto>
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Post("/api/developer/release-updates");
|
||||
Roles(KnownRoles.Developer);
|
||||
Options(o => o.WithTags("Release Communications"));
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(CreateDeveloperReleaseUpdateRequest request, CancellationToken ct)
|
||||
{
|
||||
if (!TryParseRequest(request, out ReleaseUpdateCategory category, out ReleaseUpdateImportance importance, out ReleaseUpdateAudience audience))
|
||||
{
|
||||
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
ReleaseUpdate update = new()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Title = request.Title.Trim(),
|
||||
Summary = request.Summary.Trim(),
|
||||
Body = NormalizeOptional(request.Body),
|
||||
Category = category,
|
||||
Importance = importance,
|
||||
Audience = audience,
|
||||
Status = ReleaseUpdateStatus.Draft,
|
||||
DeploymentLabel = NormalizeOptional(request.DeploymentLabel),
|
||||
BuildVersion = NormalizeOptional(request.BuildVersion),
|
||||
CommitRange = NormalizeOptional(request.CommitRange),
|
||||
CreatedByUserId = User.GetUserId(),
|
||||
CreatedAt = now,
|
||||
UpdatedAt = now,
|
||||
};
|
||||
|
||||
dbContext.ReleaseUpdates.Add(update);
|
||||
await dbContext.SaveChangesAsync(ct);
|
||||
|
||||
await SendAsync(update.ToDto(false), StatusCodes.Status201Created, ct);
|
||||
}
|
||||
|
||||
private bool TryParseRequest(
|
||||
CreateDeveloperReleaseUpdateRequest request,
|
||||
out ReleaseUpdateCategory category,
|
||||
out ReleaseUpdateImportance importance,
|
||||
out ReleaseUpdateAudience audience)
|
||||
{
|
||||
bool isValid = true;
|
||||
if (!ReleaseUpdateRules.TryParseCategory(request.Category, out category))
|
||||
{
|
||||
AddError(x => x.Category, "The selected release update category is not valid.");
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!ReleaseUpdateRules.TryParseImportance(request.Importance, out importance))
|
||||
{
|
||||
AddError(x => x.Importance, "The selected release update importance is not valid.");
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!ReleaseUpdateRules.TryParseAudience(request.Audience, out audience))
|
||||
{
|
||||
AddError(x => x.Audience, "The selected release update audience is not valid.");
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private static string? NormalizeOptional(string? value)
|
||||
{
|
||||
string? normalized = value?.Trim();
|
||||
return string.IsNullOrWhiteSpace(normalized) ? null : normalized;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user