106 lines
4.8 KiB
C#
106 lines
4.8 KiB
C#
using FinlyticBackend.Entities;
|
|
using FinlyticCore.Database;
|
|
using FinlyticCore.Entities.Settings;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Design;
|
|
|
|
namespace FinlyticBackend.Database;
|
|
|
|
/// <summary>
|
|
/// FinlyticBackend previously implemented no <see cref="ISettingsDbContext"/> at all, unlike every other
|
|
/// service - which is why it never had dynamic settings (logging channels etc.) to show in the admin UI.
|
|
/// </summary>
|
|
public class BackendDbContext : DbContext, ISettingsDbContext
|
|
{
|
|
public BackendDbContext(DbContextOptions<BackendDbContext> options) : base(options) { }
|
|
|
|
public DbSet<UserEntity> Users => Set<UserEntity>();
|
|
public DbSet<UserDeviceTokenEntity> UserDeviceTokens => Set<UserDeviceTokenEntity>();
|
|
public DbSet<UserFavoriteAssetEntity> UserFavoriteAssets => Set<UserFavoriteAssetEntity>();
|
|
public DbSet<ServiceConfigurationEntity> ServiceConfigurations => Set<ServiceConfigurationEntity>();
|
|
public DbSet<SettingEntity> DynamicSettings => Set<SettingEntity>();
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
modelBuilder.Entity<SettingEntity>(entity =>
|
|
{
|
|
entity.HasKey(e => e.Id);
|
|
entity.HasIndex(e => e.Key).IsUnique();
|
|
});
|
|
|
|
modelBuilder.Entity<UserEntity>(entity =>
|
|
{
|
|
entity.ToTable("users");
|
|
entity.Property(u => u.Id).HasColumnName("id");
|
|
entity.Property(u => u.Email).HasColumnName("email");
|
|
entity.Property(u => u.PasswordHash).HasColumnName("password_hash");
|
|
entity.Property(u => u.FullName).HasColumnName("full_name");
|
|
entity.Property(u => u.Role).HasColumnName("role");
|
|
entity.Property(u => u.IsActive).HasColumnName("is_active");
|
|
entity.Property(u => u.CreatedAt).HasColumnName("created_at");
|
|
entity.Property(u => u.LastLoginAt).HasColumnName("last_login_at");
|
|
entity.Property(u => u.ThemePreference).HasColumnName("theme_preference");
|
|
|
|
entity.HasIndex(u => u.Email).IsUnique();
|
|
entity.HasIndex(u => u.Role);
|
|
});
|
|
|
|
modelBuilder.Entity<UserDeviceTokenEntity>(entity =>
|
|
{
|
|
entity.ToTable("user_device_tokens");
|
|
entity.Property(t => t.Id).HasColumnName("id");
|
|
entity.Property(t => t.UserId).HasColumnName("user_id");
|
|
entity.Property(t => t.FcmToken).HasColumnName("fcm_token");
|
|
entity.Property(t => t.DeviceName).HasColumnName("device_name");
|
|
entity.Property(t => t.RegisteredAt).HasColumnName("registered_at");
|
|
entity.Property(t => t.LastUsedAt).HasColumnName("last_used_at");
|
|
|
|
entity.HasIndex(t => t.UserId);
|
|
entity.HasIndex(t => t.FcmToken);
|
|
});
|
|
|
|
modelBuilder.Entity<UserFavoriteAssetEntity>(entity =>
|
|
{
|
|
entity.ToTable("user_favorite_assets");
|
|
entity.Property(f => f.Id).HasColumnName("id");
|
|
entity.Property(f => f.UserId).HasColumnName("user_id");
|
|
entity.Property(f => f.Isin).HasColumnName("isin");
|
|
entity.Property(f => f.CreatedAt).HasColumnName("created_at");
|
|
|
|
entity.HasIndex(f => new { f.UserId, f.Isin }).IsUnique();
|
|
});
|
|
|
|
modelBuilder.Entity<ServiceConfigurationEntity>(entity =>
|
|
{
|
|
entity.ToTable("service_configurations");
|
|
entity.Property(c => c.Id).HasColumnName("id");
|
|
entity.Property(c => c.ServiceName).HasColumnName("service_name");
|
|
entity.Property(c => c.ConfigKey).HasColumnName("config_key");
|
|
entity.Property(c => c.ConfigValue).HasColumnName("config_value");
|
|
entity.Property(c => c.DataType).HasColumnName("data_type");
|
|
entity.Property(c => c.Description).HasColumnName("description");
|
|
entity.Property(c => c.UpdatedAt).HasColumnName("updated_at");
|
|
|
|
entity.HasIndex(c => new { c.ServiceName, c.ConfigKey }).IsUnique();
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lets `dotnet ef migrations add` construct a <see cref="BackendDbContext"/> without booting the full
|
|
/// application (which fails fast at startup if JWT_SECRET_KEY/ADMIN_DEFAULT_PASSWORD aren't set - see
|
|
/// Program.cs) - the same pattern every other service's DbContext already uses
|
|
/// (e.g. <c>TechnicalAnalysisDbContextFactory</c>).
|
|
/// </summary>
|
|
public class BackendDbContextFactory : IDesignTimeDbContextFactory<BackendDbContext>
|
|
{
|
|
public BackendDbContext CreateDbContext(string[] args)
|
|
{
|
|
var optionsBuilder = new DbContextOptionsBuilder<BackendDbContext>();
|
|
optionsBuilder.UseNpgsql("Host=localhost;Database=finlytic_backend;Username=postgres;Password=postgres");
|
|
return new BackendDbContext(optionsBuilder.Options);
|
|
}
|
|
}
|