fix(admin): filter template keys by substring
Ref: IT-1627
This commit was merged in pull request #32.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace HrynCo.NotificationService.Web.IntegrationTests;
|
||||
|
||||
public sealed class TemplateKeyFilterTests(TemplateDatabaseFixture fixture) : IClassFixture<TemplateDatabaseFixture>
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("contact", true, false)]
|
||||
[InlineData(" CONTACT ", true, false)]
|
||||
[InlineData("", true, true)]
|
||||
[InlineData(" ", true, true)]
|
||||
[InlineData("missing", false, false)]
|
||||
[InlineData("%", false, false)]
|
||||
public async Task AdminFilterMatchesLiteralSubstringAcrossBothChannels(string filter, bool contacts, bool other)
|
||||
{
|
||||
await using var c = await DefinitionApiTestContext.CreateAsync(fixture);
|
||||
await c.UpsertAsync(DefinitionApiTestContext.Body(null, "en"), "TrustedContactAdded");
|
||||
await c.UpsertAsync(DefinitionApiTestContext.Body(null, "en"), "PasswordReset");
|
||||
using var scope = c.App.Services.CreateScope();
|
||||
var pushes = scope.ServiceProvider.GetRequiredService<IPushTemplateDefinitionRepository>();
|
||||
await pushes.SaveAsync(new PushTemplateDefinition { ServiceId = c.ServiceId, Key = "TrustedContactRemoved" }, true);
|
||||
var html = await c.Client.GetStringAsync($"/admin/services/{c.ServiceId}?key={Uri.EscapeDataString(filter)}");
|
||||
Assert.Equal(contacts, html.Contains(">TrustedContactAdded<", StringComparison.Ordinal));
|
||||
Assert.Equal(contacts, html.Contains(">TrustedContactRemoved<", StringComparison.Ordinal));
|
||||
Assert.Equal(other, html.Contains(">PasswordReset<", StringComparison.Ordinal));
|
||||
Assert.Contains("Clear", html);
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await c.Client.GetAsync(c.DefinitionUrl("contact"))).StatusCode);
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,11 @@ public sealed class AdminTemplatesController(IMediator mediator, IEmailTemplateD
|
||||
ModelState.AddModelError("", previousError);
|
||||
try
|
||||
{
|
||||
var filter = key?.Trim() ?? "";
|
||||
model.PushDefinitions = (await pushes.GetDefinitionsAsync(serviceId, ct))
|
||||
.Where(d => string.IsNullOrWhiteSpace(key) || d.Key == key).ToList();
|
||||
model.Definitions = (await definitions.GetDefinitionsAsync(service.Name, key, ct))
|
||||
.Where(d => d.ServiceId == serviceId).ToList();
|
||||
.Where(d => d.Key.Contains(filter, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
model.Definitions = (await definitions.GetDefinitionsAsync(serviceId, ct))
|
||||
.Where(d => d.Key.Contains(filter, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
}
|
||||
catch (Exception error) when (error is not OperationCanceledException)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<form method="get" action="/admin/services/@serviceId" class="template-key-filter">
|
||||
<label for="key" class="form-label fw-semibold">Template Key</label>
|
||||
<div class="template-key-filter-controls">
|
||||
<input id="key" name="key" value="@keyFilter" class="form-control form-control-sm" placeholder="Filter by key" />
|
||||
<input id="key" name="key" value="@keyFilter" class="form-control form-control-sm" placeholder="Filter by part of key" />
|
||||
<button type="submit" class="btn btn-primary btn-sm">Filter</button>
|
||||
<a href="/admin/services/@serviceId" class="btn btn-outline-secondary btn-sm">Clear</a>
|
||||
</div>
|
||||
|
||||
@@ -342,3 +342,13 @@ verification, and authorized stopping the Rider Web process. The Rider process w
|
||||
stopped. A second background Web launch was rejected by the execution tool with only
|
||||
`blocked by policy`; this is an execution-tool restriction, not a request for more
|
||||
owner permission. The automated API/PostgreSQL checks remain available.
|
||||
|
||||
## Administration key substring filter (2026-10-31)
|
||||
|
||||
The service Templates page filters both Email and Push definitions by a literal,
|
||||
case-insensitive substring of Template Key. Leading/trailing search whitespace is
|
||||
ignored; empty/whitespace-only input and Clear show the full service catalog.
|
||||
For example, `contact` matches `TrustedContactAdded` and `trusted_contact_removed`.
|
||||
`%` and `_` are ordinary characters, not SQL wildcard patterns. The filter stays in
|
||||
navigation links as before. Exact template identity, management API reads and delivery
|
||||
lookups are unchanged; substring matching is limited to this administration list.
|
||||
|
||||
Reference in New Issue
Block a user