feat: add release communications
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using FastEndpoints;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Socialize.Api.Data;
|
||||
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 UpdateDeveloperReleaseUpdateRequest(
|
||||
string Title,
|
||||
string Summary,
|
||||
string? Body,
|
||||
string Category,
|
||||
string Importance,
|
||||
string Audience,
|
||||
string? DeploymentLabel,
|
||||
string? BuildVersion,
|
||||
string? CommitRange);
|
||||
|
||||
internal class UpdateDeveloperReleaseUpdateRequestValidator
|
||||
: Validator<UpdateDeveloperReleaseUpdateRequest>
|
||||
{
|
||||
public UpdateDeveloperReleaseUpdateRequestValidator()
|
||||
{
|
||||
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 UpdateDeveloperReleaseUpdateHandler(AppDbContext dbContext)
|
||||
: Endpoint<UpdateDeveloperReleaseUpdateRequest, ReleaseUpdateDto>
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Put("/api/developer/release-updates/{id}");
|
||||
Roles(KnownRoles.Developer);
|
||||
Options(o => o.WithTags("Release Communications"));
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(UpdateDeveloperReleaseUpdateRequest request, CancellationToken ct)
|
||||
{
|
||||
Guid id = Route<Guid>("id");
|
||||
ReleaseUpdate? update = await dbContext.ReleaseUpdates.SingleOrDefaultAsync(candidate => candidate.Id == id, ct);
|
||||
if (update is null)
|
||||
{
|
||||
await SendNotFoundAsync(ct);
|
||||
return;
|
||||
}
|
||||
|
||||
if (update.Status != ReleaseUpdateStatus.Draft)
|
||||
{
|
||||
AddError("Only draft release updates can be edited.");
|
||||
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryParseRequest(request, out ReleaseUpdateCategory category, out ReleaseUpdateImportance importance, out ReleaseUpdateAudience audience))
|
||||
{
|
||||
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
update.Title = request.Title.Trim();
|
||||
update.Summary = request.Summary.Trim();
|
||||
update.Body = NormalizeOptional(request.Body);
|
||||
update.Category = category;
|
||||
update.Importance = importance;
|
||||
update.Audience = audience;
|
||||
update.DeploymentLabel = NormalizeOptional(request.DeploymentLabel);
|
||||
update.BuildVersion = NormalizeOptional(request.BuildVersion);
|
||||
update.CommitRange = NormalizeOptional(request.CommitRange);
|
||||
update.UpdatedAt = DateTimeOffset.UtcNow;
|
||||
|
||||
await dbContext.SaveChangesAsync(ct);
|
||||
await SendOkAsync(update.ToDto(false), ct);
|
||||
}
|
||||
|
||||
private bool TryParseRequest(
|
||||
UpdateDeveloperReleaseUpdateRequest 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