feat: add AppDbContext (Identity + RefreshTokens) and DbSeeder (13 roles + dev admin)

This commit is contained in:
Chris Chen
2026-05-25 19:05:02 -07:00
parent 40d740d6e0
commit a66a3f7cb0
2 changed files with 118 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using ROLAC.API.Entities;
namespace ROLAC.API.Data;
public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<RefreshToken> RefreshTokens => Set<RefreshToken>();
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<RefreshToken>(entity =>
{
entity.HasKey(e => e.Id);
// Unique index on hash — enables fast lookup and prevents duplicate tokens
entity.HasIndex(e => e.TokenHash).IsUnique();
entity.Property(e => e.TokenHash).HasMaxLength(64).IsRequired();
entity.Property(e => e.UserId).HasMaxLength(450).IsRequired();
entity.Property(e => e.DeviceInfo).HasMaxLength(200);
entity.Property(e => e.IpAddress).HasMaxLength(45);
entity.Property(e => e.ReplacedByHash).HasMaxLength(64);
entity.HasOne(e => e.User)
.WithMany(u => u.RefreshTokens)
.HasForeignKey(e => e.UserId)
.OnDelete(DeleteBehavior.Cascade);
// Computed properties are not DB columns
entity.Ignore(e => e.IsExpired);
entity.Ignore(e => e.IsRevoked);
entity.Ignore(e => e.IsActive);
});
builder.Entity<AppUser>(entity =>
{
entity.Property(e => e.LanguagePreference).HasMaxLength(10).HasDefaultValue("en");
});
builder.Entity<AppRole>(entity =>
{
entity.Property(e => e.Description).HasMaxLength(500);
});
}
}