1c028313ba
Preserve the saved SMTP password when connection settings are unchanged and keep it out of admin forms. Ref: IT-1601
137 lines
6.4 KiB
C#
137 lines
6.4 KiB
C#
using System.Net;
|
|
using HrynCo.NotificationService.DAL.Abstract.Providers;
|
|
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
|
using HrynCo.NotificationService.DAL.EF;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace HrynCo.NotificationService.Web.IntegrationTests;
|
|
|
|
public sealed class AdminSmtpSaveTests(TemplateDatabaseFixture fixture) : IClassFixture<TemplateDatabaseFixture>
|
|
{
|
|
[Fact]
|
|
public async Task BlankPasswordKeepsSavedValueWhenOnlySenderChanges()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var channel = await SeedChannel(context);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var fields = TemplateEditorTestFields.Read(await client.GetStringAsync($"/admin/channels/{channel.Id}"));
|
|
fields["UseSsl"] = "true";
|
|
fields["Password"] = "";
|
|
fields["FromName"] = "Updated sender";
|
|
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
|
|
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
|
var saved = await ReadSettings(context, channel.Id);
|
|
Assert.Equal("saved-test-secret", saved.Password);
|
|
Assert.Equal("Updated sender", saved.FromName);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Host", "other.example.invalid")]
|
|
[InlineData("Port", "2525")]
|
|
[InlineData("Username", "other-user")]
|
|
[InlineData("UseSsl", "false")]
|
|
public async Task ChangedConnectionWithBlankPasswordIsRejected(string field, string value)
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var channel = await SeedChannel(context);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var fields = TemplateEditorTestFields.Read(await client.GetStringAsync($"/admin/channels/{channel.Id}"));
|
|
fields["UseSsl"] = "true";
|
|
fields["Password"] = "";
|
|
fields[field] = value;
|
|
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
var html = await response.Content.ReadAsStringAsync();
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
Assert.Contains("Enter the password to save changed SMTP connection settings.", html);
|
|
Assert.DoesNotContain("saved-test-secret", html);
|
|
var saved = await ReadSettings(context, channel.Id);
|
|
Assert.Equal("saved-test-secret", saved.Password);
|
|
Assert.Equal("smtp.example.invalid", saved.Host);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ExplicitPasswordCanReplaceSavedValue()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var channel = await SeedChannel(context);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var fields = TemplateEditorTestFields.Read(await client.GetStringAsync($"/admin/channels/{channel.Id}"));
|
|
fields["UseSsl"] = "true";
|
|
fields["Password"] = "replacement-test-secret";
|
|
fields["Host"] = "other.example.invalid";
|
|
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
|
|
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
|
var saved = await ReadSettings(context, channel.Id);
|
|
Assert.Equal("replacement-test-secret", saved.Password);
|
|
Assert.Equal("other.example.invalid", saved.Host);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task NewChannelStillRequiresPassword()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var fields = TemplateEditorTestFields.Read(await client.GetStringAsync("/admin/channels/create"));
|
|
fields["ServiceName"] = "NewTestService";
|
|
fields["Host"] = "smtp.example.invalid";
|
|
fields["Username"] = "test-user";
|
|
fields["FromEmail"] = "sender@example.invalid";
|
|
fields["FromName"] = "Sender";
|
|
fields["Password"] = "";
|
|
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
Assert.Contains("The Password field is required.", await response.Content.ReadAsStringAsync());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task InvalidFormDoesNotRenderEnteredPassword()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var channel = await SeedChannel(context);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var fields = TemplateEditorTestFields.Read(await client.GetStringAsync($"/admin/channels/{channel.Id}"));
|
|
fields["Password"] = "replacement-test-secret";
|
|
fields["FromEmail"] = "invalid-address";
|
|
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
var html = await response.Content.ReadAsStringAsync();
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
Assert.DoesNotContain("replacement-test-secret", html);
|
|
Assert.Equal("saved-test-secret", (await ReadSettings(context, channel.Id)).Password);
|
|
}
|
|
|
|
private static async Task<EmailChannel> SeedChannel(DefinitionApiTestContext context)
|
|
{
|
|
using var scope = context.App.Services.CreateScope();
|
|
var channel = new EmailChannel
|
|
{
|
|
ServiceName = "TestService", EmailChannelType = EmailChannelType.Smtp,
|
|
Settings = new SmtpChannelSettings
|
|
{
|
|
Host = "smtp.example.invalid", Port = 587, Username = "test-user",
|
|
Password = "saved-test-secret", UseSsl = true,
|
|
FromEmail = "sender@example.invalid", FromName = "Original sender"
|
|
}
|
|
};
|
|
await scope.ServiceProvider.GetRequiredService<IEmailChannelRepository>().AddAsync(channel);
|
|
await scope.ServiceProvider.GetRequiredService<NotificationDbContext>().SaveChangesAsync();
|
|
return channel;
|
|
}
|
|
|
|
private static async Task<SmtpChannelSettings> ReadSettings(DefinitionApiTestContext context, Guid id)
|
|
{
|
|
using var scope = context.App.Services.CreateScope();
|
|
var channel = await scope.ServiceProvider.GetRequiredService<IEmailChannelRepository>().GetByIdAsync(id);
|
|
return Assert.IsType<SmtpChannelSettings>(channel?.Settings);
|
|
}
|
|
}
|