From ca6ecbb70549f756c41ccc66aed97da270046f4f Mon Sep 17 00:00:00 2001 From: Jonas Hendrickx Date: Mon, 8 Jul 2024 12:27:08 +0200 Subject: [PATCH 1/3] Verified indices for ApiKeys, Aliases, Credentials --- src/Service/Storage/Ef/DbGlobalContext.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Service/Storage/Ef/DbGlobalContext.cs b/src/Service/Storage/Ef/DbGlobalContext.cs index 1cb896f23..95f10250a 100644 --- a/src/Service/Storage/Ef/DbGlobalContext.cs +++ b/src/Service/Storage/Ef/DbGlobalContext.cs @@ -41,6 +41,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) v => JsonSerializer.Serialize(v, jsonOptions), v => JsonSerializer.Deserialize(v, jsonOptions)) .Metadata.SetValueComparer(new NullableArrayValueComparer()); + b.HasIndex(x => new { x.Tenant, x.UserId }) + .HasDatabaseName("IX_EFStoredCredential_Tenant_UserId"); }); modelBuilder.Entity() From a5b302a2292a959fb4f1ef29679be2509349785e Mon Sep 17 00:00:00 2001 From: Jonas Hendrickx Date: Tue, 9 Jul 2024 15:42:35 +0200 Subject: [PATCH 2/3] Add indices for hot code paths --- ...4147_AddIndicesForHotCodePaths.Designer.cs | 500 ++++++++++++++++++ ...0240709134147_AddIndicesForHotCodePaths.cs | 43 ++ .../Mssql/MsSqlContextModelSnapshot.cs | 7 +- ...4121_AddIndicesForHotCodePaths.Designer.cs | 495 +++++++++++++++++ ...0240709134121_AddIndicesForHotCodePaths.cs | 27 + .../Sqlite/SqliteContextModelSnapshot.cs | 5 +- 6 files changed, 1074 insertions(+), 3 deletions(-) create mode 100644 src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.Designer.cs create mode 100644 src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs create mode 100644 src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.Designer.cs create mode 100644 src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs diff --git a/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.Designer.cs b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.Designer.cs new file mode 100644 index 000000000..3806a013c --- /dev/null +++ b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.Designer.cs @@ -0,0 +1,500 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Passwordless.Service.Storage.Ef; + +#nullable disable + +namespace Passwordless.Service.Migrations.Mssql +{ + [DbContext(typeof(DbGlobalMsSqlContext))] + [Migration("20240709134147_AddIndicesForHotCodePaths")] + partial class AddIndicesForHotCodePaths + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Passwordless.Service.EventLog.Models.ApplicationEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApiKeyId") + .HasColumnType("nvarchar(max)"); + + b.Property("EventType") + .HasColumnType("int"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PerformedAt") + .HasColumnType("datetime2"); + + b.Property("PerformedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Severity") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationEvents"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AccountMetaInformation", b => + { + b.Property("AcountName") + .HasColumnType("nvarchar(450)"); + + b.Property("AdminEmailsSerialized") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeleteAt") + .HasColumnType("datetime2"); + + b.Property("Tenant") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("AcountName"); + + b.ToTable("AccountInfo"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AliasPointer", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("Alias") + .HasColumnType("nvarchar(450)"); + + b.Property("Plaintext") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Tenant", "Alias"); + + b.ToTable("Aliases"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.ApiKeyDesc", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApiKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("LastLockedAt") + .HasColumnType("datetime2"); + + b.Property("LastUnlockedAt") + .HasColumnType("datetime2"); + + b.Property("Scopes") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Tenant", "Id"); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("AllowAttestation") + .HasColumnType("bit"); + + b.Property("DeveloperLoggingEndsAt") + .HasColumnType("datetime2"); + + b.Property("EventLoggingIsEnabled") + .HasColumnType("bit"); + + b.Property("EventLoggingRetentionPeriod") + .HasColumnType("int"); + + b.Property("IsGenerateSignInTokenEndpointEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsMagicLinksEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("MagicLinkEmailMonthlyQuota") + .HasColumnType("int"); + + b.Property("MaxUsers") + .HasColumnType("bigint"); + + b.HasKey("Tenant"); + + b.ToTable("AppFeatures"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AuthenticationConfiguration", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("Purpose") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("EditedBy") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("EditedOn") + .HasColumnType("datetime2"); + + b.Property("LastUsedOn") + .HasColumnType("datetime2"); + + b.Property("TimeToLive") + .HasColumnType("float"); + + b.Property("UserVerificationRequirement") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Tenant", "Purpose"); + + b.ToTable("AuthenticationConfigurations"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.Authenticator", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("AaGuid") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("IsAllowed") + .HasColumnType("bit"); + + b.HasKey("Tenant", "AaGuid"); + + b.ToTable("Authenticators"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.DispatchedEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LinkTemplate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Tenant") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("Tenant"); + + b.ToTable("DispatchedEmails"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.EFStoredCredential", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("DescriptorId") + .HasColumnType("varbinary(900)"); + + b.Property("AaGuid") + .HasColumnType("uniqueidentifier"); + + b.Property("AttestationFmt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BackupState") + .HasColumnType("bit"); + + b.Property("Country") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DescriptorTransports") + .HasColumnType("nvarchar(max)"); + + b.Property("DescriptorType") + .HasColumnType("int"); + + b.Property("Device") + .HasColumnType("nvarchar(max)"); + + b.Property("IsBackupEligible") + .HasColumnType("bit"); + + b.Property("IsDiscoverable") + .HasColumnType("bit"); + + b.Property("LastUsedAt") + .HasColumnType("datetime2"); + + b.Property("Nickname") + .HasColumnType("nvarchar(max)"); + + b.Property("Origin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("RPID") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SignatureCounter") + .HasColumnType("bigint"); + + b.Property("UserHandle") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Tenant", "DescriptorId"); + + b.HasIndex("Tenant", "UserId") + .HasDatabaseName("IX_EFStoredCredential_Tenant_UserId"); + + b.ToTable("Credentials"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicActiveUserReport", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedAt") + .HasColumnType("date"); + + b.Property("DailyActiveUsersCount") + .HasColumnType("int"); + + b.Property("TotalUsersCount") + .HasColumnType("int"); + + b.Property("WeeklyActiveUsersCount") + .HasColumnType("int"); + + b.HasKey("Tenant", "CreatedAt"); + + b.ToTable("PeriodicActiveUserReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicCredentialReport", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedAt") + .HasColumnType("date"); + + b.Property("CredentialsCount") + .HasColumnType("int"); + + b.Property("UsersCount") + .HasColumnType("int"); + + b.HasKey("Tenant", "CreatedAt"); + + b.ToTable("PeriodicCredentialReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.TokenKey", b => + { + b.Property("Tenant") + .HasColumnType("nvarchar(450)"); + + b.Property("KeyId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("KeyMaterial") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Tenant", "KeyId"); + + b.ToTable("TokenKeys"); + }); + + modelBuilder.Entity("Passwordless.Service.EventLog.Models.ApplicationEvent", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("Events") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithOne("Features") + .HasForeignKey("Passwordless.Service.Models.AppFeature", "Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.Authenticator", b => + { + b.HasOne("Passwordless.Service.Models.AppFeature", "AppFeature") + .WithMany("Authenticators") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppFeature"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.DispatchedEmail", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("DispatchedEmails") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicActiveUserReport", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("PeriodicActiveUserReports") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicCredentialReport", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("PeriodicCredentialReports") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AccountMetaInformation", b => + { + b.Navigation("DispatchedEmails"); + + b.Navigation("Events"); + + b.Navigation("Features"); + + b.Navigation("PeriodicActiveUserReports"); + + b.Navigation("PeriodicCredentialReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.Navigation("Authenticators"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs new file mode 100644 index 000000000..db3dd46e3 --- /dev/null +++ b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Passwordless.Service.Migrations.Mssql +{ + /// + public partial class AddIndicesForHotCodePaths : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserId", + table: "Credentials", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.CreateIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials", + columns: new[] { "Tenant", "UserId" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials"); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "Credentials", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + } + } +} diff --git a/src/Service/Migrations/Mssql/MsSqlContextModelSnapshot.cs b/src/Service/Migrations/Mssql/MsSqlContextModelSnapshot.cs index eee5b4ca8..19d30669b 100644 --- a/src/Service/Migrations/Mssql/MsSqlContextModelSnapshot.cs +++ b/src/Service/Migrations/Mssql/MsSqlContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("ProductVersion", "8.0.6") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -337,10 +337,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("UserId") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(450)"); b.HasKey("Tenant", "DescriptorId"); + b.HasIndex("Tenant", "UserId") + .HasDatabaseName("IX_EFStoredCredential_Tenant_UserId"); + b.ToTable("Credentials"); }); diff --git a/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.Designer.cs b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.Designer.cs new file mode 100644 index 000000000..011594d62 --- /dev/null +++ b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.Designer.cs @@ -0,0 +1,495 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Passwordless.Service.Storage.Ef; + +#nullable disable + +namespace Passwordless.Service.Migrations.Sqlite +{ + [DbContext(typeof(DbGlobalSqliteContext))] + [Migration("20240709134121_AddIndicesForHotCodePaths")] + partial class AddIndicesForHotCodePaths + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.6"); + + modelBuilder.Entity("Passwordless.Service.EventLog.Models.ApplicationEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApiKeyId") + .HasColumnType("TEXT"); + + b.Property("EventType") + .HasColumnType("INTEGER"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PerformedAt") + .HasColumnType("TEXT"); + + b.Property("PerformedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Severity") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TenantId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.ToTable("ApplicationEvents"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AccountMetaInformation", b => + { + b.Property("AcountName") + .HasColumnType("TEXT"); + + b.Property("AdminEmailsSerialized") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DeleteAt") + .HasColumnType("TEXT"); + + b.Property("Tenant") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("AcountName"); + + b.ToTable("AccountInfo"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AliasPointer", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("Plaintext") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Tenant", "Alias"); + + b.ToTable("Aliases"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.ApiKeyDesc", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsLocked") + .HasColumnType("INTEGER"); + + b.Property("LastLockedAt") + .HasColumnType("TEXT"); + + b.Property("LastUnlockedAt") + .HasColumnType("TEXT"); + + b.Property("Scopes") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Tenant", "Id"); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("AllowAttestation") + .HasColumnType("INTEGER"); + + b.Property("DeveloperLoggingEndsAt") + .HasColumnType("TEXT"); + + b.Property("EventLoggingIsEnabled") + .HasColumnType("INTEGER"); + + b.Property("EventLoggingRetentionPeriod") + .HasColumnType("INTEGER"); + + b.Property("IsGenerateSignInTokenEndpointEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("IsMagicLinksEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("MagicLinkEmailMonthlyQuota") + .HasColumnType("INTEGER"); + + b.Property("MaxUsers") + .HasColumnType("INTEGER"); + + b.HasKey("Tenant"); + + b.ToTable("AppFeatures"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AuthenticationConfiguration", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("Purpose") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EditedBy") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("EditedOn") + .HasColumnType("TEXT"); + + b.Property("LastUsedOn") + .HasColumnType("TEXT"); + + b.Property("TimeToLive") + .HasColumnType("REAL"); + + b.Property("UserVerificationRequirement") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.HasKey("Tenant", "Purpose"); + + b.ToTable("AuthenticationConfigurations"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.Authenticator", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("AaGuid") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsAllowed") + .HasColumnType("INTEGER"); + + b.HasKey("Tenant", "AaGuid"); + + b.ToTable("Authenticators"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.DispatchedEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LinkTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Tenant") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("Tenant"); + + b.ToTable("DispatchedEmails"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.EFStoredCredential", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("DescriptorId") + .HasColumnType("BLOB"); + + b.Property("AaGuid") + .HasColumnType("TEXT"); + + b.Property("AttestationFmt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("BackupState") + .HasColumnType("INTEGER"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DescriptorTransports") + .HasColumnType("TEXT"); + + b.Property("DescriptorType") + .HasColumnType("INTEGER"); + + b.Property("Device") + .HasColumnType("TEXT"); + + b.Property("IsBackupEligible") + .HasColumnType("INTEGER"); + + b.Property("IsDiscoverable") + .HasColumnType("INTEGER"); + + b.Property("LastUsedAt") + .HasColumnType("TEXT"); + + b.Property("Nickname") + .HasColumnType("TEXT"); + + b.Property("Origin") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("RPID") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SignatureCounter") + .HasColumnType("INTEGER"); + + b.Property("UserHandle") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Tenant", "DescriptorId"); + + b.HasIndex("Tenant", "UserId") + .HasDatabaseName("IX_EFStoredCredential_Tenant_UserId"); + + b.ToTable("Credentials"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicActiveUserReport", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DailyActiveUsersCount") + .HasColumnType("INTEGER"); + + b.Property("TotalUsersCount") + .HasColumnType("INTEGER"); + + b.Property("WeeklyActiveUsersCount") + .HasColumnType("INTEGER"); + + b.HasKey("Tenant", "CreatedAt"); + + b.ToTable("PeriodicActiveUserReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicCredentialReport", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CredentialsCount") + .HasColumnType("INTEGER"); + + b.Property("UsersCount") + .HasColumnType("INTEGER"); + + b.HasKey("Tenant", "CreatedAt"); + + b.ToTable("PeriodicCredentialReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.TokenKey", b => + { + b.Property("Tenant") + .HasColumnType("TEXT"); + + b.Property("KeyId") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("KeyMaterial") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Tenant", "KeyId"); + + b.ToTable("TokenKeys"); + }); + + modelBuilder.Entity("Passwordless.Service.EventLog.Models.ApplicationEvent", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("Events") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithOne("Features") + .HasForeignKey("Passwordless.Service.Models.AppFeature", "Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.Authenticator", b => + { + b.HasOne("Passwordless.Service.Models.AppFeature", "AppFeature") + .WithMany("Authenticators") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppFeature"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.DispatchedEmail", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("DispatchedEmails") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicActiveUserReport", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("PeriodicActiveUserReports") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.PeriodicCredentialReport", b => + { + b.HasOne("Passwordless.Service.Models.AccountMetaInformation", "Application") + .WithMany("PeriodicCredentialReports") + .HasForeignKey("Tenant") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AccountMetaInformation", b => + { + b.Navigation("DispatchedEmails"); + + b.Navigation("Events"); + + b.Navigation("Features"); + + b.Navigation("PeriodicActiveUserReports"); + + b.Navigation("PeriodicCredentialReports"); + }); + + modelBuilder.Entity("Passwordless.Service.Models.AppFeature", b => + { + b.Navigation("Authenticators"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs new file mode 100644 index 000000000..424dbcb79 --- /dev/null +++ b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Passwordless.Service.Migrations.Sqlite +{ + /// + public partial class AddIndicesForHotCodePaths : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials", + columns: new[] { "Tenant", "UserId" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials"); + } + } +} diff --git a/src/Service/Migrations/Sqlite/SqliteContextModelSnapshot.cs b/src/Service/Migrations/Sqlite/SqliteContextModelSnapshot.cs index fe3d34c50..f063f37db 100644 --- a/src/Service/Migrations/Sqlite/SqliteContextModelSnapshot.cs +++ b/src/Service/Migrations/Sqlite/SqliteContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class SqliteContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.3"); + modelBuilder.HasAnnotation("ProductVersion", "8.0.6"); modelBuilder.Entity("Passwordless.Service.EventLog.Models.ApplicationEvent", b => { @@ -336,6 +336,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Tenant", "DescriptorId"); + b.HasIndex("Tenant", "UserId") + .HasDatabaseName("IX_EFStoredCredential_Tenant_UserId"); + b.ToTable("Credentials"); }); From 875178cde1969d1429cbcfef69813966916e5cc6 Mon Sep 17 00:00:00 2001 From: Jonas Hendrickx Date: Wed, 10 Jul 2024 17:17:54 +0200 Subject: [PATCH 3/3] format --- ...0240709134147_AddIndicesForHotCodePaths.cs | 63 +++++++++---------- ...0240709134121_AddIndicesForHotCodePaths.cs | 35 +++++------ 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs index db3dd46e3..e41db18a4 100644 --- a/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs +++ b/src/Service/Migrations/Mssql/20240709134147_AddIndicesForHotCodePaths.cs @@ -2,42 +2,41 @@ #nullable disable -namespace Passwordless.Service.Migrations.Mssql +namespace Passwordless.Service.Migrations.Mssql; + +/// +public partial class AddIndicesForHotCodePaths : Migration { /// - public partial class AddIndicesForHotCodePaths : Migration + protected override void Up(MigrationBuilder migrationBuilder) { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "UserId", - table: "Credentials", - type: "nvarchar(450)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(max)"); + migrationBuilder.AlterColumn( + name: "UserId", + table: "Credentials", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); - migrationBuilder.CreateIndex( - name: "IX_EFStoredCredential_Tenant_UserId", - table: "Credentials", - columns: new[] { "Tenant", "UserId" }); - } + migrationBuilder.CreateIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials", + columns: new[] { "Tenant", "UserId" }); + } - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_EFStoredCredential_Tenant_UserId", - table: "Credentials"); + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials"); - migrationBuilder.AlterColumn( - name: "UserId", - table: "Credentials", - type: "nvarchar(max)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)"); - } + migrationBuilder.AlterColumn( + name: "UserId", + table: "Credentials", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); } -} +} \ No newline at end of file diff --git a/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs index 424dbcb79..c91d895f2 100644 --- a/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs +++ b/src/Service/Migrations/Sqlite/20240709134121_AddIndicesForHotCodePaths.cs @@ -2,26 +2,25 @@ #nullable disable -namespace Passwordless.Service.Migrations.Sqlite +namespace Passwordless.Service.Migrations.Sqlite; + +/// +public partial class AddIndicesForHotCodePaths : Migration { /// - public partial class AddIndicesForHotCodePaths : Migration + protected override void Up(MigrationBuilder migrationBuilder) { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateIndex( - name: "IX_EFStoredCredential_Tenant_UserId", - table: "Credentials", - columns: new[] { "Tenant", "UserId" }); - } + migrationBuilder.CreateIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials", + columns: new[] { "Tenant", "UserId" }); + } - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_EFStoredCredential_Tenant_UserId", - table: "Credentials"); - } + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_EFStoredCredential_Tenant_UserId", + table: "Credentials"); } -} +} \ No newline at end of file