feat(notification): add admin rest management and deletion
Add revision-safe service and template APIs, channel mapping, and validated admin controls. Ref: IT-1601
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using HrynCo.NotificationService.Services.TemplateDefinitions;
|
||||
using System.Text.Json;
|
||||
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
@@ -95,6 +96,59 @@ public sealed class AdminTemplatesController(IMediator mediator, IEmailTemplateD
|
||||
return RedirectToAction(nameof(Index), new { serviceId, key = keyFilter });
|
||||
}
|
||||
|
||||
[HttpGet("{definitionId:guid}/delete")]
|
||||
public async Task<IActionResult> ConfirmDefinitionDelete([FromRoute] Guid serviceId, [FromRoute] Guid definitionId,
|
||||
[FromQuery] string? keyFilter, CancellationToken ct)
|
||||
{
|
||||
var model = await DefinitionDeleteModelAsync(serviceId, definitionId, keyFilter, ct);
|
||||
return model is null ? NotFound() : View("DeleteDefinition", model);
|
||||
}
|
||||
|
||||
[HttpPost("{definitionId:guid}/delete")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteDefinition([FromRoute] Guid serviceId, [FromRoute] Guid definitionId,
|
||||
EmailTemplateDefinitionDeleteViewModel model, CancellationToken ct)
|
||||
{
|
||||
var current = await DefinitionDeleteModelAsync(serviceId, definitionId, model.KeyFilter, ct);
|
||||
if (current is null)
|
||||
return NotFound();
|
||||
if (!ModelState.IsValid || !model.ConfirmDelete)
|
||||
return await DefinitionDeleteErrorAsync(serviceId, definitionId, model.KeyFilter, "Confirm deletion of this template and its translations to continue.", ct);
|
||||
try
|
||||
{
|
||||
var result = await mediator.Send(new DeleteEmailTemplateDefinitionCommand(serviceId, current.Key, model.Revision), ct);
|
||||
if (result.IsSuccess)
|
||||
return RedirectToAction(nameof(Index), new { serviceId, key = model.KeyFilter });
|
||||
return await DefinitionDeleteErrorAsync(serviceId, definitionId, model.KeyFilter, result.Error!.Message, ct);
|
||||
}
|
||||
catch (Exception error) when (error is not OperationCanceledException)
|
||||
{
|
||||
logger.LogError(error, "Failed to delete email template definition.");
|
||||
return await DefinitionDeleteErrorAsync(serviceId, definitionId, model.KeyFilter, "Could not complete deletion. Review the current template before trying again.", ct);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<EmailTemplateDefinitionDeleteViewModel?> DefinitionDeleteModelAsync(Guid serviceId, Guid definitionId, string? keyFilter, CancellationToken ct)
|
||||
{
|
||||
var service = await services.GetAsync(serviceId, ct);
|
||||
var definition = await OwnedDefinitionAsync(service, definitionId, ct);
|
||||
return definition is null ? null : new EmailTemplateDefinitionDeleteViewModel
|
||||
{
|
||||
ServiceId = serviceId, DefinitionId = definition.Id, ServiceName = definition.ServiceName, Key = definition.Key,
|
||||
Revision = definition.Revision, KeyFilter = keyFilter, LanguageCodes = definition.Languages.Select(l => l.LanguageCode).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<IActionResult> DefinitionDeleteErrorAsync(Guid serviceId, Guid definitionId, string? keyFilter, string error, CancellationToken ct)
|
||||
{
|
||||
var model = await DefinitionDeleteModelAsync(serviceId, definitionId, keyFilter, ct);
|
||||
if (model is null)
|
||||
return NotFound();
|
||||
ModelState.Clear();
|
||||
ModelState.AddModelError("", error);
|
||||
return View("DeleteDefinition", model);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> SaveDefinitionAsync(EmailTemplateDefinition definition, EmailTemplateEditViewModel model,
|
||||
NotificationServiceInfo service, CancellationToken ct)
|
||||
{
|
||||
@@ -117,7 +171,7 @@ public sealed class AdminTemplatesController(IMediator mediator, IEmailTemplateD
|
||||
{
|
||||
if (service is null)
|
||||
return null;
|
||||
return (await definitions.GetDefinitionsAsync(service.Name, ct: ct))
|
||||
return (await definitions.GetDefinitionsAsync(service.Id, ct))
|
||||
.SingleOrDefault(d => d.Id == definitionId && d.ServiceId == service.Id);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user