113 lines
4.9 KiB
C#
113 lines
4.9 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace IM.Admin.Data;
|
|
|
|
public sealed class AdminAccount
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
public string Account { get; set; } = "";
|
|
public string Name { get; set; } = "";
|
|
public string Email { get; set; } = "";
|
|
public string PasswordHash { get; set; } = "";
|
|
public string Role { get; set; } = "reviewer";
|
|
public bool Enabled { get; set; } = true;
|
|
public string Stamp { get; set; } = Guid.NewGuid().ToString("N");
|
|
public int FailedAttempts { get; set; }
|
|
public DateTime? LockedUntil { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
public sealed class SystemSetting
|
|
{
|
|
public string Id { get; set; } = "";
|
|
public long Version { get; set; }
|
|
public string Value { get; set; } = "{}";
|
|
public string? Draft { get; set; }
|
|
public long? TestedVersion { get; set; }
|
|
public string Secret { get; set; } = "";
|
|
public string? DraftSecret { get; set; }
|
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
public sealed class Report
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
public Guid ReporterId { get; set; }
|
|
public Guid TargetId { get; set; }
|
|
public string TargetName { get; set; } = "";
|
|
public string Type { get; set; } = "user";
|
|
public string Reason { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public string Evidence { get; set; } = "[]";
|
|
public string Status { get; set; } = "待处理";
|
|
public Guid? AssigneeId { get; set; }
|
|
public string? Result { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime? ClosedAt { get; set; }
|
|
public long Version { get; set; }
|
|
}
|
|
// A durable outbox command: both the request and the pending report update commit together.
|
|
public sealed class Operation
|
|
{
|
|
public Guid Id { get; set; }
|
|
public Guid ActorId { get; set; }
|
|
public string ActorName { get; set; } = "";
|
|
public Guid TargetId { get; set; }
|
|
public string Type { get; set; } = "";
|
|
public string Action { get; set; } = "";
|
|
public string Reason { get; set; } = "";
|
|
public Guid? ReportId { get; set; }
|
|
public string Status { get; set; } = "pending";
|
|
public int Attempts { get; set; }
|
|
public string? Error { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime NextAttemptAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime? CompletedAt { get; set; }
|
|
}
|
|
public sealed class AuditRecord
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
public Guid ActorId { get; set; }
|
|
public string ActorName { get; set; } = "";
|
|
public string Action { get; set; } = "";
|
|
public string TargetId { get; set; } = "";
|
|
public string TargetName { get; set; } = "";
|
|
public string Before { get; set; } = "";
|
|
public string After { get; set; } = "";
|
|
public string Reason { get; set; } = "";
|
|
public Guid? ReportId { get; set; }
|
|
public Guid? OperationId { get; set; }
|
|
public string Result { get; set; } = "成功";
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
public sealed class PasswordReset
|
|
{
|
|
public string Id { get; set; } = "";
|
|
public Guid AccountId { get; set; }
|
|
public DateTime ExpiresAt { get; set; }
|
|
}
|
|
public sealed class AdminDb(DbContextOptions<AdminDb> options) : DbContext(options)
|
|
{
|
|
public DbSet<AdminAccount> Accounts => Set<AdminAccount>();
|
|
public DbSet<SystemSetting> Settings => Set<SystemSetting>();
|
|
public DbSet<Report> Reports => Set<Report>();
|
|
public DbSet<Operation> Operations => Set<Operation>();
|
|
public DbSet<AuditRecord> Audit => Set<AuditRecord>();
|
|
public DbSet<PasswordReset> Resets => Set<PasswordReset>();
|
|
protected override void OnModelCreating(ModelBuilder b)
|
|
{
|
|
b.Entity<AdminAccount>().ToTable("admin_accounts").HasIndex(x => x.Account).IsUnique();
|
|
b.Entity<AdminAccount>().Property(x => x.Account).HasMaxLength(100);
|
|
b.Entity<AdminAccount>().Property(x => x.Stamp).IsConcurrencyToken();
|
|
b.Entity<SystemSetting>().ToTable("admin_settings").Property(x => x.Id).HasMaxLength(64);
|
|
b.Entity<SystemSetting>().Property(x => x.Version).IsConcurrencyToken();
|
|
b.Entity<Report>().ToTable("admin_reports").HasIndex(x => new { x.ReporterId, x.CreatedAt });
|
|
b.Entity<Report>().HasIndex(x => new { x.Status, x.CreatedAt });
|
|
b.Entity<Report>().Property(x => x.Status).HasMaxLength(30);
|
|
b.Entity<Report>().Property(x => x.Version).IsConcurrencyToken();
|
|
b.Entity<Operation>().ToTable("admin_operations").HasIndex(x => new { x.Status, x.NextAttemptAt });
|
|
b.Entity<Operation>().Property(x => x.Status).HasMaxLength(30);
|
|
b.Entity<AuditRecord>().ToTable("admin_audit").HasIndex(x => x.CreatedAt);
|
|
b.Entity<AuditRecord>().HasIndex(x => x.OperationId).IsUnique();
|
|
b.Entity<PasswordReset>().ToTable("admin_password_resets").Property(x => x.Id).HasMaxLength(64);
|
|
}
|
|
}
|