From 3a13c8505a87b2b027b8ff1141a9846529b74b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 18 Oct 2018 17:58:01 +0200 Subject: [PATCH] Update the EF 6.x/EF Core entity configurations to use pre-defined column lengths --- .../OpenIddictApplicationConfiguration.cs | 9 ++++-- .../OpenIddictAuthorizationConfiguration.cs | 4 +++ .../OpenIddictScopeConfiguration.cs | 8 +++-- .../OpenIddictTokenConfiguration.cs | 12 ++++++- .../OpenIddictApplicationConfiguration.cs | 19 +++++++++-- .../OpenIddictAuthorizationConfiguration.cs | 23 +++++++++++-- .../OpenIddictScopeConfiguration.cs | 14 +++++++- .../OpenIddictTokenConfiguration.cs | 32 +++++++++++++++++-- 8 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs index 3cb81bf3..1d6749af 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs @@ -48,14 +48,19 @@ namespace OpenIddict.EntityFramework HasKey(application => application.Id); Property(application => application.ClientId) + .HasMaxLength(100) .IsRequired() - .HasMaxLength(450) - .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute())); + .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute + { + IsUnique = true + })); Property(application => application.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); Property(application => application.Type) + .HasMaxLength(25) .IsRequired(); HasMany(application => application.Authorizations) diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs index 6d30cc12..4cdc0625 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs @@ -46,15 +46,19 @@ namespace OpenIddict.EntityFramework HasKey(authorization => authorization.Id); Property(authorization => authorization.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); Property(authorization => authorization.Status) + .HasMaxLength(25) .IsRequired(); Property(authorization => authorization.Subject) + .HasMaxLength(450) .IsRequired(); Property(authorization => authorization.Type) + .HasMaxLength(25) .IsRequired(); HasMany(authorization => authorization.Tokens) diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictScopeConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictScopeConfiguration.cs index 6748215f..bb917e34 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictScopeConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictScopeConfiguration.cs @@ -44,12 +44,16 @@ namespace OpenIddict.EntityFramework HasKey(scope => scope.Id); Property(scope => scope.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); Property(scope => scope.Name) + .HasMaxLength(200) .IsRequired() - .HasMaxLength(450) - .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute())); + .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute + { + IsUnique = true + })); ToTable("OpenIddictScopes"); } diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictTokenConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictTokenConfiguration.cs index ef442392..330c815b 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictTokenConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictTokenConfiguration.cs @@ -48,16 +48,26 @@ namespace OpenIddict.EntityFramework HasKey(token => token.Id); Property(token => token.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); + // Warning: the index on the ReferenceId property MUST NOT be declared as + // a unique index, as Entity Framework 6.x doesn't support creating indexes + // with null-friendly WHERE conditions, unlike Entity Framework Core 1.x/2.x. Property(token => token.ReferenceId) - .HasMaxLength(450) + .HasMaxLength(100) .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute())); + Property(token => token.Status) + .HasMaxLength(25) + .IsRequired(); + Property(token => token.Subject) + .HasMaxLength(450) .IsRequired(); Property(token => token.Type) + .HasMaxLength(25) .IsRequired(); ToTable("OpenIddictTokens"); diff --git a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictApplicationConfiguration.cs b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictApplicationConfiguration.cs index 5c96953c..b766df87 100644 --- a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictApplicationConfiguration.cs +++ b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictApplicationConfiguration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using OpenIddict.EntityFrameworkCore.Models; @@ -26,7 +27,7 @@ namespace OpenIddict.EntityFrameworkCore where TToken : OpenIddictToken where TKey : IEquatable { - public void Configure(EntityTypeBuilder builder) + public void Configure([NotNull] EntityTypeBuilder builder) { if (builder == null) { @@ -37,28 +38,40 @@ namespace OpenIddict.EntityFrameworkCore // Entity Framework would throw an exception due to the TKey generic parameter // being non-nullable when using value types like short, int, long or Guid. + // If primary/foreign keys are strings, limit their length to ensure + // they can be safely used in indexes, specially when the underlying + // provider is known to not restrict the default length (e.g MySQL). + if (typeof(TKey) == typeof(string)) + { + builder.Property(application => application.Id) + .HasMaxLength(50); + } + builder.HasKey(application => application.Id); builder.HasIndex(application => application.ClientId) .IsUnique(); builder.Property(application => application.ClientId) + .HasMaxLength(100) .IsRequired(); builder.Property(application => application.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); builder.Property(application => application.Type) + .HasMaxLength(25) .IsRequired(); builder.HasMany(application => application.Authorizations) .WithOne(authorization => authorization.Application) - .HasForeignKey("ApplicationId") + .HasForeignKey(nameof(OpenIddictAuthorization.Application) + nameof(OpenIddictApplication.Id)) .IsRequired(required: false); builder.HasMany(application => application.Tokens) .WithOne(token => token.Application) - .HasForeignKey("ApplicationId") + .HasForeignKey(nameof(OpenIddictToken.Application) + nameof(OpenIddictApplication.Id)) .IsRequired(required: false); builder.ToTable("OpenIddictApplications"); diff --git a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs index 477d6b9a..a9906c63 100644 --- a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs +++ b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using OpenIddict.EntityFrameworkCore.Models; @@ -26,7 +27,7 @@ namespace OpenIddict.EntityFrameworkCore where TToken : OpenIddictToken where TKey : IEquatable { - public void Configure(EntityTypeBuilder builder) + public void Configure([NotNull] EntityTypeBuilder builder) { if (builder == null) { @@ -37,24 +38,40 @@ namespace OpenIddict.EntityFrameworkCore // Entity Framework would throw an exception due to the TKey generic parameter // being non-nullable when using value types like short, int, long or Guid. + // If primary/foreign keys are strings, limit their length to ensure + // they can be safely used in indexes, specially when the underlying + // provider is known to not restrict the default length (e.g MySQL). + if (typeof(TKey) == typeof(string)) + { + builder.Property(nameof(OpenIddictAuthorization.Application) + nameof(OpenIddictApplication.Id)) + .HasMaxLength(50); + + builder.Property(application => application.Id) + .HasMaxLength(50); + } + builder.HasKey(authorization => authorization.Id); - builder.HasIndex("ApplicationId", - nameof(OpenIddictAuthorization.Scopes), + builder.HasIndex( + nameof(OpenIddictAuthorization.Application) + nameof(OpenIddictApplication.Id), nameof(OpenIddictAuthorization.Status), nameof(OpenIddictAuthorization.Subject), nameof(OpenIddictAuthorization.Type)); builder.Property(authorization => authorization.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); builder.Property(authorization => authorization.Status) + .HasMaxLength(25) .IsRequired(); builder.Property(authorization => authorization.Subject) + .HasMaxLength(450) .IsRequired(); builder.Property(authorization => authorization.Type) + .HasMaxLength(25) .IsRequired(); builder.HasMany(authorization => authorization.Tokens) diff --git a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictScopeConfiguration.cs b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictScopeConfiguration.cs index d76c220f..4acddc7b 100644 --- a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictScopeConfiguration.cs +++ b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictScopeConfiguration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using OpenIddict.EntityFrameworkCore.Models; @@ -22,7 +23,7 @@ namespace OpenIddict.EntityFrameworkCore where TScope : OpenIddictScope where TKey : IEquatable { - public void Configure(EntityTypeBuilder builder) + public void Configure([NotNull] EntityTypeBuilder builder) { if (builder == null) { @@ -33,15 +34,26 @@ namespace OpenIddict.EntityFrameworkCore // Entity Framework would throw an exception due to the TKey generic parameter // being non-nullable when using value types like short, int, long or Guid. + // If primary/foreign keys are strings, limit their length to ensure + // they can be safely used in indexes, specially when the underlying + // provider is known to not restrict the default length (e.g MySQL). + if (typeof(TKey) == typeof(string)) + { + builder.Property(scope => scope.Id) + .HasMaxLength(50); + } + builder.HasKey(scope => scope.Id); builder.HasIndex(scope => scope.Name) .IsUnique(); builder.Property(scope => scope.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); builder.Property(scope => scope.Name) + .HasMaxLength(200) .IsRequired(); builder.ToTable("OpenIddictScopes"); diff --git a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictTokenConfiguration.cs b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictTokenConfiguration.cs index daa1dbee..3af9b181 100644 --- a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictTokenConfiguration.cs +++ b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictTokenConfiguration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using OpenIddict.EntityFrameworkCore.Models; @@ -26,7 +27,7 @@ namespace OpenIddict.EntityFrameworkCore where TAuthorization : OpenIddictAuthorization where TKey : IEquatable { - public void Configure(EntityTypeBuilder builder) + public void Configure([NotNull] EntityTypeBuilder builder) { if (builder == null) { @@ -37,23 +38,50 @@ namespace OpenIddict.EntityFrameworkCore // Entity Framework would throw an exception due to the TKey generic parameter // being non-nullable when using value types like short, int, long or Guid. + + // If primary/foreign keys are strings, limit their length to ensure + // they can be safely used in indexes, specially when the underlying + // provider is known to not restrict the default length (e.g MySQL). + if (typeof(TKey) == typeof(string)) + { + builder.Property(nameof(OpenIddictToken.Application) + nameof(OpenIddictApplication.Id)) + .HasMaxLength(50); + + builder.Property(nameof(OpenIddictToken.Authorization) + nameof(OpenIddictApplication.Id)) + .HasMaxLength(50); + + builder.Property(token => token.Id) + .HasMaxLength(50); + } + builder.HasKey(token => token.Id); builder.HasIndex(token => token.ReferenceId) .IsUnique(); - builder.HasIndex("ApplicationId", + builder.HasIndex( + nameof(OpenIddictToken.Application) + nameof(OpenIddictApplication.Id), nameof(OpenIddictToken.Status), nameof(OpenIddictToken.Subject), nameof(OpenIddictToken.Type)); builder.Property(token => token.ConcurrencyToken) + .HasMaxLength(50) .IsConcurrencyToken(); + builder.Property(token => token.ReferenceId) + .HasMaxLength(100); + + builder.Property(token => token.Status) + .HasMaxLength(25) + .IsRequired(); + builder.Property(token => token.Subject) + .HasMaxLength(450) .IsRequired(); builder.Property(token => token.Type) + .HasMaxLength(25) .IsRequired(); builder.ToTable("OpenIddictTokens");