// SPDX-FileCopyrightText: 2026 Progmasoft // SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.0 using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using XSharp.Web.Api.Auth; namespace XSharp.Web.Api.Data; internal sealed class RegistryDbContext(DbContextOptions options) : IdentityDbContext, Guid>(options) { public DbSet AuthChallenges => Set(); public DbSet RegistryTokens => Set(); protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.HasDefaultSchema("registry"); builder.Entity(entity => { entity.Property(user => user.CreatedAt).IsRequired(); entity.Property(user => user.PublisherName).HasMaxLength(PublisherNamePolicy.MaximumLength); entity.Property(user => user.NormalizedPublisherName).HasMaxLength(PublisherNamePolicy.MaximumLength); entity.HasIndex(user => user.NormalizedEmail).IsUnique(); entity.HasIndex(user => user.NormalizedPublisherName) .IsUnique() .HasDatabaseName("PublisherNameIndex"); }); builder.Entity(entity => { entity.HasKey(challenge => challenge.Id); entity.Property(challenge => challenge.Purpose).HasMaxLength(32); entity.Property(challenge => challenge.CodeDigest).HasMaxLength(32); entity.HasIndex(challenge => new { challenge.UserId, challenge.Purpose, challenge.ConsumedAt }); entity.HasOne() .WithMany() .HasForeignKey(challenge => challenge.UserId) .OnDelete(DeleteBehavior.Cascade); }); builder.Entity(entity => { entity.HasKey(token => token.Id); entity.Property(token => token.Name).HasMaxLength(80); entity.Property(token => token.Digest).HasMaxLength(32); entity.Property(token => token.Prefix).HasMaxLength(16); entity.Property(token => token.Scopes).HasColumnType("text[]"); entity.HasIndex(token => token.Digest).IsUnique(); entity.HasIndex(token => new { token.UserId, token.RevokedAt }); entity.HasOne() .WithMany() .HasForeignKey(token => token.UserId) .OnDelete(DeleteBehavior.Cascade); }); } }