Improve private email domain documentation in apps (#1150)

This commit is contained in:
Leendert de Borst
2025-08-27 14:19:39 +02:00
committed by Leendert de Borst
parent 70ed03e1b3
commit 2c3d2379ee
11 changed files with 69 additions and 11 deletions

View File

@@ -64,7 +64,7 @@ const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
// 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

View File

@@ -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)));
};

View File

@@ -71,7 +71,7 @@ export const EmailDomainField: React.FC<EmailDomainFieldProps> = ({
// 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

View File

@@ -81,6 +81,7 @@ class SqliteClient {
const isValidDomain = (domain: string): boolean => {
return Boolean(domain &&
domain !== 'DISABLED.TLD' &&
domain !== '' &&
(privateEmailDomains?.includes(domain) || publicEmailDomains?.includes(domain)));
};

View File

@@ -55,6 +55,8 @@ config.IpLoggingEnabled = bool.Parse(ipLoggingEnabled);
builder.Services.AddSingleton(config);
builder.Services.AddSingleton<SharedConfig>(sp => sp.GetRequiredService<Config>());
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<AdminUser>(options =>
{
options.Password.RequireDigit = false;

View File

@@ -56,6 +56,7 @@ builder.Services.AddSingleton<SharedConfig>(sp => sp.GetRequiredService<Config>(
builder.Services.ConfigureLogging(builder.Configuration, Assembly.GetExecutingAssembly().GetName().Name!, "../../logs");
builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration);
builder.Services.AddAliasVaultDataProtection("AliasVault.Api");
builder.Services.AddSingleton<ITimeProvider, SystemTimeProvider>();
builder.Services.AddScoped<TimeValidationJwtBearerEvents>();
@@ -71,7 +72,6 @@ builder.Services.AddLogging(logging =>
logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Error);
});
builder.Services.AddAliasVaultDatabaseConfiguration(builder.Configuration);
builder.Services.AddIdentity<AliasVaultUser, AliasVaultRole>(options =>
{
options.Password.RequireDigit = false;

View File

@@ -18,7 +18,7 @@
<div class="mb-4">
<label for="defaultEmailDomain" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["DefaultEmailDomainLabel"]</label>
<select @bind="DefaultEmailDomain" @bind:after="UpdateDefaultEmailDomain" id="defaultEmailDomain" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
@if (ShowPrivateDomains)
@if (HasValidPrivateDomains())
{
<optgroup label="@Localizer["PrivateDomainsLabel"]">
@foreach (var domain in PrivateDomains)
@@ -27,6 +27,11 @@
}
</optgroup>
}
else {
<optgroup label="@Localizer["PrivateDomainsLabel"]">
<option disabled value="_">@Localizer["PrivateDomainsDisabledLabel"]</option>
</optgroup>
}
<optgroup label="@Localizer["PublicDomainsLabel"]">
@foreach (var domain in PublicDomains)
{
@@ -34,7 +39,7 @@
}
</optgroup>
</select>
<span class="block text-sm font-normal text-gray-500 dark:text-gray-400">
<span class="block text-sm font-normal text-gray-500 dark:text-gray-400 mt-2">
@Localizer["DefaultEmailDomainDescription"] @Localizer["DefaultEmailDomainDescriptionNote"] <a href="https://docs.aliasvault.net/misc/private-vs-public-email.html" class="text-primary-500 hover:text-primary-700 hover:underline" target="_blank" rel="noopener">@Localizer["DefaultEmailDomainLearnMore"]</a>.
</span>
</div>
@@ -122,7 +127,6 @@
private List<string> PrivateDomains => Config.PrivateEmailDomains;
private List<string> 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();
}
/// <summary>
/// Checks if the private domains are valid.
/// </summary>
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;
}
}

View File

@@ -59,6 +59,10 @@
<value>Private Domains</value>
<comment>Label for private domains group</comment>
</data>
<data name="PrivateDomainsDisabledLabel">
<value>No private email domains configured</value>
<comment>Label for private domains group when no private email domains are configured</comment>
</data>
<data name="PublicDomainsLabel">
<value>Public Domains</value>
<comment>Label for public domains group</comment>

View File

@@ -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" &&

View File

@@ -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();
}

View File

@@ -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";