Split SQLite rebuild migration from roles change
This commit is contained in:
@@ -121,7 +121,7 @@ For migration authoring, use the local tool command form:
|
||||
dotnet dotnet-ef migrations add <MigrationName> --project RpgRoller/RpgRoller.csproj --startup-project RpgRoller/RpgRoller.csproj
|
||||
```
|
||||
|
||||
For SQLite migrations, avoid `migrationBuilder.Sql(...)` in the same migration step that rebuilds a table for schema changes; prefer column defaults or a follow-up migration so EF Core does not warn about raw SQL executing while a rebuilt table is still pending.
|
||||
For SQLite migrations, keep table-rebuild operations isolated from unrelated schema/data changes. If a migration needs both a rebuild-triggering change (for example `AlterColumn`) and another independent operation, split them into separate migrations so EF Core does not emit non-transactional migration warnings.
|
||||
|
||||
## Frontend Runtime
|
||||
|
||||
|
||||
@@ -199,6 +199,11 @@ public sealed class HostingCoverageTests
|
||||
var rolesHistoryCount = Convert.ToInt32(rolesHistoryCommand.ExecuteScalar());
|
||||
Assert.Equal(1, rolesHistoryCount);
|
||||
|
||||
using var authorizationRolesHistoryCommand = verifyConnection.CreateCommand();
|
||||
authorizationRolesHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226170000_AddAuthorizationRoles';";
|
||||
var authorizationRolesHistoryCount = Convert.ToInt32(authorizationRolesHistoryCommand.ExecuteScalar());
|
||||
Assert.Equal(1, authorizationRolesHistoryCount);
|
||||
|
||||
using var rolemasterHistoryCommand = verifyConnection.CreateCommand();
|
||||
rolemasterHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260402222501_AddRolemasterFumbleRange';";
|
||||
var rolemasterHistoryCount = Convert.ToInt32(rolemasterHistoryCommand.ExecuteScalar());
|
||||
@@ -206,20 +211,147 @@ public sealed class HostingCoverageTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthorizationRolesAndCampaignDeletion_MigrationScript_DoesNotMixUsersSqlIntoCharactersRebuild()
|
||||
public void AuthorizationMigrations_SplitCharactersRebuildFromRolesColumnAddition()
|
||||
{
|
||||
var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-migration-script-{Guid.NewGuid():N}.db");
|
||||
var options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
||||
|
||||
using var db = new RpgRollerDbContext(options);
|
||||
var migrator = db.GetService<IMigrator>();
|
||||
var script = migrator.GenerateScript(
|
||||
var charactersScript = migrator.GenerateScript(
|
||||
fromMigration: "20260226131003_AddSkillGroupPrototypes",
|
||||
toMigration: "20260226160859_AddAuthorizationRolesAndCampaignDeletion");
|
||||
var rolesScript = migrator.GenerateScript(
|
||||
fromMigration: "20260226160859_AddAuthorizationRolesAndCampaignDeletion",
|
||||
toMigration: "20260226170000_AddAuthorizationRoles");
|
||||
|
||||
Assert.Contains("""ALTER TABLE "Users" ADD "Roles" TEXT NOT NULL DEFAULT 'admin';""", script);
|
||||
Assert.Contains("""CREATE TABLE "ef_temp_Characters" (""", script);
|
||||
Assert.DoesNotContain("UPDATE Users", script);
|
||||
Assert.Contains("""CREATE TABLE "ef_temp_Characters" (""", charactersScript);
|
||||
Assert.DoesNotContain("""ALTER TABLE "Users" ADD "Roles" TEXT NOT NULL DEFAULT 'admin';""", charactersScript);
|
||||
Assert.Contains("""ALTER TABLE "Users" ADD "Roles" TEXT NOT NULL DEFAULT 'admin';""", rolesScript);
|
||||
Assert.DoesNotContain("""CREATE TABLE "ef_temp_Characters" (""", rolesScript);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SqliteSchemaUpgrader_BackfillsSplitAuthorizationRolesMigrationHistory()
|
||||
{
|
||||
var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-split-history-{Guid.NewGuid():N}.db");
|
||||
|
||||
using (var connection = new SqliteConnection($"Data Source={dbPath}"))
|
||||
{
|
||||
connection.Open();
|
||||
using var command = connection.CreateCommand();
|
||||
command.CommandText = """
|
||||
CREATE TABLE "__EFMigrationsHistory" (
|
||||
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY,
|
||||
"ProductVersion" TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES
|
||||
('20260226084000_InitialSchema', '10.0.2'),
|
||||
('20260226090000_ModelSync', '10.0.2'),
|
||||
('20260226100000_AddRollLogDice', '10.0.2'),
|
||||
('20260226124941_AddSkillGroupsAndCharacterOwnerTransfer', '10.0.2'),
|
||||
('20260226131003_AddSkillGroupPrototypes', '10.0.2'),
|
||||
('20260226160859_AddAuthorizationRolesAndCampaignDeletion', '10.0.2');
|
||||
|
||||
CREATE TABLE "Users" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_Users" PRIMARY KEY,
|
||||
"Username" TEXT NOT NULL,
|
||||
"UsernameNormalized" TEXT NOT NULL,
|
||||
"PasswordHash" TEXT NOT NULL,
|
||||
"DisplayName" TEXT NOT NULL,
|
||||
"ActiveCharacterId" TEXT NULL,
|
||||
"Roles" TEXT NOT NULL DEFAULT 'admin'
|
||||
);
|
||||
|
||||
CREATE TABLE "Sessions" (
|
||||
"Token" TEXT NOT NULL CONSTRAINT "PK_Sessions" PRIMARY KEY,
|
||||
"UserId" TEXT NOT NULL,
|
||||
"CreatedAtUtc" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "Campaigns" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_Campaigns" PRIMARY KEY,
|
||||
"GmUserId" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Ruleset" TEXT NOT NULL,
|
||||
"Version" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "Characters" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_Characters" PRIMARY KEY,
|
||||
"OwnerUserId" TEXT NOT NULL,
|
||||
"CampaignId" TEXT NULL,
|
||||
"Name" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "IX_Characters_OwnerUserId" ON "Characters" ("OwnerUserId");
|
||||
CREATE INDEX "IX_Characters_CampaignId" ON "Characters" ("CampaignId");
|
||||
|
||||
CREATE TABLE "SkillGroups" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_SkillGroups" PRIMARY KEY,
|
||||
"CharacterId" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"AllowFumble" INTEGER NOT NULL,
|
||||
"DiceRollDefinition" TEXT NOT NULL,
|
||||
"WildDice" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "IX_SkillGroups_CharacterId" ON "SkillGroups" ("CharacterId");
|
||||
|
||||
CREATE TABLE "Skills" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_Skills" PRIMARY KEY,
|
||||
"CharacterId" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"DiceRollDefinition" TEXT NOT NULL,
|
||||
"WildDice" INTEGER NOT NULL,
|
||||
"AllowFumble" INTEGER NOT NULL,
|
||||
"SkillGroupId" TEXT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "IX_Skills_CharacterId" ON "Skills" ("CharacterId");
|
||||
CREATE INDEX "IX_Skills_SkillGroupId" ON "Skills" ("SkillGroupId");
|
||||
|
||||
CREATE TABLE "RollLogEntries" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_RollLogEntries" PRIMARY KEY,
|
||||
"CampaignId" TEXT NOT NULL,
|
||||
"CharacterId" TEXT NOT NULL,
|
||||
"SkillId" TEXT NOT NULL,
|
||||
"RollerUserId" TEXT NOT NULL,
|
||||
"Visibility" TEXT NOT NULL,
|
||||
"Result" INTEGER NOT NULL,
|
||||
"Breakdown" TEXT NOT NULL,
|
||||
"TimestampUtc" TEXT NOT NULL,
|
||||
"Dice" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "IX_RollLogEntries_CampaignId" ON "RollLogEntries" ("CampaignId");
|
||||
CREATE INDEX "IX_RollLogEntries_CharacterId" ON "RollLogEntries" ("CharacterId");
|
||||
CREATE INDEX "IX_RollLogEntries_RollerUserId" ON "RollLogEntries" ("RollerUserId");
|
||||
CREATE INDEX "IX_RollLogEntries_SkillId" ON "RollLogEntries" ("SkillId");
|
||||
""";
|
||||
_ = command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
var options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
||||
using (var db = new RpgRollerDbContext(options))
|
||||
{
|
||||
SqliteSchemaUpgrader.ApplyPendingChanges(db);
|
||||
}
|
||||
|
||||
using var verifyConnection = new SqliteConnection($"Data Source={dbPath}");
|
||||
verifyConnection.Open();
|
||||
|
||||
using var authorizationRolesHistoryCommand = verifyConnection.CreateCommand();
|
||||
authorizationRolesHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226170000_AddAuthorizationRoles';";
|
||||
var authorizationRolesHistoryCount = Convert.ToInt32(authorizationRolesHistoryCommand.ExecuteScalar());
|
||||
Assert.Equal(1, authorizationRolesHistoryCount);
|
||||
|
||||
using var rolemasterHistoryCommand = verifyConnection.CreateCommand();
|
||||
rolemasterHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260402222501_AddRolemasterFumbleRange';";
|
||||
var rolemasterHistoryCount = Convert.ToInt32(rolemasterHistoryCommand.ExecuteScalar());
|
||||
Assert.Equal(1, rolemasterHistoryCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -343,5 +475,10 @@ public sealed class HostingCoverageTests
|
||||
skillGroupColumns.Add(skillGroupsTableInfoReader.GetString(1));
|
||||
|
||||
Assert.Contains("FumbleRange", skillGroupColumns);
|
||||
|
||||
using var authorizationRolesHistoryCommand = verifyConnection.CreateCommand();
|
||||
authorizationRolesHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226170000_AddAuthorizationRoles';";
|
||||
var authorizationRolesHistoryCount = Convert.ToInt32(authorizationRolesHistoryCommand.ExecuteScalar());
|
||||
Assert.Equal(1, authorizationRolesHistoryCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,23 @@ public static class SqliteSchemaUpgrader
|
||||
public static void ApplyPendingChanges(RpgRollerDbContext db)
|
||||
{
|
||||
if (db.Database.IsSqlite())
|
||||
{
|
||||
db.Database.OpenConnection();
|
||||
try
|
||||
{
|
||||
EnsureLegacySchemaHistory(db);
|
||||
EnsureSplitMigrationHistory(db);
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.Database.CloseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
db.Database.Migrate();
|
||||
}
|
||||
|
||||
private static void EnsureLegacySchemaHistory(RpgRollerDbContext db)
|
||||
{
|
||||
db.Database.OpenConnection();
|
||||
try
|
||||
{
|
||||
if (TableExists(db, "__EFMigrationsHistory"))
|
||||
return;
|
||||
@@ -36,28 +44,24 @@ public static class SqliteSchemaUpgrader
|
||||
""";
|
||||
_ = createHistoryCommand.ExecuteNonQuery();
|
||||
|
||||
using var insertHistoryCommand = db.Database.GetDbConnection().CreateCommand();
|
||||
insertHistoryCommand.CommandText = """
|
||||
INSERT OR IGNORE INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES ($migrationId, $productVersion);
|
||||
""";
|
||||
|
||||
var migrationParameter = insertHistoryCommand.CreateParameter();
|
||||
migrationParameter.ParameterName = "$migrationId";
|
||||
migrationParameter.Value = InitialMigrationId;
|
||||
insertHistoryCommand.Parameters.Add(migrationParameter);
|
||||
|
||||
var productVersionParameter = insertHistoryCommand.CreateParameter();
|
||||
productVersionParameter.ParameterName = "$productVersion";
|
||||
productVersionParameter.Value = ProductVersion;
|
||||
insertHistoryCommand.Parameters.Add(productVersionParameter);
|
||||
|
||||
_ = insertHistoryCommand.ExecuteNonQuery();
|
||||
InsertMigrationHistory(db, InitialMigrationId);
|
||||
}
|
||||
finally
|
||||
|
||||
private static void EnsureSplitMigrationHistory(RpgRollerDbContext db)
|
||||
{
|
||||
db.Database.CloseConnection();
|
||||
}
|
||||
if (!TableExists(db, "__EFMigrationsHistory"))
|
||||
return;
|
||||
|
||||
if (!MigrationExists(db, CharactersCampaignDeletionMigrationId))
|
||||
return;
|
||||
|
||||
if (MigrationExists(db, AuthorizationRolesMigrationId))
|
||||
return;
|
||||
|
||||
if (!ColumnExists(db, "Users", "Roles"))
|
||||
return;
|
||||
|
||||
InsertMigrationHistory(db, AuthorizationRolesMigrationId);
|
||||
}
|
||||
|
||||
private static bool TableExists(RpgRollerDbContext db, string tableName)
|
||||
@@ -87,6 +91,46 @@ public static class SqliteSchemaUpgrader
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool MigrationExists(RpgRollerDbContext db, string migrationId)
|
||||
{
|
||||
using var command = db.Database.GetDbConnection().CreateCommand();
|
||||
command.CommandText = """
|
||||
SELECT 1
|
||||
FROM "__EFMigrationsHistory"
|
||||
WHERE "MigrationId" = $migrationId
|
||||
LIMIT 1;
|
||||
""";
|
||||
var migrationParameter = command.CreateParameter();
|
||||
migrationParameter.ParameterName = "$migrationId";
|
||||
migrationParameter.Value = migrationId;
|
||||
command.Parameters.Add(migrationParameter);
|
||||
|
||||
return command.ExecuteScalar() is not null;
|
||||
}
|
||||
|
||||
private static void InsertMigrationHistory(RpgRollerDbContext db, string migrationId)
|
||||
{
|
||||
using var insertHistoryCommand = db.Database.GetDbConnection().CreateCommand();
|
||||
insertHistoryCommand.CommandText = """
|
||||
INSERT OR IGNORE INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES ($migrationId, $productVersion);
|
||||
""";
|
||||
|
||||
var migrationParameter = insertHistoryCommand.CreateParameter();
|
||||
migrationParameter.ParameterName = "$migrationId";
|
||||
migrationParameter.Value = migrationId;
|
||||
insertHistoryCommand.Parameters.Add(migrationParameter);
|
||||
|
||||
var productVersionParameter = insertHistoryCommand.CreateParameter();
|
||||
productVersionParameter.ParameterName = "$productVersion";
|
||||
productVersionParameter.Value = ProductVersion;
|
||||
insertHistoryCommand.Parameters.Add(productVersionParameter);
|
||||
|
||||
_ = insertHistoryCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private const string InitialMigrationId = "20260226084000_InitialSchema";
|
||||
private const string CharactersCampaignDeletionMigrationId = "20260226160859_AddAuthorizationRolesAndCampaignDeletion";
|
||||
private const string AuthorizationRolesMigrationId = "20260226170000_AddAuthorizationRoles";
|
||||
private const string ProductVersion = "10.0.2";
|
||||
}
|
||||
@@ -211,11 +211,6 @@ namespace RpgRoller.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
|
||||
@@ -11,14 +11,6 @@ namespace RpgRoller.Migrations
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Roles",
|
||||
table: "Users",
|
||||
type: "TEXT",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
defaultValue: "admin");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CampaignId",
|
||||
table: "Characters",
|
||||
@@ -31,10 +23,6 @@ namespace RpgRoller.Migrations
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Roles",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CampaignId",
|
||||
table: "Characters",
|
||||
|
||||
258
RpgRoller/Migrations/20260226170000_AddAuthorizationRoles.Designer.cs
generated
Normal file
258
RpgRoller/Migrations/20260226170000_AddAuthorizationRoles.Designer.cs
generated
Normal file
@@ -0,0 +1,258 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using RpgRoller.Data;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RpgRoller.Migrations
|
||||
{
|
||||
[DbContext(typeof(RpgRollerDbContext))]
|
||||
[Migration("20260226170000_AddAuthorizationRoles")]
|
||||
partial class AddAuthorizationRoles
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.2");
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.Campaign", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("GmUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Ruleset")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("Version")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GmUserId");
|
||||
|
||||
b.ToTable("Campaigns");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("CampaignId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("OwnerUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CampaignId");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.RollLogEntry", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Breakdown")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("CampaignId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Dice")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Result")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("RollerUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("SkillId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("TimestampUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Visibility")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CampaignId");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("RollerUserId");
|
||||
|
||||
b.HasIndex("SkillId");
|
||||
|
||||
b.ToTable("RollLogEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.Skill", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("AllowFumble")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DiceRollDefinition")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("SkillGroupId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("WildDice")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("SkillGroupId");
|
||||
|
||||
b.ToTable("Skills");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.SkillGroup", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("AllowFumble")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DiceRollDefinition")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("WildDice")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("SkillGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.UserAccount", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("ActiveCharacterId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Roles")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UsernameNormalized")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UsernameNormalized")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("RpgRoller.Domain.UserSession", b =>
|
||||
{
|
||||
b.Property<string>("Token")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Token");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Sessions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
30
RpgRoller/Migrations/20260226170000_AddAuthorizationRoles.cs
Normal file
30
RpgRoller/Migrations/20260226170000_AddAuthorizationRoles.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RpgRoller.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddAuthorizationRoles : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Roles",
|
||||
table: "Users",
|
||||
type: "TEXT",
|
||||
maxLength: 256,
|
||||
nullable: false,
|
||||
defaultValue: "admin");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Roles",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user