fix(sms): repair S1 build breaks — null-filter EmailAddress projections + SiteNotificationRepository SMS stubs
S1 made NotificationRecipient.EmailAddress nullable + added SmsConfiguration and four INotificationRepository SMS methods, breaking compilation beyond the intentionally-deferred central NotificationRepository. Fix 1 (CS8620/CS8604 nullable EmailAddress projections, email-only paths): - NotificationOutbox EmailNotificationDeliveryAdapter: filter non-null emails - DeploymentManager ArtifactDeploymentService: filter non-null emails - Transport EntitySerializer: filter non-null emails into NotificationRecipientDto Fix 2 (CS0535): stub the four SMS-config methods on SiteRuntime SiteNotificationRepository (central-only — NotSupportedException, matching the existing 'Managed via artifact deployment from Central' write-path pattern). Doc nits: reword NotificationRecipient private ctor and SmsConfiguration.AuthToken comments. The central ConfigurationDatabase.NotificationRepository compile break is left as-is (S2 implements those four methods).
This commit is contained in:
@@ -71,8 +71,9 @@ public class NotificationRecipient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parameterless constructor used by EF Core materialization and the SMS factory, where the
|
/// Private parameterless constructor that backs the <see cref="ForSms"/> factory path,
|
||||||
/// contact field is assigned via property setters rather than constructor parameters.
|
/// where the contact field is assigned via property setters rather than constructor
|
||||||
|
/// parameters — without exposing a half-initialized public constructor to callers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private NotificationRecipient()
|
private NotificationRecipient()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ public class SmsConfiguration
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
/// <summary>Gets or sets the Twilio Account SID.</summary>
|
/// <summary>Gets or sets the Twilio Account SID.</summary>
|
||||||
public string AccountSid { get; set; }
|
public string AccountSid { get; set; }
|
||||||
/// <summary>Gets or sets the Twilio Auth Token (secret), or null when not applicable.</summary>
|
/// <summary>
|
||||||
|
/// Gets or sets the Twilio Auth Token (secret). Stored encrypted; null only transiently
|
||||||
|
/// during configuration, never a valid production value.
|
||||||
|
/// </summary>
|
||||||
public string? AuthToken { get; set; }
|
public string? AuthToken { get; set; }
|
||||||
/// <summary>Gets or sets the sender phone number (E.164) placed in the From field.</summary>
|
/// <summary>Gets or sets the sender phone number (E.164) placed in the From field.</summary>
|
||||||
public string FromNumber { get; set; }
|
public string FromNumber { get; set; }
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ public class ArtifactDeploymentService
|
|||||||
|
|
||||||
// Map notification lists
|
// Map notification lists
|
||||||
var notificationListArtifacts = notificationLists.Select(nl =>
|
var notificationListArtifacts = notificationLists.Select(nl =>
|
||||||
new NotificationListArtifact(nl.Name, nl.Recipients.Select(r => r.EmailAddress).ToList())).ToList();
|
new NotificationListArtifact(nl.Name, nl.Recipients.Where(r => r.EmailAddress is not null).Select(r => r.EmailAddress!).ToList())).ToList();
|
||||||
|
|
||||||
// Map SMTP configurations — use Host as the artifact name (matches SQLite PK on site)
|
// Map SMTP configurations — use Host as the artifact name (matches SQLite PK on site)
|
||||||
var smtpArtifacts = smtpConfigurations.Select(smtp =>
|
var smtpArtifacts = smtpConfigurations.Select(smtp =>
|
||||||
|
|||||||
+4
-1
@@ -106,7 +106,10 @@ public sealed class EmailNotificationDeliveryAdapter : INotificationDeliveryAdap
|
|||||||
return DeliveryOutcome.Permanent(addressError);
|
return DeliveryOutcome.Permanent(addressError);
|
||||||
}
|
}
|
||||||
|
|
||||||
var recipientAddresses = recipients.Select(r => r.EmailAddress).ToList();
|
var recipientAddresses = recipients
|
||||||
|
.Where(r => r.EmailAddress is not null)
|
||||||
|
.Select(r => r.EmailAddress!)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -193,6 +193,24 @@ public class SiteNotificationRepository : INotificationRepository
|
|||||||
public Task DeleteSmtpConfigurationAsync(int id, CancellationToken cancellationToken = default)
|
public Task DeleteSmtpConfigurationAsync(int id, CancellationToken cancellationToken = default)
|
||||||
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|
||||||
|
// ── SmsConfiguration (central-only — never deployed to or served from the site) ──
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<SmsConfiguration?> GetSmsConfigurationAsync(CancellationToken cancellationToken = default)
|
||||||
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<IReadOnlyList<SmsConfiguration>> GetAllSmsConfigurationsAsync(CancellationToken cancellationToken = default)
|
||||||
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task AddSmsConfigurationAsync(SmsConfiguration smsConfiguration, CancellationToken cancellationToken = default)
|
||||||
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task UpdateSmsConfigurationAsync(SmsConfiguration smsConfiguration, CancellationToken cancellationToken = default)
|
||||||
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
public Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
=> throw new NotSupportedException("Managed via artifact deployment from Central");
|
||||||
|
|||||||
@@ -138,9 +138,11 @@ public sealed class EntitySerializer
|
|||||||
NotificationLists: aggregate.NotificationLists.Select(nl => new NotificationListDto(
|
NotificationLists: aggregate.NotificationLists.Select(nl => new NotificationListDto(
|
||||||
Name: nl.Name,
|
Name: nl.Name,
|
||||||
Type: nl.Type,
|
Type: nl.Type,
|
||||||
Recipients: nl.Recipients.Select(r => new NotificationRecipientDto(
|
Recipients: nl.Recipients
|
||||||
Name: r.Name,
|
.Where(r => r.EmailAddress is not null)
|
||||||
EmailAddress: r.EmailAddress)).ToList())).ToList(),
|
.Select(r => new NotificationRecipientDto(
|
||||||
|
Name: r.Name,
|
||||||
|
EmailAddress: r.EmailAddress!)).ToList())).ToList(),
|
||||||
SmtpConfigs: aggregate.SmtpConfigurations.Select(smtp =>
|
SmtpConfigs: aggregate.SmtpConfigurations.Select(smtp =>
|
||||||
{
|
{
|
||||||
SecretsBlock? secrets = null;
|
SecretsBlock? secrets = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user