diff --git a/IdentityShroud.Core/EFCore/Converters/DekIdConverter.cs b/IdentityShroud.Core/EFCore/Converters/DekIdConverter.cs new file mode 100644 index 0000000..0a957ae --- /dev/null +++ b/IdentityShroud.Core/EFCore/Converters/DekIdConverter.cs @@ -0,0 +1,12 @@ +using IdentityShroud.Core.Security; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace IdentityShroud.Core; + +public class DekIdConverter : ValueConverter +{ + public DekIdConverter() + : base(id => id.Id, guid => new DekId(guid)) + { + } +} \ No newline at end of file diff --git a/IdentityShroud.Core/EFCore/Converters/KekIdConverter.cs b/IdentityShroud.Core/EFCore/Converters/KekIdConverter.cs new file mode 100644 index 0000000..87c0de9 --- /dev/null +++ b/IdentityShroud.Core/EFCore/Converters/KekIdConverter.cs @@ -0,0 +1,12 @@ +using IdentityShroud.Core.Security; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace IdentityShroud.Core; + +public class KekIdConverter : ValueConverter +{ + public KekIdConverter() + : base(id => id.Id, guid => new KekId(guid)) + { + } +} \ No newline at end of file diff --git a/IdentityShroud.Core/Db.cs b/IdentityShroud.Core/EFCore/Db.cs similarity index 59% rename from IdentityShroud.Core/Db.cs rename to IdentityShroud.Core/EFCore/Db.cs index a37136c..90ebea7 100644 --- a/IdentityShroud.Core/Db.cs +++ b/IdentityShroud.Core/EFCore/Db.cs @@ -1,7 +1,7 @@ +using System.Linq.Expressions; using IdentityShroud.Core.Model; using IdentityShroud.Core.Security; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -23,39 +23,6 @@ public class Db( public virtual DbSet Keys { get; set; } public virtual DbSet Deks { get; set; } - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - var dekIdConverter = new ValueConverter( - id => id.Id, - guid => new DekId(guid)); - - var kekIdConverter = new ValueConverter( - id => id.Id, - guid => new KekId(guid)); - - modelBuilder.Entity() - .Property(d => d.Id) - .HasConversion(dekIdConverter); - - modelBuilder.Entity() - .OwnsOne(d => d.KeyData, keyData => - { - keyData.Property(k => k.KekId).HasConversion(kekIdConverter); - }); - - modelBuilder.Entity() - .OwnsOne(k => k.Key, key => - { - key.Property(k => k.KekId).HasConversion(kekIdConverter); - }); - - modelBuilder.Entity() - .OwnsOne(c => c.Secret, secret => - { - secret.Property(s => s.DekId).HasConversion(dekIdConverter); - }); - } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(""); @@ -71,6 +38,18 @@ public class Db( { optionsBuilder.UseLoggerFactory(loggerFactory); } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(typeof(Db).Assembly); + } + + protected override void ConfigureConventions(ModelConfigurationBuilder b) + { + base.ConfigureConventions(b); + b.Properties().HaveConversion(); + b.Properties().HaveConversion(); } } \ No newline at end of file diff --git a/IdentityShroud.Core/IdentityShroud.Core.csproj.DotSettings b/IdentityShroud.Core/IdentityShroud.Core.csproj.DotSettings new file mode 100644 index 0000000..f42aea1 --- /dev/null +++ b/IdentityShroud.Core/IdentityShroud.Core.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/IdentityShroud.Core/Model/ClientSecret.cs b/IdentityShroud.Core/Model/ClientSecret.cs index 52d25cc..d17e24d 100644 --- a/IdentityShroud.Core/Model/ClientSecret.cs +++ b/IdentityShroud.Core/Model/ClientSecret.cs @@ -2,6 +2,8 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Security; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace IdentityShroud.Core.Model; @@ -13,5 +15,15 @@ public class ClientSecret public Guid ClientId { get; set; } public DateTime CreatedAt { get; set; } public DateTime? RevokedAt { get; set; } - public required EncryptedValue Secret { get; set; } + public EncryptedValue? Secret { get; set; } +} + +public class ClientSecretConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder b) + { + b.ToTable("client_secret"); + b.HasKey(e => e.Id); + b.ComplexProperty(e => e.Secret); + } } \ No newline at end of file diff --git a/IdentityShroud.Core/Model/Realm.cs b/IdentityShroud.Core/Model/Realm.cs index bbe9631..8f6737a 100644 --- a/IdentityShroud.Core/Model/Realm.cs +++ b/IdentityShroud.Core/Model/Realm.cs @@ -1,13 +1,14 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using IdentityShroud.Core.Security; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace IdentityShroud.Core.Model; [Table("realm")] public class Realm { - public Guid Id { get; set; } /// /// Note this is part of the url we should encourage users to keep it short but we do not want to limit them too much @@ -27,14 +28,4 @@ public class Realm /// Can be overriden per client /// public string DefaultSignatureAlgorithm { get; set; } = JsonWebAlgorithm.RS256; -} - -[Table("realm_dek")] -public record RealmDek -{ - public required DekId Id { get; init; } - public required bool Active { get; set; } - public required string Algorithm { get; init; } - public required EncryptedDek KeyData { get; init; } - public required Guid RealmId { get; init; } -} +} \ No newline at end of file diff --git a/IdentityShroud.Core/Model/RealmDek.cs b/IdentityShroud.Core/Model/RealmDek.cs new file mode 100644 index 0000000..ed78b14 --- /dev/null +++ b/IdentityShroud.Core/Model/RealmDek.cs @@ -0,0 +1,24 @@ +using IdentityShroud.Core.Security; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace IdentityShroud.Core.Model; + +public record RealmDek +{ + public required DekId Id { get; init; } + public required bool Active { get; set; } + public required string Algorithm { get; init; } + public required EncryptedDek KeyData { get; init; } + public required Guid RealmId { get; init; } +} + +public class RealmDekConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder b) + { + b.ToTable("realm_dek"); + b.HasKey(e => e.Id); + b.ComplexProperty(e => e.KeyData, e => e.IsRequired()); + } +} \ No newline at end of file diff --git a/IdentityShroud.Core/Model/RealmKey.cs b/IdentityShroud.Core/Model/RealmKey.cs index 3fcf2d1..4613be8 100644 --- a/IdentityShroud.Core/Model/RealmKey.cs +++ b/IdentityShroud.Core/Model/RealmKey.cs @@ -2,17 +2,14 @@ using System.ComponentModel.DataAnnotations.Schema; using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Security; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace IdentityShroud.Core.Model; - -[Table("realm_key")] public record RealmKey { public required Guid Id { get; init; } public required string KeyType { get; init; } - - public required EncryptedDek Key { get; init; } public required DateTime CreatedAt { get; init; } public DateTime? RevokedAt { get; set; } @@ -22,6 +19,15 @@ public record RealmKey /// are more comfortable replacing keys by using priority then directly deactivating the old key. /// public int Priority { get; set; } = 10; - +} +public class RealmKeyConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder b) + { + b.ToTable("realm_key"); + b.HasKey(e => e.Id); + + b.ComplexProperty(e => e.Key, e => e.IsRequired()); + } } \ No newline at end of file diff --git a/IdentityShroud.Core/Security/EncryptedDek.cs b/IdentityShroud.Core/Security/EncryptedDek.cs index 377a2f6..002c1c9 100644 --- a/IdentityShroud.Core/Security/EncryptedDek.cs +++ b/IdentityShroud.Core/Security/EncryptedDek.cs @@ -2,5 +2,4 @@ using Microsoft.EntityFrameworkCore; namespace IdentityShroud.Core.Security; -[Owned] public record EncryptedDek(KekId KekId, byte[] Value); \ No newline at end of file diff --git a/IdentityShroud.Core/Security/EncryptedValue.cs b/IdentityShroud.Core/Security/EncryptedValue.cs index 173c295..37619fa 100644 --- a/IdentityShroud.Core/Security/EncryptedValue.cs +++ b/IdentityShroud.Core/Security/EncryptedValue.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore; namespace IdentityShroud.Core.Security; -[Owned] public record EncryptedValue(DekId DekId, byte[] Value); diff --git a/IdentityShroud.sln.DotSettings.user b/IdentityShroud.sln.DotSettings.user index 88c8f46..540f7bf 100644 --- a/IdentityShroud.sln.DotSettings.user +++ b/IdentityShroud.sln.DotSettings.user @@ -26,6 +26,9 @@ /home/eelke/.dotnet/dotnet /home/eelke/.dotnet/sdk/10.0.102/MSBuild.dll + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> <Solution /> </SessionState>