feat(sms): export wizard SMS-config selection (S10c)
This commit is contained in:
@@ -138,6 +138,13 @@
|
||||
@RenderCheckboxList(_smtpConfigs, s => s.Id, s => s.Host, _selectedSmtpConfigs)
|
||||
</fieldset>
|
||||
|
||||
@* S10c: SMS provider configs, mirroring the SMTP section above. Labelled by
|
||||
AccountSid (the bundle key); the secret AuthToken is never rendered. *@
|
||||
<fieldset class="mb-4" data-testid="group-sms-configs">
|
||||
<legend class="h6">SMS Configurations</legend>
|
||||
@RenderCheckboxList(_smsConfigs, s => s.Id, s => s.AccountSid, _selectedSmsConfigs)
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="mb-4" data-testid="group-api-methods">
|
||||
<legend class="h6">API Methods</legend>
|
||||
@RenderCheckboxList(_apiMethods, m => m.Id, m => m.Name, _selectedApiMethods)
|
||||
@@ -354,6 +361,11 @@
|
||||
{
|
||||
<li>SmtpConfig: @s.Host</li>
|
||||
}
|
||||
@* S10c: SMS configs in the closure, mirroring SmtpConfig above; AccountSid only, never AuthToken. *@
|
||||
@foreach (var s in _resolved.SmsConfigs.OrderBy(s => s.AccountSid, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
<li>SmsConfig: @s.AccountSid</li>
|
||||
}
|
||||
@* Inbound API keys are not transported (re-arch C4) — methods only. *@
|
||||
@foreach (var m in _resolved.ApiMethods.OrderBy(m => m.Name, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -447,8 +459,8 @@
|
||||
{
|
||||
<div class="alert alert-warning" role="alert" data-testid="secrets-warning">
|
||||
<strong>@_secretCount</strong> secret @(_secretCount == 1 ? "field" : "fields")
|
||||
will be encrypted (external-system credentials, SMTP credentials, and database
|
||||
connection strings).
|
||||
will be encrypted (external-system credentials, SMTP credentials, SMS auth
|
||||
tokens, and database connection strings).
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -495,7 +507,7 @@
|
||||
<div class="alert alert-danger" data-testid="unencrypted-confirm">
|
||||
<strong>Unencrypted export</strong> — the bundle will contain all secret fields
|
||||
in plaintext. Anyone with the file can read external-system credentials, SMTP
|
||||
passwords, and database connection strings. The audit log will record this as
|
||||
passwords, SMS auth tokens, and database connection strings. The audit log will record this as
|
||||
<code>UnencryptedBundleExport</code>.
|
||||
<div class="mt-2 d-flex gap-2">
|
||||
<button class="btn btn-sm btn-danger" @onclick="ConfirmUnencryptedExport">
|
||||
|
||||
@@ -72,6 +72,9 @@ public partial class TransportExport : ComponentBase
|
||||
private List<DatabaseConnectionDefinition> _dbConnections = new();
|
||||
private List<NotificationList> _notificationLists = new();
|
||||
private List<SmtpConfiguration> _smtpConfigs = new();
|
||||
// S10c: SMS provider configs, mirroring _smtpConfigs. Keyed by AccountSid in the
|
||||
// bundle; the wizard selects by entity id (same as SMTP) and never surfaces AuthToken.
|
||||
private List<SmsConfiguration> _smsConfigs = new();
|
||||
// Inbound API keys are not transported between environments (re-arch C4); only methods.
|
||||
private List<ApiMethod> _apiMethods = new();
|
||||
// M8 (E1): site/instance-scoped export. Sites are listed flat; each site's
|
||||
@@ -90,6 +93,8 @@ public partial class TransportExport : ComponentBase
|
||||
private readonly HashSet<int> _selectedDbConnections = new();
|
||||
private readonly HashSet<int> _selectedNotificationLists = new();
|
||||
private readonly HashSet<int> _selectedSmtpConfigs = new();
|
||||
// S10c: SMS provider config selection, mirroring _selectedSmtpConfigs.
|
||||
private readonly HashSet<int> _selectedSmsConfigs = new();
|
||||
// No _selectedApiKeys: inbound API keys are not transported (re-arch C4).
|
||||
private readonly HashSet<int> _selectedApiMethods = new();
|
||||
// M8 (E1): site/instance selection backed by entity primary keys, matching the
|
||||
@@ -138,6 +143,8 @@ public partial class TransportExport : ComponentBase
|
||||
_dbConnections = (await ExternalRepo.GetAllDatabaseConnectionsAsync()).ToList();
|
||||
_notificationLists = (await NotificationRepo.GetAllNotificationListsAsync()).ToList();
|
||||
_smtpConfigs = (await NotificationRepo.GetAllSmtpConfigurationsAsync()).ToList();
|
||||
// S10c: SMS provider configs, mirroring the SMTP load path above.
|
||||
_smsConfigs = (await NotificationRepo.GetAllSmsConfigurationsAsync()).ToList();
|
||||
// Inbound API keys are not transported (re-arch C4) — only methods are loaded.
|
||||
_apiMethods = (await InboundApiRepo.GetAllApiMethodsAsync()).ToList();
|
||||
|
||||
@@ -199,6 +206,7 @@ public partial class TransportExport : ComponentBase
|
||||
|| _selectedDbConnections.Count > 0
|
||||
|| _selectedNotificationLists.Count > 0
|
||||
|| _selectedSmtpConfigs.Count > 0
|
||||
|| _selectedSmsConfigs.Count > 0
|
||||
|| _selectedApiMethods.Count > 0
|
||||
|| _selectedSites.Count > 0
|
||||
|| _selectedInstances.Count > 0;
|
||||
@@ -247,6 +255,9 @@ public partial class TransportExport : ComponentBase
|
||||
// already-selected owning site.
|
||||
SiteIds = _selectedSites.ToList(),
|
||||
InstanceIds = _selectedInstances.ToList(),
|
||||
// S10c: SMS provider config ids feed the resolver's SmsConfigurationIds,
|
||||
// exactly as SmtpConfigurationIds above (init-only, trailing additive shape).
|
||||
SmsConfigurationIds = _selectedSmsConfigs.ToList(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -314,6 +325,11 @@ public partial class TransportExport : ComponentBase
|
||||
{
|
||||
if (!string.IsNullOrEmpty(smtp.Credentials)) count++;
|
||||
}
|
||||
// S10c: SMS provider AuthToken is a secret, mirroring SMTP Credentials above.
|
||||
foreach (var sms in resolved.SmsConfigs)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sms.AuthToken)) count++;
|
||||
}
|
||||
foreach (var db in resolved.DatabaseConnections)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(db.ConnectionString)) count++;
|
||||
@@ -440,6 +456,7 @@ public partial class TransportExport : ComponentBase
|
||||
_selectedDbConnections.Clear();
|
||||
_selectedNotificationLists.Clear();
|
||||
_selectedSmtpConfigs.Clear();
|
||||
_selectedSmsConfigs.Clear();
|
||||
_selectedApiMethods.Clear();
|
||||
_selectedSites.Clear();
|
||||
_selectedInstances.Clear();
|
||||
|
||||
Reference in New Issue
Block a user