diff --git a/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor b/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor
index 39cd5428d..e6b5252b7 100644
--- a/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor
+++ b/apps/server/AliasVault.Client/Main/Pages/Settings/General.razor
@@ -3,6 +3,7 @@
@inject LanguageService LanguageService
@using Microsoft.Extensions.Localization
@using AliasVault.Client.Services
+@using AliasVault.Client.Services.JsInterop.Models
@Localizer["PageTitle"]
@@ -12,6 +13,22 @@
Description="@Localizer["PageDescription"]">
+
@Localizer["AppLanguageTitle"]
+
+
+
+
+
+ @Localizer["AppLanguageDescription"]
+
+
+
+
@Localizer["EmailSettingsTitle"]
@@ -50,23 +67,6 @@
-
-
@Localizer["AppLanguageTitle"]
-
-
-
-
-
- @Localizer["AppLanguageDescription"]
-
-
-
-
@Localizer["AliasSettingsTitle"]
@@ -75,6 +75,7 @@
@Localizer["AliasGenerationLanguageDescription"]
@@ -92,6 +93,21 @@
@Localizer["AliasGenerationGenderDescription"]
+
+
+
+
+
+ @Localizer["AliasGenerationAgeRangeDescription"]
+
+
@@ -134,8 +150,10 @@
private bool AutoEmailRefresh { get; set; }
private string DefaultIdentityLanguage { get; set; } = string.Empty;
private string DefaultIdentityGender { get; set; } = string.Empty;
+ private string DefaultIdentityAgeRange { get; set; } = string.Empty;
private string AppLanguage { get; set; } = string.Empty;
private int ClipboardClearSeconds { get; set; }
+ private List
AvailableAgeRanges { get; set; } = new();
///
protected override async Task OnInitializedAsync()
@@ -143,6 +161,9 @@
await base.OnInitializedAsync();
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbTitle"] });
+ // Load available age ranges from JavaScript utility
+ AvailableAgeRanges = await JsInteropService.GetAvailableAgeRangesAsync();
+
DefaultEmailDomain = DbService.Settings.DefaultEmailDomain;
if (DefaultEmailDomain == string.Empty || Config.HiddenPrivateEmailDomains.Contains(DefaultEmailDomain))
{
@@ -158,6 +179,7 @@
AutoEmailRefresh = DbService.Settings.AutoEmailRefresh;
DefaultIdentityLanguage = DbService.Settings.DefaultIdentityLanguage;
DefaultIdentityGender = DbService.Settings.DefaultIdentityGender;
+ DefaultIdentityAgeRange = DbService.Settings.DefaultIdentityAgeRange;
AppLanguage = DbService.Settings.AppLanguage;
ClipboardClearSeconds = DbService.Settings.ClipboardClearSeconds;
}
@@ -198,6 +220,15 @@
StateHasChanged();
}
+ ///
+ /// Updates the default identity age range setting.
+ ///
+ private async Task UpdateDefaultIdentityAgeRange()
+ {
+ await DbService.Settings.SetDefaultIdentityAgeRange(DefaultIdentityAgeRange);
+ StateHasChanged();
+ }
+
///
/// Updates the app language setting.
///
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 47aaa89a0..bf13c0207 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
@@ -74,11 +74,11 @@
- Alias Settings
- Title for alias settings section
+ Identity Generator Settings
+ Title for identity generator settings section
- Alias generation language
+ Language
Label for alias generation language setting
@@ -93,8 +93,12 @@
Dutch
Dutch language option
+
+ German
+ German language option
+
- Alias generation gender
+ Gender
Label for alias generation gender setting
@@ -113,6 +117,14 @@
Female
Female gender option
+
+ Age range
+ Label for alias generation age range setting
+
+
+ Set the default age range for generating new identities. This affects the birthdate assigned to the generated identity.
+ Description for alias generation age range setting
+
diff --git a/apps/server/AliasVault.Client/Services/CredentialService.cs b/apps/server/AliasVault.Client/Services/CredentialService.cs
index 5dd22b8f0..8ffcd6c97 100644
--- a/apps/server/AliasVault.Client/Services/CredentialService.cs
+++ b/apps/server/AliasVault.Client/Services/CredentialService.cs
@@ -58,8 +58,11 @@ public sealed class CredentialService(HttpClient httpClient, DbService dbService
do
{
+ // Convert age range to birthdate options using shared JS utility
+ var birthdateOptions = await jsInteropService.ConvertAgeRangeToBirthdateOptionsAsync(dbService.Settings.DefaultIdentityAgeRange);
+
// Generate a random identity using the TypeScript library
- var identity = await jsInteropService.GenerateRandomIdentityAsync(dbService.Settings.DefaultIdentityLanguage, dbService.Settings.DefaultIdentityGender);
+ var identity = await jsInteropService.GenerateRandomIdentityAsync(dbService.Settings.DefaultIdentityLanguage, dbService.Settings.DefaultIdentityGender, birthdateOptions);
// Generate random values for the Identity properties
credential.Username = identity.NickName;
diff --git a/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs b/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
index b7dcca87c..4dc6a75d4 100644
--- a/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
+++ b/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
@@ -360,13 +360,61 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
return await jsRuntime.InvokeAsync("cryptoInterop.decryptBytes", base64Ciphertext, encryptionKey);
}
+ ///
+ /// Gets all available age range options from the shared JavaScript utility.
+ ///
+ /// Array of age range options.
+ public async Task> GetAvailableAgeRangesAsync()
+ {
+ try
+ {
+ if (_identityGeneratorModule == null)
+ {
+ await InitializeAsync();
+ }
+
+ var result = await _identityGeneratorModule!.InvokeAsync>("getAvailableAgeRanges");
+ return result ?? new List();
+ }
+ catch (JSException ex)
+ {
+ await Console.Error.WriteLineAsync($"JavaScript error getting age ranges: {ex.Message}");
+ return new List();
+ }
+ }
+
+ ///
+ /// Converts an age range string to birthdate options using the shared JavaScript utility.
+ ///
+ /// Age range string (e.g., "21-25", "30-35", or "random").
+ /// Birthdate options object or null if random.
+ public async Task