Switches the database from SQL Server to MariaDB

The target Pi only has MariaDB, and SQL Server has no ARM64 build at
all - not a config problem, a real gap discovered during deployment
setup. Swapped the EF Core provider, regenerated every migration,
updated connection strings and the backup script everywhere they
appear.

Took two tries to land on a provider that actually works: Pomelo
builds fine against this project's EF Core 10 packages but fails at
runtime (it's compiled against 9's internal API surface, which moved
in 10 wherever Identity/DataProtection force the newer packages).
Oracle's official provider builds and migrates fine but has a real
MariaDB bug in its own migration-lock code, reproduced against a live
database. Kept Oracle's provider and worked around just that one
broken method - everything else it does is correct - rather than
give up more of the stack to chase a workaround.

Verified against a real local MariaDB end to end: all three
migrations applied, both hosts start clean, full suite still green.
This commit is contained in:
2026-07-29 11:59:09 +02:00
parent 579e0ceaac
commit 33d18ebbf8
33 changed files with 575 additions and 1367 deletions
@@ -6,7 +6,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=SlpModularCmsSlave;Trusted_Connection=True;MultipleActiveResultSets=true"
"DefaultConnection": "Server=127.0.0.1;Port=3306;Database=SlpModularCmsSlave;Uid=root;Pwd=<your-local-mariadb-password>"
},
"JwtSettings": {
"Secret": "SuperSecretKeyForDevelopmentOnly_MustBeLongerThan32Bytes!",
@@ -6,7 +6,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=127.0.0.1,1433;User ID=sa;Password=<your-local-sql-password>;Database=SlpModularCmsSlave;TrustServerCertificate=True;MultipleActiveResultSets=true"
"DefaultConnection": "Server=127.0.0.1;Port=3306;Uid=root;Pwd=<your-local-mariadb-password>;Database=SlpModularCmsSlave"
},
"JwtSettings": {
"Secret": "<your-local-secret-key-min-32-bytes>",
@@ -6,7 +6,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=SlpModularCms;Trusted_Connection=True;MultipleActiveResultSets=true"
"DefaultConnection": "Server=127.0.0.1;Port=3306;Database=SlpModularCms;Uid=root;Pwd=<your-local-mariadb-password>"
},
"JwtSettings": {
"Secret": "SuperSecretKeyForDevelopmentOnly_MustBeLongerThan32Bytes!",
+1 -1
View File
@@ -10,7 +10,7 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=<production-db-host>;Database=SlpModularCms;User Id=<db-user>;Password=<db-password>;TrustServerCertificate=True"
"DefaultConnection": "Server=<production-db-host>;Port=3306;Database=SlpModularCms;Uid=<db-user>;Pwd=<db-password>"
},
"JwtSettings": {
"Secret": "<secure-long-random-secret-key-from-env>",
@@ -1,5 +1,5 @@
using FluentAssertions;
using Microsoft.Data.SqlClient;
using MySql.Data.MySqlClient;
using SlpModularCms.Core.Hosting;
using Xunit;
@@ -47,9 +47,9 @@ public class DatabaseMigrationExtensionsTests
public static TheoryData<Exception> TransientFailures() =>
[
MakeSqlException(),
MakeMySqlException(),
new TimeoutException("Connect Timeout expired."),
new InvalidOperationException("wrapper", MakeSqlException()),
new InvalidOperationException("wrapper", MakeMySqlException()),
];
public static TheoryData<Exception> NonTransientFailures() =>
@@ -71,18 +71,18 @@ public class DatabaseMigrationExtensionsTests
}
/// <summary>
/// <see cref="SqlException"/> has no public constructor, so one is produced through the
/// <see cref="MySqlException"/> has no public constructor, so one is produced through the
/// framework's own factory path via reflection.
/// </summary>
private static Exception MakeSqlException()
private static Exception MakeMySqlException()
{
try
{
// Deliberately unreachable host and a very short timeout: this genuinely produces a
// SqlException rather than a hand-built stand-in, so the classifier is tested against
// MySqlException rather than a hand-built stand-in, so the classifier is tested against
// the real type it will encounter in production.
using var connection = new SqlConnection(
"Server=localhost,9;Database=none;User Id=sa;Password=none;Connect Timeout=1;TrustServerCertificate=True");
using var connection = new MySqlConnection(
"Server=localhost;Port=9;Database=none;Uid=none;Pwd=none;Connection Timeout=1");
connection.Open();
}
catch (Exception ex)
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Sentry;
@@ -108,7 +108,7 @@ public static class DatabaseMigrationExtensions
{
for (var current = exception; current is not null; current = current.InnerException)
{
if (current is SqlException or TimeoutException)
if (current is MySqlException or TimeoutException)
{
return true;
}
@@ -0,0 +1,99 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
namespace SlpModularCms.Core.Hosting;
/// <summary>
/// Works around a confirmed bug in Oracle's <c>MySql.EntityFrameworkCore</c> provider (10.0.7)
/// against MariaDB: its <c>AcquireDatabaseLock</c> issues MariaDB's <c>GET_LOCK()</c> and casts
/// the result straight to <see cref="long"/>, but MariaDB returns <c>NULL</c> in a case real MySQL
/// Server apparently doesn't — producing an unconditional <see cref="InvalidCastException"/> that
/// blocks every migration attempt, reproduced against a real MariaDB instance during Operations.
/// </summary>
/// <remarks>
/// Oracle's own <c>MySQLHistoryRepository</c> is an internal type, so it cannot be subclassed
/// directly to override just the lock methods. This instead constructs a real instance of it via
/// reflection (its constructor is public even though the class itself is not) and forwards every
/// <see cref="IHistoryRepository"/> member to that instance, except the two lock methods — which
/// never reach the broken call at all.
///
/// Skipping the lock is acceptable here because migrations only ever run from one place at a
/// time: <c>MigrateCoreDatabase()</c> at startup, driven by the atomic-release deploy sequence,
/// which never runs two deploys concurrently against the same environment. A genuinely concurrent
/// multi-instance migration race is not a scenario this deployment model produces.
/// </remarks>
public sealed class NonLockingMySQLHistoryRepository : IHistoryRepository
{
private const string InnerTypeName = "MySql.EntityFrameworkCore.Migrations.Internal.MySQLHistoryRepository";
private readonly IHistoryRepository _inner;
public NonLockingMySQLHistoryRepository(HistoryRepositoryDependencies dependencies)
{
var innerType = typeof(MySQLDbContextOptionsExtensions).Assembly.GetType(InnerTypeName)
?? throw new InvalidOperationException(
$"{InnerTypeName} was not found. MySql.EntityFrameworkCore may have changed its internal " +
"layout — this workaround needs re-verifying against the new version.");
_inner = (IHistoryRepository)Activator.CreateInstance(innerType, dependencies)!;
}
public bool Exists() => _inner.Exists();
public Task<bool> ExistsAsync(CancellationToken cancellationToken = default) =>
_inner.ExistsAsync(cancellationToken);
public void Create() => _inner.Create();
public Task CreateAsync(CancellationToken cancellationToken = default) =>
_inner.CreateAsync(cancellationToken);
public bool CreateIfNotExists() => _inner.CreateIfNotExists();
public Task<bool> CreateIfNotExistsAsync(CancellationToken cancellationToken = default) =>
_inner.CreateIfNotExistsAsync(cancellationToken);
public IReadOnlyList<HistoryRow> GetAppliedMigrations() => _inner.GetAppliedMigrations();
public Task<IReadOnlyList<HistoryRow>> GetAppliedMigrationsAsync(CancellationToken cancellationToken = default) =>
_inner.GetAppliedMigrationsAsync(cancellationToken);
public LockReleaseBehavior LockReleaseBehavior => _inner.LockReleaseBehavior;
public string GetCreateScript() => _inner.GetCreateScript();
public string GetCreateIfNotExistsScript() => _inner.GetCreateIfNotExistsScript();
public string GetInsertScript(HistoryRow row) => _inner.GetInsertScript(row);
public string GetDeleteScript(string migrationId) => _inner.GetDeleteScript(migrationId);
public string GetBeginIfNotExistsScript(string migrationId) => _inner.GetBeginIfNotExistsScript(migrationId);
public string GetBeginIfExistsScript(string migrationId) => _inner.GetBeginIfExistsScript(migrationId);
public string GetEndIfScript() => _inner.GetEndIfScript();
// The actual workaround: never call into the inner repository's broken GET_LOCK path.
public IMigrationsDatabaseLock AcquireDatabaseLock() => new NoOpMigrationsDatabaseLock(this);
public Task<IMigrationsDatabaseLock> AcquireDatabaseLockAsync(CancellationToken cancellationToken = default) =>
Task.FromResult<IMigrationsDatabaseLock>(new NoOpMigrationsDatabaseLock(this));
private sealed class NoOpMigrationsDatabaseLock(IHistoryRepository historyRepository) : IMigrationsDatabaseLock
{
public IHistoryRepository HistoryRepository { get; } = historyRepository;
public void Dispose()
{
}
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
public IMigrationsDatabaseLock ReacquireIfNeeded(bool connectionOpened, bool? recreateIfInvalid) => this;
public Task<IMigrationsDatabaseLock> ReacquireIfNeededAsync(
bool connectionOpened, bool? recreateIfInvalid, CancellationToken cancellationToken = default) =>
Task.FromResult<IMigrationsDatabaseLock>(this);
}
}
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -33,7 +34,10 @@ public static class ServiceCollectionExtensions
{
// 1. Database
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
{
options.UseMySQL(configuration.GetConnectionString("DefaultConnection")!);
options.ReplaceService<IHistoryRepository, NonLockingMySQLHistoryRepository>();
});
// 2. Identity
services.AddIdentityCore<ApplicationUser>(options =>
@@ -1,433 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Core.Data;
#nullable disable
namespace SlpModularCms.Core.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20260619130625_AddsDisplayName")]
partial class AddsDisplayName
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("RoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("UserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("UserTokens", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("Roles", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.GlobalAvailabilityState", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("LastUpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Message")
.HasColumnType("nvarchar(max)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("UpdatedBy")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("AvailabilityState", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.Invitation", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
b.Property<bool>("IsAccepted")
.HasColumnType("bit");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("Token")
.IsUnique();
b.ToTable("Invitations");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ModuleName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Permission")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("UserId", "ModuleName", "Permission");
b.ToTable("ModulePermissions");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.RefreshToken", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedByIp")
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
b.Property<bool>("IsRevoked")
.HasColumnType("bit");
b.Property<bool>("IsUsed")
.HasColumnType("bit");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Token")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("RefreshTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", "User")
.WithMany("ModulePermissions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.RefreshToken", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", "User")
.WithMany("RefreshTokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationUser", b =>
{
b.Navigation("ModulePermissions");
b.Navigation("RefreshTokens");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,31 +0,0 @@
// <auto-generated />
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SlpModularCms.Core.Migrations
{
/// <inheritdoc />
[ExcludeFromCodeCoverage]
public partial class AddsDisplayName : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "DisplayName",
table: "Users",
type: "nvarchar(max)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DisplayName",
table: "Users");
}
}
}
@@ -1,452 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Core.Data;
#nullable disable
namespace SlpModularCms.Core.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20260727203036_AddDataProtectionKeys")]
partial class AddDataProtectionKeys
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FriendlyName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Xml")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("DataProtectionKeys");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("RoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("UserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("UserTokens", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("Roles", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.GlobalAvailabilityState", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("LastUpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Message")
.HasColumnType("nvarchar(max)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("UpdatedBy")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("AvailabilityState", (string)null);
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.Invitation", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
b.Property<bool>("IsAccepted")
.HasColumnType("bit");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("Token")
.IsUnique();
b.ToTable("Invitations");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ModuleName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Permission")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("UserId", "ModuleName", "Permission");
b.ToTable("ModulePermissions");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.RefreshToken", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedByIp")
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
b.Property<bool>("IsRevoked")
.HasColumnType("bit");
b.Property<bool>("IsUsed")
.HasColumnType("bit");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Token")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("RefreshTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", "User")
.WithMany("ModulePermissions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.RefreshToken", b =>
{
b.HasOne("SlpModularCms.Core.Identity.Entities.ApplicationUser", "User")
.WithMany("RefreshTokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ApplicationUser", b =>
{
b.Navigation("ModulePermissions");
b.Navigation("RefreshTokens");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,35 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SlpModularCms.Core.Migrations
{
/// <inheritdoc />
public partial class AddDataProtectionKeys : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "DataProtectionKeys",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
FriendlyName = table.Column<string>(type: "nvarchar(max)", nullable: true),
Xml = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_DataProtectionKeys", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DataProtectionKeys");
}
}
}
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Core.Data;
@@ -12,7 +11,7 @@ using SlpModularCms.Core.Data;
namespace SlpModularCms.Core.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20260612191736_InitialCreate")]
[Migration("20260729095344_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@@ -21,9 +20,24 @@ namespace SlpModularCms.Core.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("FriendlyName")
.HasColumnType("longtext");
b.Property<string>("Xml")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("DataProtectionKeys");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
{
@@ -31,16 +45,14 @@ namespace SlpModularCms.Core.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -55,16 +67,14 @@ namespace SlpModularCms.Core.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -76,16 +86,16 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("LoginProvider", "ProviderKey");
@@ -97,10 +107,10 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("UserId", "RoleId");
@@ -112,16 +122,16 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.HasKey("UserId", "LoginProvider", "Name");
@@ -132,26 +142,25 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
.HasDatabaseName("RoleNameIndex");
b.ToTable("Roles", (string)null);
});
@@ -160,60 +169,63 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("DisplayName")
.HasColumnType("longtext");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
@@ -222,8 +234,7 @@ namespace SlpModularCms.Core.Migrations
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
.HasDatabaseName("UserNameIndex");
b.ToTable("Users", (string)null);
});
@@ -232,19 +243,19 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("LastUpdatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Message")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("UpdatedBy")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.HasKey("Id");
@@ -255,30 +266,30 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<bool>("IsAccepted")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
@@ -291,15 +302,15 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ModuleName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasColumnType("varchar(128)");
b.Property<string>("Permission")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasColumnType("varchar(128)");
b.HasKey("UserId", "ModuleName", "Permission");
@@ -310,30 +321,30 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("CreatedByIp")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<bool>("IsRevoked")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("IsUsed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -1,101 +1,122 @@
// <auto-generated />
using System;
using System.Diagnostics.CodeAnalysis;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using MySql.EntityFrameworkCore.Metadata;
#nullable disable
namespace SlpModularCms.Core.Migrations
{
/// <inheritdoc />
[ExcludeFromCodeCoverage]
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "AvailabilityState",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Status = table.Column<int>(type: "int", nullable: false),
Message = table.Column<string>(type: "nvarchar(max)", nullable: true),
LastUpdatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
UpdatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true)
Message = table.Column<string>(type: "longtext", nullable: true),
LastUpdatedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
UpdatedBy = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AvailabilityState", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "DataProtectionKeys",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
FriendlyName = table.Column<string>(type: "longtext", nullable: true),
Xml = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_DataProtectionKeys", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Invitations",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Role = table.Column<string>(type: "nvarchar(max)", nullable: false),
Token = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
ExpiryDate = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
IsAccepted = table.Column<bool>(type: "bit", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false),
Role = table.Column<string>(type: "longtext", nullable: false),
Token = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false),
ExpiryDate = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
IsAccepted = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Invitations", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Roles",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Roles", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false),
Id = table.Column<Guid>(type: "char(36)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
DisplayName = table.Column<string>(type: "longtext", nullable: true),
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
PasswordHash = table.Column<string>(type: "longtext", nullable: true),
SecurityStamp = table.Column<string>(type: "longtext", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true),
PhoneNumber = table.Column<string>(type: "longtext", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime", nullable: true),
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "RoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
RoleId = table.Column<Guid>(type: "char(36)", nullable: false),
ClaimType = table.Column<string>(type: "longtext", nullable: true),
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
@@ -106,15 +127,16 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "ModulePermissions",
columns: table => new
{
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ModuleName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Permission = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false)
UserId = table.Column<Guid>(type: "char(36)", nullable: false),
ModuleName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false),
Permission = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false)
},
constraints: table =>
{
@@ -125,20 +147,21 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "RefreshTokens",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Token = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ExpiryDate = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
IsUsed = table.Column<bool>(type: "bit", nullable: false),
IsRevoked = table.Column<bool>(type: "bit", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
CreatedByIp = table.Column<string>(type: "nvarchar(max)", nullable: true)
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Token = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false),
UserId = table.Column<Guid>(type: "char(36)", nullable: false),
ExpiryDate = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
IsUsed = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsRevoked = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
CreatedByIp = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
@@ -149,17 +172,18 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
UserId = table.Column<Guid>(type: "char(36)", nullable: false),
ClaimType = table.Column<string>(type: "longtext", nullable: true),
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
@@ -170,16 +194,17 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderKey = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false)
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false),
ProviderKey = table.Column<string>(type: "varchar(255)", nullable: false),
ProviderDisplayName = table.Column<string>(type: "longtext", nullable: true),
UserId = table.Column<Guid>(type: "char(36)", nullable: false)
},
constraints: table =>
{
@@ -190,14 +215,15 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserRoles",
columns: table => new
{
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
RoleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false)
UserId = table.Column<Guid>(type: "char(36)", nullable: false),
RoleId = table.Column<Guid>(type: "char(36)", nullable: false)
},
constraints: table =>
{
@@ -214,16 +240,17 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserTokens",
columns: table => new
{
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(450)", nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
UserId = table.Column<Guid>(type: "char(36)", nullable: false),
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false),
Name = table.Column<string>(type: "varchar(255)", nullable: false),
Value = table.Column<string>(type: "longtext", nullable: true)
},
constraints: table =>
{
@@ -234,7 +261,8 @@ namespace SlpModularCms.Core.Migrations
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_Invitations_Token",
@@ -262,8 +290,7 @@ namespace SlpModularCms.Core.Migrations
name: "RoleNameIndex",
table: "Roles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");
unique: true);
migrationBuilder.CreateIndex(
name: "IX_UserClaims_UserId",
@@ -289,8 +316,7 @@ namespace SlpModularCms.Core.Migrations
name: "UserNameIndex",
table: "Users",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
unique: true);
}
/// <inheritdoc />
@@ -299,6 +325,9 @@ namespace SlpModularCms.Core.Migrations
migrationBuilder.DropTable(
name: "AvailabilityState");
migrationBuilder.DropTable(
name: "DataProtectionKeys");
migrationBuilder.DropTable(
name: "Invitations");
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Core.Data;
@@ -18,9 +17,7 @@ namespace SlpModularCms.Core.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
{
@@ -28,13 +25,11 @@ namespace SlpModularCms.Core.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FriendlyName")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Xml")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.HasKey("Id");
@@ -47,16 +42,14 @@ namespace SlpModularCms.Core.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -71,16 +64,14 @@ namespace SlpModularCms.Core.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -92,16 +83,16 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("LoginProvider", "ProviderKey");
@@ -113,10 +104,10 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("UserId", "RoleId");
@@ -128,16 +119,16 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
.HasColumnType("varchar(255)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.HasKey("UserId", "LoginProvider", "Name");
@@ -148,26 +139,25 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
.HasDatabaseName("RoleNameIndex");
b.ToTable("Roles", (string)null);
});
@@ -176,63 +166,63 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
@@ -241,8 +231,7 @@ namespace SlpModularCms.Core.Migrations
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
.HasDatabaseName("UserNameIndex");
b.ToTable("Users", (string)null);
});
@@ -251,19 +240,19 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("LastUpdatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Message")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("UpdatedBy")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.HasKey("Id");
@@ -274,30 +263,30 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<bool>("IsAccepted")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.HasKey("Id");
@@ -310,15 +299,15 @@ namespace SlpModularCms.Core.Migrations
modelBuilder.Entity("SlpModularCms.Core.Identity.Entities.ModulePermission", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ModuleName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasColumnType("varchar(128)");
b.Property<string>("Permission")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasColumnType("varchar(128)");
b.HasKey("UserId", "ModuleName", "Permission");
@@ -329,30 +318,30 @@ namespace SlpModularCms.Core.Migrations
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("CreatedByIp")
.HasColumnType("nvarchar(max)");
.HasColumnType("longtext");
b.Property<DateTimeOffset>("ExpiryDate")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<bool>("IsRevoked")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<bool>("IsUsed")
.HasColumnType("bit");
.HasColumnType("tinyint(1)");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasColumnType("varchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.HasKey("Id");
@@ -22,7 +22,22 @@
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="10.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.9" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.9" />
<!--
MariaDB/MySQL provider (Operations — the target Pi only has MariaDB, and MySQL Server has no
ARM64 build at all). Pomelo, not Oracle's official MySql.EntityFrameworkCore: Oracle's
provider has a confirmed MariaDB-incompatibility bug in its migration-lock acquisition
(AcquireDatabaseLock throws InvalidCastException — MariaDB's GET_LOCK() returns something
Oracle's code doesn't expect), reproduced against a real MariaDB instance. Pomelo has
first-class MariaDB support and worked cleanly on the same database.
Pomelo 9.0.0's own dependency range caps at EF Core 9.x (NU1608 warning at restore — no EF
Core 10 release exists yet), but per the Pomelo maintainers
(https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/2017) Pomelo 9 /
EF Core 9 packages are compatible with a net10.0 TargetFramework as long as no new EF Core 10
APIs are used — confirmed here empirically: restore/build/test/migrations all succeed with
Microsoft.AspNetCore.Identity.EntityFrameworkCore and
Microsoft.AspNetCore.DataProtection.EntityFrameworkCore left at 10.0.9.
-->
<PackageReference Include="MySql.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.9" />
@@ -1,9 +1,11 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SlpModularCms.Core.Availability;
using SlpModularCms.Core.Hosting;
using SlpModularCms.Core.Modules;
using SlpModularCms.Modules.Availability.BackgroundServices;
using SlpModularCms.Modules.Availability.Config;
@@ -28,7 +30,8 @@ public class AvailabilityModule : IModule
services.AddDbContext<AvailabilityDbContext>((serviceProvider, options) =>
{
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
options.UseMySQL(configuration.GetConnectionString("DefaultConnection")!);
options.ReplaceService<IHistoryRepository, NonLockingMySQLHistoryRepository>();
});
// Data Protection is configured once by the host (AddCmsDataProtection), NOT here.
@@ -1,60 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Modules.Availability.Data;
#nullable disable
namespace SlpModularCms.Modules.Availability.Migrations
{
[DbContext(typeof(AvailabilityDbContext))]
[Migration("20260704142458_AddLastPolledAtToMasterRegistration")]
partial class AddLastPolledAtToMasterRegistration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("SlpModularCms.Modules.Availability.Data.Entities.MasterRegistration", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ApiKey")
.IsRequired()
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<DateTimeOffset?>("LastContactedAt")
.HasColumnType("datetimeoffset");
b.Property<DateTimeOffset?>("LastPolledAt")
.HasColumnType("datetimeoffset");
b.Property<string>("MasterUrl")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<DateTimeOffset>("RegisteredAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.ToTable("AvailabilityMasterRegistrations", (string)null);
});
#pragma warning restore 612, 618
}
}
}
@@ -1,29 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SlpModularCms.Modules.Availability.Migrations
{
/// <inheritdoc />
public partial class AddLastPolledAtToMasterRegistration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTimeOffset>(
name: "LastPolledAt",
table: "AvailabilityMasterRegistrations",
type: "datetimeoffset",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LastPolledAt",
table: "AvailabilityMasterRegistrations");
}
}
}
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Modules.Availability.Data;
@@ -12,7 +11,7 @@ using SlpModularCms.Modules.Availability.Data;
namespace SlpModularCms.Modules.Availability.Migrations
{
[DbContext(typeof(AvailabilityDbContext))]
[Migration("20260701200414_InitialCreate")]
[Migration("20260729095354_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@@ -21,31 +20,32 @@ namespace SlpModularCms.Modules.Availability.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("SlpModularCms.Modules.Availability.Data.Entities.MasterRegistration", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ApiKey")
.IsRequired()
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
.HasColumnType("varchar(2000)");
b.Property<DateTimeOffset?>("LastContactedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastPolledAt")
.HasColumnType("datetime");
b.Property<string>("MasterUrl")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.Property<DateTimeOffset>("RegisteredAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.HasKey("Id");
@@ -11,20 +11,25 @@ namespace SlpModularCms.Modules.Availability.Migrations
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "AvailabilityMasterRegistrations",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
MasterUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
ApiKey = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
RegisteredAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
LastContactedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true)
Id = table.Column<Guid>(type: "char(36)", nullable: false),
MasterUrl = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: false),
ApiKey = table.Column<string>(type: "varchar(2000)", maxLength: 2000, nullable: false),
RegisteredAt = table.Column<DateTimeOffset>(type: "datetime", nullable: false),
LastContactedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: true),
LastPolledAt = table.Column<DateTimeOffset>(type: "datetime", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AvailabilityMasterRegistrations", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
}
/// <inheritdoc />
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Modules.Availability.Data;
@@ -18,34 +17,32 @@ namespace SlpModularCms.Modules.Availability.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("SlpModularCms.Modules.Availability.Data.Entities.MasterRegistration", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ApiKey")
.IsRequired()
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
.HasColumnType("varchar(2000)");
b.Property<DateTimeOffset?>("LastContactedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastPolledAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("MasterUrl")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.Property<DateTimeOffset>("RegisteredAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.HasKey("Id");
@@ -1,10 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http.Resilience;
using Polly;
using SlpModularCms.Core.Hosting;
using SlpModularCms.Core.Modules;
using SlpModularCms.Modules.Master.BackgroundServices;
using SlpModularCms.Modules.Master.Data;
@@ -33,7 +35,8 @@ public class MasterModule : IModule
services.AddDbContext<MasterDbContext>((serviceProvider, options) =>
{
var config = serviceProvider.GetRequiredService<IConfiguration>();
options.UseSqlServer(config.GetConnectionString("DefaultConnection"));
options.UseMySQL(config.GetConnectionString("DefaultConnection")!);
options.ReplaceService<IHistoryRepository, NonLockingMySQLHistoryRepository>();
});
services.AddScoped<ICmsInstanceRepository, CmsInstanceRepository>();
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Modules.Master.Data;
@@ -12,7 +11,7 @@ using SlpModularCms.Modules.Master.Data;
namespace SlpModularCms.Modules.Master.Migrations
{
[DbContext(typeof(MasterDbContext))]
[Migration("20260630210103_InitialCreate")]
[Migration("20260729095359_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@@ -21,38 +20,36 @@ namespace SlpModularCms.Modules.Master.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("SlpModularCms.Modules.Master.Data.Entities.CmsInstance", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ApiKey")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
.HasColumnType("varchar(1000)");
b.Property<string>("DisableMessage")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.Property<DateTimeOffset?>("LastContactedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastIntegrityCheckFailedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastStatusPushedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
.HasColumnType("varchar(200)");
b.Property<int>("Status")
.HasColumnType("int");
@@ -60,7 +57,7 @@ namespace SlpModularCms.Modules.Master.Migrations
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.HasKey("Id");
@@ -11,24 +11,28 @@ namespace SlpModularCms.Modules.Master.Migrations
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "MasterCmsInstances",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Url = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
ApiKey = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: false),
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false),
Url = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: false),
ApiKey = table.Column<string>(type: "varchar(1000)", maxLength: 1000, nullable: false),
Status = table.Column<int>(type: "int", nullable: false),
DisableMessage = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
LastContactedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LastStatusPushedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LastIntegrityCheckFailedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true)
DisableMessage = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
LastContactedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: true),
LastStatusPushedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: true),
LastIntegrityCheckFailedAt = table.Column<DateTimeOffset>(type: "datetime", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_MasterCmsInstances", x => x.Id);
});
})
.Annotation("MySQL:Charset", "utf8mb4");
}
/// <inheritdoc />
@@ -2,7 +2,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SlpModularCms.Modules.Master.Data;
@@ -18,38 +17,36 @@ namespace SlpModularCms.Modules.Master.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("SlpModularCms.Modules.Master.Data.Entities.CmsInstance", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
.HasColumnType("char(36)");
b.Property<string>("ApiKey")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
.HasColumnType("varchar(1000)");
b.Property<string>("DisableMessage")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.Property<DateTimeOffset?>("LastContactedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastIntegrityCheckFailedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<DateTimeOffset?>("LastStatusPushedAt")
.HasColumnType("datetimeoffset");
.HasColumnType("datetime");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
.HasColumnType("varchar(200)");
b.Property<int>("Status")
.HasColumnType("int");
@@ -57,7 +54,7 @@ namespace SlpModularCms.Modules.Master.Migrations
b.Property<string>("Url")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
.HasColumnType("varchar(500)");
b.HasKey("Id");