From 6a35ad4f98cf554e7e7ca47c7675f4a6b631e2bd Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Mon, 22 Sep 2025 20:01:50 +0200 Subject: [PATCH] Remove AuthLog UserAgent column, update DeviceIdentifier column length (#1260) --- .../(tabs)/settings/security/auth-logs.tsx | 1 - .../Security/SecurityController.cs | 1 - .../Components/RecentAuthLogsSection.razor | 2 - .../AliasVaultUserRefreshToken.cs | 1 - .../server/Databases/AliasServerDb/AuthLog.cs | 6 - ...427_RemoveUserAgentFromAuthLog.Designer.cs | 925 ++++++++++++++++++ ...250922173427_RemoveUserAgentFromAuthLog.cs | 28 + ...ngeDeviceIdentifierToTextField.Designer.cs | 924 +++++++++++++++++ ...73722_ChangeDeviceIdentifierToTextField.cs | 36 + .../AliasServerDbContextModelSnapshot.cs | 7 +- .../Models/WebApi/Security/AuthLogModel.cs | 5 - .../AliasVault.Auth/AuthLoggingService.cs | 2 - 12 files changed, 1914 insertions(+), 24 deletions(-) create mode 100644 apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.Designer.cs create mode 100644 apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.cs create mode 100644 apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.Designer.cs create mode 100644 apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.cs diff --git a/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx b/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx index e2f0ca0b0..70e68e6ff 100644 --- a/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx +++ b/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx @@ -168,7 +168,6 @@ export default function AuthLogsScreen() : React.ReactNode { {t('settings.securitySettings.authLogs.time')}: {formatDate(item.timestamp)} - {t('settings.securitySettings.authLogs.device')}: {item.userAgent} {t('settings.securitySettings.authLogs.ipAddress')}: {item.ipAddress} {t('settings.securitySettings.authLogs.client')}: {item.client} diff --git a/apps/server/AliasVault.Api/Controllers/Security/SecurityController.cs b/apps/server/AliasVault.Api/Controllers/Security/SecurityController.cs index 72127ee4a..80b16be00 100644 --- a/apps/server/AliasVault.Api/Controllers/Security/SecurityController.cs +++ b/apps/server/AliasVault.Api/Controllers/Security/SecurityController.cs @@ -112,7 +112,6 @@ public class SecurityController(IAliasServerDbContextFactory dbContextFactory, U EventType = x.EventType, Username = x.Username, IpAddress = x.IpAddress ?? string.Empty, - UserAgent = x.UserAgent ?? string.Empty, Client = x.Client ?? string.Empty, IsSuccess = x.IsSuccess, }) diff --git a/apps/server/AliasVault.Client/Main/Pages/Settings/Security/Components/RecentAuthLogsSection.razor b/apps/server/AliasVault.Client/Main/Pages/Settings/Security/Components/RecentAuthLogsSection.razor index 80045e0ed..b32587907 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Settings/Security/Components/RecentAuthLogsSection.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Settings/Security/Components/RecentAuthLogsSection.razor @@ -28,7 +28,6 @@ @Localizer["EventTypeColumn"] @Localizer["ClientColumn"] @Localizer["IpAddressColumn"] - @Localizer["DeviceColumn"] @Localizer["SuccessColumn"] @@ -40,7 +39,6 @@ @authLog.EventType @authLog.Client @authLog.IpAddress - @authLog.UserAgent } diff --git a/apps/server/Databases/AliasServerDb/AliasVaultUserRefreshToken.cs b/apps/server/Databases/AliasServerDb/AliasVaultUserRefreshToken.cs index cbe9e2428..269240af5 100644 --- a/apps/server/Databases/AliasServerDb/AliasVaultUserRefreshToken.cs +++ b/apps/server/Databases/AliasServerDb/AliasVaultUserRefreshToken.cs @@ -36,7 +36,6 @@ public class AliasVaultUserRefreshToken /// /// Gets or sets the device identifier (one token per device). /// - [StringLength(255)] public string DeviceIdentifier { get; set; } = null!; /// diff --git a/apps/server/Databases/AliasServerDb/AuthLog.cs b/apps/server/Databases/AliasServerDb/AuthLog.cs index 86f2f04d3..7a7738710 100644 --- a/apps/server/Databases/AliasServerDb/AuthLog.cs +++ b/apps/server/Databases/AliasServerDb/AuthLog.cs @@ -111,12 +111,6 @@ public class AuthLog [MaxLength(50)] public string? IpAddress { get; set; } - /// - /// Gets or sets the user agent string of the client used for the authentication event. - /// - [MaxLength(255)] - public string? UserAgent { get; set; } - /// /// Gets or sets the type of device used for the authentication event (e.g., Mobile, Desktop, Tablet). /// diff --git a/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.Designer.cs b/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.Designer.cs new file mode 100644 index 000000000..916d1bd15 --- /dev/null +++ b/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.Designer.cs @@ -0,0 +1,925 @@ +// +using System; +using AliasServerDb; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AliasServerDb.Migrations +{ + [DbContext(typeof(AliasServerDbContext))] + [Migration("20250922173427_RemoveUserAgentFromAuthLog")] + partial class RemoveUserAgentFromAuthLog + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.4") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AliasServerDb.AdminRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AdminRoles"); + }); + + modelBuilder.Entity("AliasServerDb.AdminUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastPasswordChanged") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AdminUsers"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AliasVaultRoles"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Blocked") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastActivityDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxEmailAgeDays") + .HasColumnType("integer"); + + b.Property("MaxEmails") + .HasColumnType("integer"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AliasVaultUsers"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceIdentifier") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExpireDate") + .HasMaxLength(255) + .HasColumnType("timestamp with time zone"); + + b.Property("IpAddress") + .HasMaxLength(45) + .HasColumnType("character varying(45)"); + + b.Property("PreviousTokenValue") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AliasVaultUserRefreshTokens"); + }); + + modelBuilder.Entity("AliasServerDb.AuthLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdditionalInfo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Browser") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Client") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DeviceType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventType") + .HasColumnType("integer"); + + b.Property("FailureReason") + .HasColumnType("integer"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("IsSuccess") + .HasColumnType("boolean"); + + b.Property("IsSuspiciousActivity") + .HasColumnType("boolean"); + + b.Property("OperatingSystem") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RequestPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "EventType" }, "IX_EventType"); + + b.HasIndex(new[] { "IpAddress" }, "IX_IpAddress"); + + b.HasIndex(new[] { "Timestamp" }, "IX_Timestamp"); + + b.HasIndex(new[] { "Username", "IsSuccess", "Timestamp" }, "IX_Username_IsSuccess_Timestamp") + .IsDescending(false, false, true); + + b.HasIndex(new[] { "Username", "Timestamp" }, "IX_Username_Timestamp") + .IsDescending(false, true); + + b.ToTable("AuthLogs"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DateSystem") + .HasColumnType("timestamp with time zone"); + + b.Property("EncryptedSymmetricKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("From") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromDomain") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromLocal") + .IsRequired() + .HasColumnType("text"); + + b.Property("MessageHtml") + .HasColumnType("text"); + + b.Property("MessagePlain") + .HasColumnType("text"); + + b.Property("MessagePreview") + .HasColumnType("text"); + + b.Property("MessageSource") + .IsRequired() + .HasColumnType("text"); + + b.Property("PushNotificationSent") + .HasColumnType("boolean"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("To") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToDomain") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToLocal") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserEncryptionKeyId") + .HasMaxLength(255) + .HasColumnType("uuid"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("Date"); + + b.HasIndex("DateSystem"); + + b.HasIndex("PushNotificationSent"); + + b.HasIndex("ToLocal"); + + b.HasIndex("UserEncryptionKeyId"); + + b.HasIndex("Visible"); + + b.ToTable("Emails"); + }); + + modelBuilder.Entity("AliasServerDb.EmailAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bytes") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("EmailId") + .HasColumnType("integer"); + + b.Property("Filename") + .IsRequired() + .HasColumnType("text"); + + b.Property("Filesize") + .HasColumnType("integer"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EmailId"); + + b.ToTable("EmailAttachments"); + }); + + modelBuilder.Entity("AliasServerDb.Log", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Application") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Exception") + .IsRequired() + .HasColumnType("text"); + + b.Property("Level") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogEvent") + .IsRequired() + .HasColumnType("text") + .HasColumnName("LogEvent"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("MessageTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("Properties") + .IsRequired() + .HasColumnType("text"); + + b.Property("SourceContext") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TimeStamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Application"); + + b.HasIndex("TimeStamp"); + + b.ToTable("Logs", (string)null); + }); + + modelBuilder.Entity("AliasServerDb.ServerSetting", b => + { + b.Property("Key") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("ServerSettings"); + }); + + modelBuilder.Entity("AliasServerDb.TaskRunnerJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EndTime") + .HasColumnType("time without time zone"); + + b.Property("ErrorMessage") + .HasColumnType("text"); + + b.Property("IsOnDemand") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("RunDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StartTime") + .HasColumnType("time without time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("TaskRunnerJobs"); + }); + + modelBuilder.Entity("AliasServerDb.UserEmailClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AddressDomain") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AddressLocal") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("Address") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserEmailClaims"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("PublicKey") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserEncryptionKeys"); + }); + + modelBuilder.Entity("AliasServerDb.Vault", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Client") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CredentialsCount") + .HasColumnType("integer"); + + b.Property("EmailClaimsCount") + .HasColumnType("integer"); + + b.Property("EncryptionSettings") + .IsRequired() + .HasColumnType("text"); + + b.Property("EncryptionType") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("integer"); + + b.Property("RevisionNumber") + .HasColumnType("bigint"); + + b.Property("Salt") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("VaultBlob") + .IsRequired() + .HasColumnType("text"); + + b.Property("Verifier") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Vaults"); + }); + + modelBuilder.Entity("AliasVault.WorkerStatus.Database.WorkerServiceStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrentStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DesiredStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Heartbeat") + .HasColumnType("timestamp with time zone"); + + b.Property("ServiceName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("WorkerServiceStatuses"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUserRefreshToken", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.HasOne("AliasServerDb.UserEncryptionKey", "EncryptionKey") + .WithMany("Emails") + .HasForeignKey("UserEncryptionKeyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EncryptionKey"); + }); + + modelBuilder.Entity("AliasServerDb.EmailAttachment", b => + { + b.HasOne("AliasServerDb.Email", "Email") + .WithMany("Attachments") + .HasForeignKey("EmailId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Email"); + }); + + modelBuilder.Entity("AliasServerDb.UserEmailClaim", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("EmailClaims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("EncryptionKeys") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.Vault", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("Vaults") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUser", b => + { + b.Navigation("EmailClaims"); + + b.Navigation("EncryptionKeys"); + + b.Navigation("Vaults"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.Navigation("Emails"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.cs b/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.cs new file mode 100644 index 000000000..0d1fa3aa6 --- /dev/null +++ b/apps/server/Databases/AliasServerDb/Migrations/20250922173427_RemoveUserAgentFromAuthLog.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AliasServerDb.Migrations +{ + /// + public partial class RemoveUserAgentFromAuthLog : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UserAgent", + table: "AuthLogs"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserAgent", + table: "AuthLogs", + type: "text", + nullable: true); + } + } +} diff --git a/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.Designer.cs b/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.Designer.cs new file mode 100644 index 000000000..30779d965 --- /dev/null +++ b/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.Designer.cs @@ -0,0 +1,924 @@ +// +using System; +using AliasServerDb; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AliasServerDb.Migrations +{ + [DbContext(typeof(AliasServerDbContext))] + [Migration("20250922173722_ChangeDeviceIdentifierToTextField")] + partial class ChangeDeviceIdentifierToTextField + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.4") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AliasServerDb.AdminRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AdminRoles"); + }); + + modelBuilder.Entity("AliasServerDb.AdminUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastPasswordChanged") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AdminUsers"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AliasVaultRoles"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Blocked") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastActivityDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MaxEmailAgeDays") + .HasColumnType("integer"); + + b.Property("MaxEmails") + .HasColumnType("integer"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AliasVaultUsers"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceIdentifier") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpireDate") + .HasMaxLength(255) + .HasColumnType("timestamp with time zone"); + + b.Property("IpAddress") + .HasMaxLength(45) + .HasColumnType("character varying(45)"); + + b.Property("PreviousTokenValue") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AliasVaultUserRefreshTokens"); + }); + + modelBuilder.Entity("AliasServerDb.AuthLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdditionalInfo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Browser") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Client") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DeviceType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventType") + .HasColumnType("integer"); + + b.Property("FailureReason") + .HasColumnType("integer"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("IsSuccess") + .HasColumnType("boolean"); + + b.Property("IsSuspiciousActivity") + .HasColumnType("boolean"); + + b.Property("OperatingSystem") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RequestPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "EventType" }, "IX_EventType"); + + b.HasIndex(new[] { "IpAddress" }, "IX_IpAddress"); + + b.HasIndex(new[] { "Timestamp" }, "IX_Timestamp"); + + b.HasIndex(new[] { "Username", "IsSuccess", "Timestamp" }, "IX_Username_IsSuccess_Timestamp") + .IsDescending(false, false, true); + + b.HasIndex(new[] { "Username", "Timestamp" }, "IX_Username_Timestamp") + .IsDescending(false, true); + + b.ToTable("AuthLogs"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DateSystem") + .HasColumnType("timestamp with time zone"); + + b.Property("EncryptedSymmetricKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("From") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromDomain") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromLocal") + .IsRequired() + .HasColumnType("text"); + + b.Property("MessageHtml") + .HasColumnType("text"); + + b.Property("MessagePlain") + .HasColumnType("text"); + + b.Property("MessagePreview") + .HasColumnType("text"); + + b.Property("MessageSource") + .IsRequired() + .HasColumnType("text"); + + b.Property("PushNotificationSent") + .HasColumnType("boolean"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("To") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToDomain") + .IsRequired() + .HasColumnType("text"); + + b.Property("ToLocal") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserEncryptionKeyId") + .HasMaxLength(255) + .HasColumnType("uuid"); + + b.Property("Visible") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("Date"); + + b.HasIndex("DateSystem"); + + b.HasIndex("PushNotificationSent"); + + b.HasIndex("ToLocal"); + + b.HasIndex("UserEncryptionKeyId"); + + b.HasIndex("Visible"); + + b.ToTable("Emails"); + }); + + modelBuilder.Entity("AliasServerDb.EmailAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bytes") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("EmailId") + .HasColumnType("integer"); + + b.Property("Filename") + .IsRequired() + .HasColumnType("text"); + + b.Property("Filesize") + .HasColumnType("integer"); + + b.Property("MimeType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EmailId"); + + b.ToTable("EmailAttachments"); + }); + + modelBuilder.Entity("AliasServerDb.Log", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Application") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Exception") + .IsRequired() + .HasColumnType("text"); + + b.Property("Level") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LogEvent") + .IsRequired() + .HasColumnType("text") + .HasColumnName("LogEvent"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("MessageTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("Properties") + .IsRequired() + .HasColumnType("text"); + + b.Property("SourceContext") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TimeStamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Application"); + + b.HasIndex("TimeStamp"); + + b.ToTable("Logs", (string)null); + }); + + modelBuilder.Entity("AliasServerDb.ServerSetting", b => + { + b.Property("Key") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("ServerSettings"); + }); + + modelBuilder.Entity("AliasServerDb.TaskRunnerJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EndTime") + .HasColumnType("time without time zone"); + + b.Property("ErrorMessage") + .HasColumnType("text"); + + b.Property("IsOnDemand") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("RunDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StartTime") + .HasColumnType("time without time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("TaskRunnerJobs"); + }); + + modelBuilder.Entity("AliasServerDb.UserEmailClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AddressDomain") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AddressLocal") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("Address") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserEmailClaims"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("PublicKey") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserEncryptionKeys"); + }); + + modelBuilder.Entity("AliasServerDb.Vault", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Client") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CredentialsCount") + .HasColumnType("integer"); + + b.Property("EmailClaimsCount") + .HasColumnType("integer"); + + b.Property("EncryptionSettings") + .IsRequired() + .HasColumnType("text"); + + b.Property("EncryptionType") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("integer"); + + b.Property("RevisionNumber") + .HasColumnType("bigint"); + + b.Property("Salt") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("VaultBlob") + .IsRequired() + .HasColumnType("text"); + + b.Property("Verifier") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Vaults"); + }); + + modelBuilder.Entity("AliasVault.WorkerStatus.Database.WorkerServiceStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrentStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DesiredStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Heartbeat") + .HasColumnType("timestamp with time zone"); + + b.Property("ServiceName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("WorkerServiceStatuses"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUserRefreshToken", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.HasOne("AliasServerDb.UserEncryptionKey", "EncryptionKey") + .WithMany("Emails") + .HasForeignKey("UserEncryptionKeyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EncryptionKey"); + }); + + modelBuilder.Entity("AliasServerDb.EmailAttachment", b => + { + b.HasOne("AliasServerDb.Email", "Email") + .WithMany("Attachments") + .HasForeignKey("EmailId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Email"); + }); + + modelBuilder.Entity("AliasServerDb.UserEmailClaim", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("EmailClaims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("EncryptionKeys") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.Vault", b => + { + b.HasOne("AliasServerDb.AliasVaultUser", "User") + .WithMany("Vaults") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AliasServerDb.AliasVaultUser", b => + { + b.Navigation("EmailClaims"); + + b.Navigation("EncryptionKeys"); + + b.Navigation("Vaults"); + }); + + modelBuilder.Entity("AliasServerDb.Email", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("AliasServerDb.UserEncryptionKey", b => + { + b.Navigation("Emails"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.cs b/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.cs new file mode 100644 index 000000000..2d3b4f226 --- /dev/null +++ b/apps/server/Databases/AliasServerDb/Migrations/20250922173722_ChangeDeviceIdentifierToTextField.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AliasServerDb.Migrations +{ + /// + public partial class ChangeDeviceIdentifierToTextField : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "DeviceIdentifier", + table: "AliasVaultUserRefreshTokens", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(255)", + oldMaxLength: 255); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "DeviceIdentifier", + table: "AliasVaultUserRefreshTokens", + type: "character varying(255)", + maxLength: 255, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + } + } +} diff --git a/apps/server/Databases/AliasServerDb/Migrations/AliasServerDbContextModelSnapshot.cs b/apps/server/Databases/AliasServerDb/Migrations/AliasServerDbContextModelSnapshot.cs index 8a8db46c9..23cf10910 100644 --- a/apps/server/Databases/AliasServerDb/Migrations/AliasServerDbContextModelSnapshot.cs +++ b/apps/server/Databases/AliasServerDb/Migrations/AliasServerDbContextModelSnapshot.cs @@ -202,8 +202,7 @@ namespace AliasServerDb.Migrations b.Property("DeviceIdentifier") .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasColumnType("text"); b.Property("ExpireDate") .HasMaxLength(255) @@ -289,10 +288,6 @@ namespace AliasServerDb.Migrations b.Property("Timestamp") .HasColumnType("timestamp with time zone"); - b.Property("UserAgent") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - b.Property("Username") .IsRequired() .HasMaxLength(255) diff --git a/apps/server/Shared/AliasVault.Shared/Models/WebApi/Security/AuthLogModel.cs b/apps/server/Shared/AliasVault.Shared/Models/WebApi/Security/AuthLogModel.cs index 44db8e135..4d551883e 100644 --- a/apps/server/Shared/AliasVault.Shared/Models/WebApi/Security/AuthLogModel.cs +++ b/apps/server/Shared/AliasVault.Shared/Models/WebApi/Security/AuthLogModel.cs @@ -39,11 +39,6 @@ public class AuthLogModel /// public string IpAddress { get; set; } = string.Empty; - /// - /// Gets or sets the user agent string of the device used for the authentication attempt. - /// - public string UserAgent { get; set; } = string.Empty; - /// /// Gets or sets the client application name and version. /// diff --git a/apps/server/Utilities/AliasVault.Auth/AuthLoggingService.cs b/apps/server/Utilities/AliasVault.Auth/AuthLoggingService.cs index 944b07602..0e7e89ae6 100644 --- a/apps/server/Utilities/AliasVault.Auth/AuthLoggingService.cs +++ b/apps/server/Utilities/AliasVault.Auth/AuthLoggingService.cs @@ -45,7 +45,6 @@ public class AuthLoggingService(IServiceProvider serviceProvider, IHttpContextAc IsSuccess = true, FailureReason = null, IpAddress = ipAddress, - UserAgent = httpContext?.Request.Headers.UserAgent, Client = clientHeader, RequestPath = httpContext?.Request.Path, DeviceType = DetermineDeviceType(httpContext), @@ -92,7 +91,6 @@ public class AuthLoggingService(IServiceProvider serviceProvider, IHttpContextAc IsSuccess = false, FailureReason = failureReason, IpAddress = ipAddress, - UserAgent = httpContext?.Request.Headers.UserAgent, Client = clientHeader, RequestPath = httpContext?.Request.Path, DeviceType = DetermineDeviceType(httpContext),