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
|
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
|
## Frontend Runtime
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,11 @@ public sealed class HostingCoverageTests
|
|||||||
var rolesHistoryCount = Convert.ToInt32(rolesHistoryCommand.ExecuteScalar());
|
var rolesHistoryCount = Convert.ToInt32(rolesHistoryCommand.ExecuteScalar());
|
||||||
Assert.Equal(1, rolesHistoryCount);
|
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();
|
using var rolemasterHistoryCommand = verifyConnection.CreateCommand();
|
||||||
rolemasterHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260402222501_AddRolemasterFumbleRange';";
|
rolemasterHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260402222501_AddRolemasterFumbleRange';";
|
||||||
var rolemasterHistoryCount = Convert.ToInt32(rolemasterHistoryCommand.ExecuteScalar());
|
var rolemasterHistoryCount = Convert.ToInt32(rolemasterHistoryCommand.ExecuteScalar());
|
||||||
@@ -206,20 +211,147 @@ public sealed class HostingCoverageTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AuthorizationRolesAndCampaignDeletion_MigrationScript_DoesNotMixUsersSqlIntoCharactersRebuild()
|
public void AuthorizationMigrations_SplitCharactersRebuildFromRolesColumnAddition()
|
||||||
{
|
{
|
||||||
var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-migration-script-{Guid.NewGuid():N}.db");
|
var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-migration-script-{Guid.NewGuid():N}.db");
|
||||||
var options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
var options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
||||||
|
|
||||||
using var db = new RpgRollerDbContext(options);
|
using var db = new RpgRollerDbContext(options);
|
||||||
var migrator = db.GetService<IMigrator>();
|
var migrator = db.GetService<IMigrator>();
|
||||||
var script = migrator.GenerateScript(
|
var charactersScript = migrator.GenerateScript(
|
||||||
fromMigration: "20260226131003_AddSkillGroupPrototypes",
|
fromMigration: "20260226131003_AddSkillGroupPrototypes",
|
||||||
toMigration: "20260226160859_AddAuthorizationRolesAndCampaignDeletion");
|
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" (""", charactersScript);
|
||||||
Assert.Contains("""CREATE TABLE "ef_temp_Characters" (""", script);
|
Assert.DoesNotContain("""ALTER TABLE "Users" ADD "Roles" TEXT NOT NULL DEFAULT 'admin';""", charactersScript);
|
||||||
Assert.DoesNotContain("UPDATE Users", script);
|
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]
|
[Fact]
|
||||||
@@ -343,5 +475,10 @@ public sealed class HostingCoverageTests
|
|||||||
skillGroupColumns.Add(skillGroupsTableInfoReader.GetString(1));
|
skillGroupColumns.Add(skillGroupsTableInfoReader.GetString(1));
|
||||||
|
|
||||||
Assert.Contains("FumbleRange", skillGroupColumns);
|
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,56 +8,60 @@ public static class SqliteSchemaUpgrader
|
|||||||
public static void ApplyPendingChanges(RpgRollerDbContext db)
|
public static void ApplyPendingChanges(RpgRollerDbContext db)
|
||||||
{
|
{
|
||||||
if (db.Database.IsSqlite())
|
if (db.Database.IsSqlite())
|
||||||
EnsureLegacySchemaHistory(db);
|
{
|
||||||
|
db.Database.OpenConnection();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EnsureLegacySchemaHistory(db);
|
||||||
|
EnsureSplitMigrationHistory(db);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
db.Database.CloseConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db.Database.Migrate();
|
db.Database.Migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EnsureLegacySchemaHistory(RpgRollerDbContext db)
|
private static void EnsureLegacySchemaHistory(RpgRollerDbContext db)
|
||||||
{
|
{
|
||||||
db.Database.OpenConnection();
|
if (TableExists(db, "__EFMigrationsHistory"))
|
||||||
try
|
return;
|
||||||
{
|
|
||||||
if (TableExists(db, "__EFMigrationsHistory"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!TableExists(db, "Skills"))
|
if (!TableExists(db, "Skills"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!ColumnExists(db, "Skills", "WildDice") || !ColumnExists(db, "Skills", "AllowFumble"))
|
if (!ColumnExists(db, "Skills", "WildDice") || !ColumnExists(db, "Skills", "AllowFumble"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var createHistoryCommand = db.Database.GetDbConnection().CreateCommand();
|
using var createHistoryCommand = db.Database.GetDbConnection().CreateCommand();
|
||||||
createHistoryCommand.CommandText = """
|
createHistoryCommand.CommandText = """
|
||||||
CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
||||||
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY,
|
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY,
|
||||||
"ProductVersion" TEXT NOT NULL
|
"ProductVersion" TEXT NOT NULL
|
||||||
);
|
);
|
||||||
""";
|
""";
|
||||||
_ = createHistoryCommand.ExecuteNonQuery();
|
_ = createHistoryCommand.ExecuteNonQuery();
|
||||||
|
|
||||||
using var insertHistoryCommand = db.Database.GetDbConnection().CreateCommand();
|
InsertMigrationHistory(db, InitialMigrationId);
|
||||||
insertHistoryCommand.CommandText = """
|
}
|
||||||
INSERT OR IGNORE INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
|
||||||
VALUES ($migrationId, $productVersion);
|
|
||||||
""";
|
|
||||||
|
|
||||||
var migrationParameter = insertHistoryCommand.CreateParameter();
|
private static void EnsureSplitMigrationHistory(RpgRollerDbContext db)
|
||||||
migrationParameter.ParameterName = "$migrationId";
|
{
|
||||||
migrationParameter.Value = InitialMigrationId;
|
if (!TableExists(db, "__EFMigrationsHistory"))
|
||||||
insertHistoryCommand.Parameters.Add(migrationParameter);
|
return;
|
||||||
|
|
||||||
var productVersionParameter = insertHistoryCommand.CreateParameter();
|
if (!MigrationExists(db, CharactersCampaignDeletionMigrationId))
|
||||||
productVersionParameter.ParameterName = "$productVersion";
|
return;
|
||||||
productVersionParameter.Value = ProductVersion;
|
|
||||||
insertHistoryCommand.Parameters.Add(productVersionParameter);
|
|
||||||
|
|
||||||
_ = insertHistoryCommand.ExecuteNonQuery();
|
if (MigrationExists(db, AuthorizationRolesMigrationId))
|
||||||
}
|
return;
|
||||||
finally
|
|
||||||
{
|
if (!ColumnExists(db, "Users", "Roles"))
|
||||||
db.Database.CloseConnection();
|
return;
|
||||||
}
|
|
||||||
|
InsertMigrationHistory(db, AuthorizationRolesMigrationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TableExists(RpgRollerDbContext db, string tableName)
|
private static bool TableExists(RpgRollerDbContext db, string tableName)
|
||||||
@@ -87,6 +91,46 @@ public static class SqliteSchemaUpgrader
|
|||||||
return false;
|
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 InitialMigrationId = "20260226084000_InitialSchema";
|
||||||
|
private const string CharactersCampaignDeletionMigrationId = "20260226160859_AddAuthorizationRolesAndCampaignDeletion";
|
||||||
|
private const string AuthorizationRolesMigrationId = "20260226170000_AddAuthorizationRoles";
|
||||||
private const string ProductVersion = "10.0.2";
|
private const string ProductVersion = "10.0.2";
|
||||||
}
|
}
|
||||||
@@ -211,11 +211,6 @@ namespace RpgRoller.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<string>("Roles")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("Username")
|
b.Property<string>("Username")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(64)
|
.HasMaxLength(64)
|
||||||
|
|||||||
@@ -11,14 +11,6 @@ namespace RpgRoller.Migrations
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "Roles",
|
|
||||||
table: "Users",
|
|
||||||
type: "TEXT",
|
|
||||||
maxLength: 256,
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: "admin");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<Guid>(
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
name: "CampaignId",
|
name: "CampaignId",
|
||||||
table: "Characters",
|
table: "Characters",
|
||||||
@@ -31,10 +23,6 @@ namespace RpgRoller.Migrations
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Roles",
|
|
||||||
table: "Users");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<Guid>(
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
name: "CampaignId",
|
name: "CampaignId",
|
||||||
table: "Characters",
|
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