From 2c3d2379eed4c3564f8ebdaaa6b32dc3ebb5a16a Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Wed, 27 Aug 2025 14:19:39 +0200 Subject: [PATCH] Improve private email domain documentation in apps (#1150) --- .../popup/components/EmailDomainField.tsx | 2 +- .../src/utils/SqliteClient.ts | 1 + .../components/form/EmailDomainField.tsx | 2 +- apps/mobile-app/utils/SqliteClient.tsx | 1 + apps/server/AliasVault.Admin/Program.cs | 4 +- apps/server/AliasVault.Api/Program.cs | 2 +- .../Main/Pages/Settings/General.razor | 44 +++++++++++++++++-- .../Pages/Main/Settings/General.en.resx | 4 ++ .../Services/CredentialService.cs | 2 + .../Services/Database/DbService.cs | 16 ++++++- .../AliasVault.SmtpService/Program.cs | 2 +- 11 files changed, 69 insertions(+), 11 deletions(-) diff --git a/apps/browser-extension/src/entrypoints/popup/components/EmailDomainField.tsx b/apps/browser-extension/src/entrypoints/popup/components/EmailDomainField.tsx index de01ee1cf..e30702fea 100644 --- a/apps/browser-extension/src/entrypoints/popup/components/EmailDomainField.tsx +++ b/apps/browser-extension/src/entrypoints/popup/components/EmailDomainField.tsx @@ -64,7 +64,7 @@ const EmailDomainField: React.FC = ({ // Check if private domains are available and valid const showPrivateDomains = useMemo(() => { return privateEmailDomains.length > 0 && - !(privateEmailDomains.length === 1 && privateEmailDomains[0] === 'DISABLED.TLD'); + !(privateEmailDomains.length === 1 && (privateEmailDomains[0] === 'DISABLED.TLD' || privateEmailDomains[0] === '')); }, [privateEmailDomains]); // Initialize state from value prop diff --git a/apps/browser-extension/src/utils/SqliteClient.ts b/apps/browser-extension/src/utils/SqliteClient.ts index cc6ec9165..5ff80e52f 100644 --- a/apps/browser-extension/src/utils/SqliteClient.ts +++ b/apps/browser-extension/src/utils/SqliteClient.ts @@ -357,6 +357,7 @@ export class SqliteClient { const isValidDomain = (domain: string): boolean => { return Boolean(domain && domain !== 'DISABLED.TLD' && + domain !== '' && (privateEmailDomains.includes(domain) || publicEmailDomains.includes(domain))); }; diff --git a/apps/mobile-app/components/form/EmailDomainField.tsx b/apps/mobile-app/components/form/EmailDomainField.tsx index 10b3e1b9a..5deb7f661 100644 --- a/apps/mobile-app/components/form/EmailDomainField.tsx +++ b/apps/mobile-app/components/form/EmailDomainField.tsx @@ -71,7 +71,7 @@ export const EmailDomainField: React.FC = ({ // Check if private domains are available and valid const showPrivateDomains = useMemo(() => { return privateEmailDomains.length > 0 && - !(privateEmailDomains.length === 1 && privateEmailDomains[0] === 'DISABLED.TLD'); + !(privateEmailDomains.length === 1 && (privateEmailDomains[0] === 'DISABLED.TLD' || privateEmailDomains[0] === '')); }, [privateEmailDomains]); // Initialize state from value prop diff --git a/apps/mobile-app/utils/SqliteClient.tsx b/apps/mobile-app/utils/SqliteClient.tsx index a26c383d6..e67e3d855 100644 --- a/apps/mobile-app/utils/SqliteClient.tsx +++ b/apps/mobile-app/utils/SqliteClient.tsx @@ -81,6 +81,7 @@ class SqliteClient { const isValidDomain = (domain: string): boolean => { return Boolean(domain && domain !== 'DISABLED.TLD' && + domain !== '' && (privateEmailDomains?.includes(domain) || publicEmailDomains?.includes(domain))); }; diff --git a/apps/server/AliasVault.Admin/Program.cs b/apps/server/AliasVault.Admin/Program.cs index e21bac30c..7e428057f 100644 --- a/apps/server/AliasVault.Admin/Program.cs +++ b/apps/server/AliasVault.Admin/Program.cs @@ -55,6 +55,8 @@ config.IpLoggingEnabled = bool.Parse(ipLoggingEnabled); builder.Services.AddSingleton(config); builder.Services.AddSingleton(sp => sp.GetRequiredService()); +builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddAliasVaultDataProtection("AliasVault.Admin"); // Add services to the container. @@ -88,8 +90,6 @@ builder.Services.ConfigureApplicationCookie(options => options.LoginPath = "/user/login"; }); -builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddIdentityCore(options => { options.Password.RequireDigit = false; diff --git a/apps/server/AliasVault.Api/Program.cs b/apps/server/AliasVault.Api/Program.cs index c3fd6e053..2be6434eb 100644 --- a/apps/server/AliasVault.Api/Program.cs +++ b/apps/server/AliasVault.Api/Program.cs @@ -56,6 +56,7 @@ builder.Services.AddSingleton(sp => sp.GetRequiredService( builder.Services.ConfigureLogging(builder.Configuration, Assembly.GetExecutingAssembly().GetName().Name!, "../../logs"); +builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration); builder.Services.AddAliasVaultDataProtection("AliasVault.Api"); builder.Services.AddSingleton(); builder.Services.AddScoped(); @@ -71,7 +72,6 @@ builder.Services.AddLogging(logging => logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Error); }); -builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration); builder.Services.AddIdentity(options => { options.Password.RequireDigit = false; diff --git a/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor b/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor index fdf753ddf..052ae2d4c 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor @@ -18,7 +18,7 @@
- + @Localizer["DefaultEmailDomainDescription"] @Localizer["DefaultEmailDomainDescriptionNote"] @Localizer["DefaultEmailDomainLearnMore"].
@@ -122,7 +127,6 @@ private List PrivateDomains => Config.PrivateEmailDomains; private List PublicDomains => Config.PublicEmailDomains; - private bool ShowPrivateDomains => PrivateDomains.Count > 0 && !(PrivateDomains.Count == 1 && PrivateDomains[0] == "DISABLED.TLD"); private string DefaultEmailDomain { get; set; } = string.Empty; private bool AutoEmailRefresh { get; set; } @@ -140,7 +144,7 @@ DefaultEmailDomain = DbService.Settings.DefaultEmailDomain; if (DefaultEmailDomain == string.Empty) { - if (PrivateDomains.Count > 0) + if (HasValidPrivateDomains()) { DefaultEmailDomain = PrivateDomains[0]; } @@ -209,4 +213,36 @@ await DbService.Settings.SetClipboardClearSeconds(ClipboardClearSeconds); StateHasChanged(); } + + /// + /// Checks if the private domains are valid. + /// + private bool HasValidPrivateDomains() + { + if (PrivateDomains.Count == 0) { + return false; + } + + if (PrivateDomains.Count == 1) + { + var singleDomain = PrivateDomains[0]; + + // If the domain is empty, return false. + if (string.IsNullOrWhiteSpace(singleDomain)) + { + return false; + } + + // TODO: "DISABLED.TLD" was a placeholder used < 0.22.0 that has been replaced by an empty string. + // That value is still here for legacy purposes, but it can be removed from the codebase in a future release. + if (singleDomain == "DISABLED.TLD") + { + return false; + } + + return true; + } + + return true; + } } diff --git a/apps/server/AliasVault.Client/Resources/Pages/Main/Settings/General.en.resx b/apps/server/AliasVault.Client/Resources/Pages/Main/Settings/General.en.resx index 8d69680ad..4522a12a8 100644 --- a/apps/server/AliasVault.Client/Resources/Pages/Main/Settings/General.en.resx +++ b/apps/server/AliasVault.Client/Resources/Pages/Main/Settings/General.en.resx @@ -59,6 +59,10 @@ Private Domains Label for private domains group + + No private email domains configured + Label for private domains group when no private email domains are configured + Public Domains Label for public domains group diff --git a/apps/server/AliasVault.Client/Services/CredentialService.cs b/apps/server/AliasVault.Client/Services/CredentialService.cs index 0d3424db1..348bb96fd 100644 --- a/apps/server/AliasVault.Client/Services/CredentialService.cs +++ b/apps/server/AliasVault.Client/Services/CredentialService.cs @@ -105,6 +105,8 @@ public sealed class CredentialService(HttpClient httpClient, DbService dbService var defaultDomain = dbService.Settings.DefaultEmailDomain; // Function to check if a domain is valid + // TODO: "DISABLED.TLD" was a placeholder used < 0.22.0 that has been replaced by an empty string. + // That value is still here for legacy purposes, but it can be removed from the codebase in a future release. bool IsValidDomain(string domain) => !string.IsNullOrEmpty(domain) && domain != "DISABLED.TLD" && diff --git a/apps/server/AliasVault.Client/Services/Database/DbService.cs b/apps/server/AliasVault.Client/Services/Database/DbService.cs index e95ef7d0c..413845c9a 100644 --- a/apps/server/AliasVault.Client/Services/Database/DbService.cs +++ b/apps/server/AliasVault.Client/Services/Database/DbService.cs @@ -506,10 +506,24 @@ public sealed class DbService : IDisposable if (_config.PrivateEmailDomains.Count == 0) { - // No private email domains known, so there are no email claims. return []; } + if (_config.PrivateEmailDomains.Count == 1) + { + if (string.IsNullOrWhiteSpace(_config.PrivateEmailDomains[0])) + { + return []; + } + + // TODO: "DISABLED.TLD" was a placeholder used < 0.22.0 that has been replaced by an empty string. + // That value is still here for legacy purposes, but it can be removed from the codebase in a future release. + if (_config.PrivateEmailDomains[0] == "DISABLED.TLD") + { + return []; + } + } + // Filter the list of email addresses to only include those that are in the supported private email domains. return emailAddresses.Where(email => _config.PrivateEmailDomains.Exists(domain => email.EndsWith(domain))).ToList(); } diff --git a/apps/server/Services/AliasVault.SmtpService/Program.cs b/apps/server/Services/AliasVault.SmtpService/Program.cs index 6cae4c0ff..06ec818c8 100644 --- a/apps/server/Services/AliasVault.SmtpService/Program.cs +++ b/apps/server/Services/AliasVault.SmtpService/Program.cs @@ -32,7 +32,7 @@ builder.Services.ConfigureLogging(builder.Configuration, Assembly.GetExecutingAs // Create global config object, get values from environment variables. Config config = new Config(); -var emailDomains = Environment.GetEnvironmentVariable("PRIVATE_EMAIL_DOMAINS") ?? "DISABLED.TLD"; +var emailDomains = Environment.GetEnvironmentVariable("PRIVATE_EMAIL_DOMAINS") ?? string.Empty; config.AllowedToDomains = emailDomains.Split(',').ToList(); var tlsEnabled = Environment.GetEnvironmentVariable("SMTP_TLS_ENABLED") ?? "false";