feat(notifications): OAuth2 authority/scope management + CLI + UI surfaces
Additive UpdateSmtpConfigCommand params (OAuth2Authority/OAuth2Scope), preserve-on-null handler application, CLI --oauth2-authority/--oauth2-scope on smtp update, Central UI text inputs shown only for the OAuth2 auth type, and the Component-NotificationService doc paragraph with M365 defaults. Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
@@ -1404,6 +1404,65 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
Assert.Equal("Basic", existing.AuthType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdateSmtpConfig_AppliesOAuth2AuthorityAndScope()
|
||||
{
|
||||
var notifRepo = Substitute.For<INotificationRepository>();
|
||||
var existing = new Commons.Entities.Notifications.SmtpConfiguration(
|
||||
"old.example.com", "OAuth2", "old@example.com")
|
||||
{
|
||||
Id = 1,
|
||||
Port = 25,
|
||||
OAuth2Authority = "https://old.authority/token",
|
||||
OAuth2Scope = "old.scope/.default",
|
||||
};
|
||||
notifRepo.GetSmtpConfigurationByIdAsync(1, Arg.Any<CancellationToken>()).Returns(existing);
|
||||
_services.AddScoped(_ => notifRepo);
|
||||
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new UpdateSmtpConfigCommand(
|
||||
1, "new.example.com", 465, "OAuth2", "new@example.com",
|
||||
OAuth2Authority: "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
|
||||
OAuth2Scope: "https://outlook.office365.com/.default"),
|
||||
"Administrator");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
Assert.Equal(envelope.CorrelationId, response.CorrelationId);
|
||||
Assert.Equal("https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token", existing.OAuth2Authority);
|
||||
Assert.Equal("https://outlook.office365.com/.default", existing.OAuth2Scope);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdateSmtpConfig_WithNullOAuth2AuthorityAndScope_PreservesExistingValues()
|
||||
{
|
||||
var notifRepo = Substitute.For<INotificationRepository>();
|
||||
var existing = new Commons.Entities.Notifications.SmtpConfiguration(
|
||||
"old.example.com", "OAuth2", "old@example.com")
|
||||
{
|
||||
Id = 1,
|
||||
Port = 25,
|
||||
OAuth2Authority = "https://old.authority/token",
|
||||
OAuth2Scope = "old.scope/.default",
|
||||
};
|
||||
notifRepo.GetSmtpConfigurationByIdAsync(1, Arg.Any<CancellationToken>()).Returns(existing);
|
||||
_services.AddScoped(_ => notifRepo);
|
||||
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new UpdateSmtpConfigCommand(1, "new.example.com", 465, "OAuth2", "new@example.com"),
|
||||
"Administrator");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
Assert.Equal(envelope.CorrelationId, response.CorrelationId);
|
||||
Assert.Equal("https://old.authority/token", existing.OAuth2Authority);
|
||||
Assert.Equal("old.scope/.default", existing.OAuth2Scope);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// SMS Notifications (S5) — list Type discriminator + SMS-config management
|
||||
// ========================================================================
|
||||
|
||||
Reference in New Issue
Block a user