using IdentityServer8.EntityFramework.Entities; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; namespace Yavsc.Models { using Abstract.Identity; using Abstract.Models.Messaging; using Access; using Attributes; using Auth; using Bank; using Billing; using Blog; using Chat; using Drawing; using Forms; using Haircut; using Identity; using IT.Evolution; using IT.Fixing; using Market; using Messaging; using Microsoft.AspNetCore.Http; using Musical; using Musical.Profiles; using Payment; using Relationship; using Server.Models.Calendar; using Server.Models.EMailing; using Server.Models.IT; using Server.Models.IT.SourceCode; using Streaming; using Workflow; using Workflow.Profiles; using Yavsc.Models.Kyc; public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() { } public ApplicationDbContext(DbContextOptions options) : base(options) { if (Database.IsRelational()) { Database.SetCommandTimeout(180); } } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); if (Database.IsNpgsql()) { NOW_SQL = "LOCALTIMESTAMP"; } else { NOW_SQL = "CURRENT_TIMESTAMP"; } builder.UseIdentityByDefaultColumns(); // Customize the ASP.NET Identity model and override the defaults if needed. // For example, you can rename the ASP.NET Identity table names and more. // Add your customizations after calling base.OnModelCreating(builder); builder.Entity().HasKey(x => new { x.OwnerId, x.UserId }); builder.Entity().Property(x => x.DeclarationDate).HasDefaultValueSql(NOW_SQL); builder.Entity().HasKey(x => new { x.PostId, x.TagId }); // Signature: composite index (EstimateId, Type, // CapturedAtUtc DESC) to support the controller's // "most recent signature per type" read pattern // without an extra ORDER BY cost. The default // EF-generated FK index on EstimateId alone is // replaced by the composite to avoid duplicate // indexes. builder.Entity() .HasIndex(s => new { s.EstimateId, s.Type, s.CapturedAtUtc }) .IsDescending(false, false, true); builder.Entity() .HasOne(s => s.Estimate) .WithMany(e => e.Signatures) .HasForeignKey(s => s.EstimateId) .OnDelete(DeleteBehavior.Cascade); builder.Entity() .Property(s => s.CoordinateMax) .HasDefaultValue(10_000); builder.Entity().Property(u => u.FullName).IsRequired(false); builder.Entity().Property(u => u.DedicatedGoogleCalendar).IsRequired(false); builder.Entity().HasMany(c => c.Connections); builder.Entity().Property(u => u.Avatar).HasDefaultValue(YavscConstants.DefaultAvatar); builder.Entity().Property(u => u.DiskQuota).HasDefaultValue(YavscConstants.DefaultFSQ); builder.Entity().HasAlternateKey(u => u.Email); builder.Entity().HasOne(bl => bl.User); builder.Entity().HasOne(bl => bl.Owner); builder.Entity().HasKey(u => new { u.DoesCode, u.UserId }); builder.Entity().HasKey(u => new { u.InstrumentId, u.UserId }); builder.Entity().HasKey(a => new { a.CircleId, a.BlogPostId }); builder.Entity().HasKey(c => new { c.MemberId, c.CircleId }); builder.Entity().HasKey(c => new { uid = c.UserId, notid = c.NotificationId }); builder.Entity().HasKey(ti => new { ti.TaintId, ti.PrestationId }); builder.Entity().HasKey(l => new { l.HRef, l.Method }); builder.Entity().HasKey(l => new { l.Start, l.End }); builder.Entity().HasKey(o => new { o.Code, o.CodeScrutin }); builder.Entity().Property(n => n.icon).HasDefaultValue("exclam"); builder.Entity().HasKey(p => new { room = p.ChannelName, user = p.UserId }); builder.Entity().HasAlternateKey(i => new { Instrument = i.InstrumentId, owner = i.OwnerId }) ; builder.Entity().Property(a => a.ParentCode).IsRequired(false); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().Property("Id").UseIdentityAlwaysColumn(); builder.Entity().HasKey(e => new { e.UserCode, e.DeviceCode }); builder.Entity().HasKey(e => e.Key); // builder.Entity>().HasKey(i=> new { i.LoginProvider, i.UserId, i.ProviderKey }); builder.Entity().HasOne().WithMany(e => e.ClientSecrets).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.AllowedScopes).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.IdentityProviderRestrictions).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.Properties).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.PostLogoutRedirectUris).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.RedirectUris).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.AllowedCorsOrigins).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.AllowedGrantTypes).HasForeignKey(e => e.ClientId); builder.Entity().HasOne().WithMany(e => e.Secrets).HasForeignKey(e => e.ApiResourceId); builder.Entity().HasOne().WithMany(e => e.Scopes).HasForeignKey(e => e.ApiResourceId); builder.Entity().HasOne().WithMany(e => e.UserClaims).HasForeignKey(e => e.ApiResourceId); builder.Entity().HasOne().WithMany(e => e.Properties).HasForeignKey(e => e.ApiResourceId); builder.Entity().HasOne().WithMany(e => e.UserClaims).HasForeignKey(e => e.ScopeId); builder.Entity().HasOne().WithMany(e => e.Properties).HasForeignKey(e => e.ScopeId); foreach (var et in builder.Model.GetEntityTypes()) { if (et.ClrType.GetInterface("IBaseTrackedEntity") != null) et.FindProperty("DateCreated").SetAfterSaveBehavior(Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.Ignore); } // ── TrustToken ─────────────────────────────────────────────────────── builder.Entity(e => { e.HasIndex(t => t.TokenHash).IsUnique(); // idempotence garantie en DB e.Property(t => t.TokenHash).HasMaxLength(128).IsRequired(); e.Property(t => t.TokenSource).HasMaxLength(32).IsRequired(); }); // ── TrustDeclaration ───────────────────────────────────────────────── builder.Entity(e => { e.HasOne(d => d.Subject) .WithMany(t => t.Declarations) .HasForeignKey(d => d.TrustTokenId) .OnDelete(DeleteBehavior.Restrict); // on ne supprime pas un token qui a des déclarations // DeclarantTokenId est une FK vers TrustToken mais sans navigation // pour éviter les cycles EF e.HasIndex(d => d.TrustTokenId); e.HasIndex(d => d.Status); e.HasIndex(d => d.SubmittedAt); e.Property(d => d.Content).HasMaxLength(2000); }); // ── DeclarationFlag ────────────────────────────────────────────────── builder.Entity(e => { e.HasOne(f => f.Declaration) .WithMany(d => d.Flags) .HasForeignKey(f => f.DeclarationId) .OnDelete(DeleteBehavior.Cascade); e.HasOne(f => f.Pattern) .WithMany() .HasForeignKey(f => f.PatternId) .OnDelete(DeleteBehavior.Restrict); e.Property(f => f.MatchExcerpt).HasMaxLength(100); }); // ── RegexAlertPattern ──────────────────────────────────────────────── builder.Entity(e => { e.Property(p => p.Pattern).HasMaxLength(500).IsRequired(); e.Property(p => p.Description).HasMaxLength(200); e.HasIndex(p => p.IsActive); }); // ── ModerationLog ──────────────────────────────────────────────────── builder.Entity(e => { e.HasOne(l => l.Declaration) .WithMany() .HasForeignKey(l => l.DeclarationId) .OnDelete(DeleteBehavior.Restrict); e.HasIndex(l => l.DeclarationId); e.HasIndex(l => l.ModeratorId); e.HasIndex(l => l.Timestamp); // Log immuable — pas de update autorisé e.ToTable(tb => tb.HasCheckConstraint("CK_ModerationLog_Immutable", "1=1")); }); } /// /// Activities referenced on this site /// /// public DbSet Activities { get; set; } public DbSet UserActivities { get; set; } /// /// Users posts /// /// public DbSet BlogSpot { get; set; } /// /// Skills powered by this site /// /// public DbSet SiteSkills { get; set; } /// /// Circle members /// /// public DbSet CircleMembers { get; set; } /// /// Special commands, talking about /// a given place and date. /// public DbSet RdvQueries { get; set; } public DbSet HairCutQueries { get; set; } public DbSet HairPrestation { get; set; } public DbSet HairMultiCutQueries { get; set; } public DbSet Performers { get; set; } public DbSet Estimates { get; set; } public DbSet Signatures { get; set; } public DbSet BankStatus { get; set; } public DbSet BalanceImpact { get; set; } /// /// References all declared external NativeConfidential devices /// /// public DbSet DeviceDeclaration { get; set; } public DbSet Services { get; set; } public DbSet Products { get; set; } public DbSet ExceptionsSIREN { get; set; } public DbSet Locations { get; set; } public DbSet Tags { get; set; } public DbSet TagsDomain { get; set; } public DbSet EstimateTemplates { get; set; } public DbSet Contact { get; set; } public DbSet ClientProviderInfo { get; set; } public DbSet BlackListed { get; set; } public DbSet MusicalPreference { get; set; } public DbSet MusicalTendency { get; set; } public DbSet Instrument { get; set; } [ActivitySettings] public DbSet DjSettings { get; set; } [ActivitySettings] public DbSet Instrumentation { get; set; } [ActivitySettings] public DbSet FormationSettings { get; set; } [ActivitySettings] public DbSet GeneralSettings { get; set; } public DbSet CoWorking { get; set; } private void AddTimestamps(string userId) { var entities = ChangeTracker.Entries() .Where(x => x.Entity.GetType().GetInterface(nameof(ITrackedEntity)) != null && (x.State == EntityState.Added || x.State == EntityState.Modified)); foreach (var entity in entities) { if (entity.State == EntityState.Added) { ((ITrackedEntity)entity.Entity).DateCreated = DateTime.Now; ((ITrackedEntity)entity.Entity).UserCreated = userId; } ((ITrackedEntity)entity.Entity).DateModified = DateTime.Now; ((ITrackedEntity)entity.Entity).UserModified = userId; } } public int SaveChanges(string userId) { AddTimestamps(userId); return base.SaveChanges(); } public async Task SaveChangesAsync(string userId, CancellationToken ctoken = default(CancellationToken)) { AddTimestamps(userId); return await base.SaveChangesAsync(ctoken); } public Task SaveChangesAsync() { return base.SaveChangesAsync(); } public DbSet Circle { get; set; } public DbSet CircleAuthorizationToBlogPost { get; set; } public DbSet CommandForm { get; set; } public DbSet
Form { get; set; } public DbSet Ban { get; set; } public DbSet HairTaint { get; set; } public DbSet Color { get; set; } public DbSet Notification { get; set; } public DbSet DismissClicked { get; set; } [ActivitySettings] public DbSet BrusherProfile { get; set; } public DbSet BankIdentity { get; set; } public DbSet PayPalPayment { get; set; } public DbSet HyperLink { get; set; } public DbSet Period { get; set; } public DbSet BlogTag { get; set; } public DbSet ApplicationUser { get; set; } public DbSet Feature { get; set; } public DbSet Bug { get; set; } public DbSet Comment { get; set; } public DbSet Announce { get; set; } // TODO remove and opt for for memory only storing, // as long as it must be set empty each time the service is restarted, // and that chatting should be kept as must as possible independent from db context public DbSet ChatConnection { get; set; } public DbSet ChatRoom { get; set; } public DbSet MailingTemplate { get; set; } public DbSet GitRepositoryReference { get; set; } public DbSet Project { get; set; } [Obsolete("use signaled flows")] public DbSet LiveFlow { get; set; } public DbSet ChatRoomAccess { get; set; } public DbSet InstrumentRating { get; set; } public DbSet blogSpotPublications { get; set; } public DbSet UploadedFiles { get; set; } public DbSet BlogAttachedFiles { get; set; } public DbSet Clients { get; set; } public DbSet ClientIdPRestrictions { get; set; } public DbSet ClientProperties { get; set; } public DbSet ClientCorsOrigins { get; set; } public DbSet ClientSecrets { get; set; } public DbSet ClientScopes { get; set; } public DbSet ClientGrantTypes { get; set; } public DbSet ClientClaims { get; set; } public DbSet ClientRedirectUris { get; set; } public DbSet ClientPostLogoutRedirectUris { get; set; } public DbSet IdentityResources { get; set; } public DbSet IdentityResourceClaims { get; set; } public DbSet IdentityResourceProperties { get; set; } public DbSet ApiResources { get; set; } public DbSet ApiResourceSecrets { get; set; } public DbSet ApiResourceScopes { get; set; } public DbSet ApiResourceClaims { get; set; } public DbSet ApiResourceProperties { get; set; } public DbSet ApiScopes { get; set; } public DbSet ApiScopeClaims { get; set; } public DbSet ApiScopeProperties { get; set; } public DbSet PersistedGrants { get; set; } public DbSet DeviceFlowCodes { get; set; } public string NOW_SQL { get; private set; } public DbSet TrustTokens { get; set; } public DbSet TrustDeclarations { get; set; } public DbSet RegexAlertPatterns { get; set; } public DbSet ModerationLogs { get; set; } } }