From 6fa4abd4501704cae2efda2f51703c0fa411c2c7 Mon Sep 17 00:00:00 2001 From: Maxime Date: Thu, 6 Jun 2024 14:59:01 +0200 Subject: [PATCH] added MSSQL Provider (#939) * add sql server * add migrations for MSSQL Provider --------- Co-authored-by: Mukesh Murugan <31455818+iammukeshm@users.noreply.github.com> --- api/Directory.Packages.props | 1 + api/FSH.WebApi.sln | 15 + .../Infrastructure/Infrastructure.csproj | 1 + .../Infrastructure/Jobs/Extensions.cs | 3 + .../Infrastructure/Persistence/DbProviders.cs | 1 + .../Infrastructure/Persistence/Extensions.cs | 2 + .../Services/ConnectionStringValidator.cs | 4 + ...40605195930_Add Catalog Schema.Designer.cs | 73 ++++ .../20240605195930_Add Catalog Schema.cs | 46 +++ .../Catalog/CatalogDbContextModelSnapshot.cs | 70 ++++ ...0605195809_Add Identity Schema.Designer.cs | 359 ++++++++++++++++++ .../20240605195809_Add Identity Schema.cs | 271 +++++++++++++ .../IdentityDbContextModelSnapshot.cs | 356 +++++++++++++++++ api/migrations/MSSQL/MSSQL.csproj | 11 + ...240605195846_Add Tenant Schema.Designer.cs | 69 ++++ .../20240605195846_Add Tenant Schema.cs | 52 +++ .../Tenant/TenantDbContextModelSnapshot.cs | 66 ++++ ...20240605195913_Add Todo Schema.Designer.cs | 69 ++++ .../Todo/20240605195913_Add Todo Schema.cs | 45 +++ .../MSSQL/Todo/TodoDbContextModelSnapshot.cs | 66 ++++ api/server/Server.csproj | 1 + 21 files changed, 1581 insertions(+) create mode 100644 api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.Designer.cs create mode 100644 api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.cs create mode 100644 api/migrations/MSSQL/Catalog/CatalogDbContextModelSnapshot.cs create mode 100644 api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.Designer.cs create mode 100644 api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.cs create mode 100644 api/migrations/MSSQL/Identity/IdentityDbContextModelSnapshot.cs create mode 100644 api/migrations/MSSQL/MSSQL.csproj create mode 100644 api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.Designer.cs create mode 100644 api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.cs create mode 100644 api/migrations/MSSQL/Tenant/TenantDbContextModelSnapshot.cs create mode 100644 api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.Designer.cs create mode 100644 api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.cs create mode 100644 api/migrations/MSSQL/Todo/TodoDbContextModelSnapshot.cs diff --git a/api/Directory.Packages.props b/api/Directory.Packages.props index 63d8fd5ec..40e59f0a0 100644 --- a/api/Directory.Packages.props +++ b/api/Directory.Packages.props @@ -24,6 +24,7 @@ + diff --git a/api/FSH.WebApi.sln b/api/FSH.WebApi.sln index fd7e27ab4..332c8efb1 100644 --- a/api/FSH.WebApi.sln +++ b/api/FSH.WebApi.sln @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostgreSQL", "migrations\Po EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "modules\Shared\Shared.csproj", "{87D0AB12-A19D-42B3-928C-C60AFA698952}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSSQL", "migrations\MSSQL\MSSQL.csproj", "{F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -159,6 +161,18 @@ Global {87D0AB12-A19D-42B3-928C-C60AFA698952}.Release|x64.Build.0 = Release|Any CPU {87D0AB12-A19D-42B3-928C-C60AFA698952}.Release|x86.ActiveCfg = Release|Any CPU {87D0AB12-A19D-42B3-928C-C60AFA698952}.Release|x86.Build.0 = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|x64.ActiveCfg = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|x64.Build.0 = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|x86.ActiveCfg = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Debug|x86.Build.0 = Debug|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|Any CPU.Build.0 = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|x64.ActiveCfg = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|x64.Build.0 = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|x86.ActiveCfg = Release|Any CPU + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -175,6 +189,7 @@ Global {32F5383E-4201-4527-98DB-40715BB9F574} = {F3DF5AC5-8CDC-46D4-969D-1245A6880215} {6EB9D713-B3F6-495A-AF78-8DF2234B758C} = {12F8343D-20A6-4E24-B0F5-3A66F2228CF6} {87D0AB12-A19D-42B3-928C-C60AFA698952} = {32F5383E-4201-4527-98DB-40715BB9F574} + {F99FF9C4-C19D-47A7-BF07-687EB39B2EBC} = {12F8343D-20A6-4E24-B0F5-3A66F2228CF6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EA8248C2-3877-4AF7-8777-A17E7881E030} diff --git a/api/framework/Infrastructure/Infrastructure.csproj b/api/framework/Infrastructure/Infrastructure.csproj index a0a4a3120..1f0fee9ab 100644 --- a/api/framework/Infrastructure/Infrastructure.csproj +++ b/api/framework/Infrastructure/Infrastructure.csproj @@ -25,6 +25,7 @@ + diff --git a/api/framework/Infrastructure/Jobs/Extensions.cs b/api/framework/Infrastructure/Jobs/Extensions.cs index c75a5f948..eb2875ed5 100644 --- a/api/framework/Infrastructure/Jobs/Extensions.cs +++ b/api/framework/Infrastructure/Jobs/Extensions.cs @@ -34,6 +34,9 @@ internal static IServiceCollection ConfigureJobs(this IServiceCollection service o.UseNpgsqlConnection(dbOptions.ConnectionString); }); break; + case DbProviders.MSSQL: + config.UseSqlServerStorage(dbOptions.ConnectionString); + break; default: throw new FshException($"hangfire storage provider {dbOptions.Provider} is not supported"); } diff --git a/api/framework/Infrastructure/Persistence/DbProviders.cs b/api/framework/Infrastructure/Persistence/DbProviders.cs index 25dd83ccc..f330df512 100644 --- a/api/framework/Infrastructure/Persistence/DbProviders.cs +++ b/api/framework/Infrastructure/Persistence/DbProviders.cs @@ -2,4 +2,5 @@ internal static class DbProviders { public const string PostgreSQL = "POSTGRESQL"; + public const string MSSQL = "MSSQL"; } diff --git a/api/framework/Infrastructure/Persistence/Extensions.cs b/api/framework/Infrastructure/Persistence/Extensions.cs index f47cf094c..f07065b69 100644 --- a/api/framework/Infrastructure/Persistence/Extensions.cs +++ b/api/framework/Infrastructure/Persistence/Extensions.cs @@ -17,6 +17,8 @@ internal static DbContextOptionsBuilder ConfigureDatabase(this DbContextOptionsB { DbProviders.PostgreSQL => builder.UseNpgsql(connectionString, e => e.MigrationsAssembly("FSH.WebApi.Migrations.PostgreSQL")), + DbProviders.MSSQL => builder.UseSqlServer(connectionString, e => + e.MigrationsAssembly("FSH.WebApi.Migrations.MSSQL")), _ => throw new InvalidOperationException($"DB Provider {dbProvider} is not supported."), }; } diff --git a/api/framework/Infrastructure/Persistence/Services/ConnectionStringValidator.cs b/api/framework/Infrastructure/Persistence/Services/ConnectionStringValidator.cs index c33ff464b..2b39de48d 100644 --- a/api/framework/Infrastructure/Persistence/Services/ConnectionStringValidator.cs +++ b/api/framework/Infrastructure/Persistence/Services/ConnectionStringValidator.cs @@ -1,4 +1,5 @@ using FSH.Framework.Core.Persistence; +using Microsoft.Data.SqlClient; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Npgsql; @@ -23,6 +24,9 @@ public bool TryValidate(string connectionString, string? dbProvider = null) case DbProviders.PostgreSQL: _ = new NpgsqlConnectionStringBuilder(connectionString); break; + case DbProviders.MSSQL: + _ = new SqlConnectionStringBuilder(connectionString); + break; default: break; } diff --git a/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.Designer.cs b/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.Designer.cs new file mode 100644 index 000000000..23228fc0a --- /dev/null +++ b/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.Designer.cs @@ -0,0 +1,73 @@ +// +using System; +using FSH.WebApi.Catalog.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Catalog +{ + [DbContext(typeof(CatalogDbContext))] + [Migration("20240605195930_Add Catalog Schema")] + partial class AddCatalogSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("catalog") + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.WebApi.Catalog.Domain.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.ToTable("Products", "catalog"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.cs b/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.cs new file mode 100644 index 000000000..8219cc2dc --- /dev/null +++ b/api/migrations/MSSQL/Catalog/20240605195930_Add Catalog Schema.cs @@ -0,0 +1,46 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Catalog +{ + /// + public partial class AddCatalogSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "catalog"); + + migrationBuilder.CreateTable( + name: "Products", + schema: "catalog", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Price = table.Column(type: "decimal(18,2)", nullable: false), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Products", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Products", + schema: "catalog"); + } + } +} diff --git a/api/migrations/MSSQL/Catalog/CatalogDbContextModelSnapshot.cs b/api/migrations/MSSQL/Catalog/CatalogDbContextModelSnapshot.cs new file mode 100644 index 000000000..9508f400c --- /dev/null +++ b/api/migrations/MSSQL/Catalog/CatalogDbContextModelSnapshot.cs @@ -0,0 +1,70 @@ +// +using System; +using FSH.WebApi.Catalog.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Catalog +{ + [DbContext(typeof(CatalogDbContext))] + partial class CatalogDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("catalog") + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.WebApi.Catalog.Domain.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.ToTable("Products", "catalog"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.Designer.cs b/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.Designer.cs new file mode 100644 index 000000000..fd559556d --- /dev/null +++ b/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.Designer.cs @@ -0,0 +1,359 @@ +// +using System; +using FSH.Framework.Infrastructure.Identity.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Identity +{ + [DbContext(typeof(IdentityDbContext))] + [Migration("20240605195809_Add Identity Schema")] + partial class AddIdentitySchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.RoleClaims.FshRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetimeoffset"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.Roles.FshRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName", "TenantId") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Roles", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.Users.FshUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("ImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ObjectId") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("RefreshToken") + .HasColumnType("nvarchar(max)"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime2"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("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", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.RoleClaims.FshRoleClaim", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Roles.FshRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Roles.FshRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.cs b/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.cs new file mode 100644 index 000000000..40d1583f0 --- /dev/null +++ b/api/migrations/MSSQL/Identity/20240605195809_Add Identity Schema.cs @@ -0,0 +1,271 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Identity +{ + /// + public partial class AddIdentitySchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "identity"); + + migrationBuilder.CreateTable( + name: "Roles", + schema: "identity", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + schema: "identity", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: true), + LastName = table.Column(type: "nvarchar(max)", nullable: true), + ImageUrl = table.Column(type: "nvarchar(max)", nullable: true), + IsActive = table.Column(type: "bit", nullable: false), + RefreshToken = table.Column(type: "nvarchar(max)", nullable: true), + RefreshTokenExpiryTime = table.Column(type: "datetime2", nullable: false), + ObjectId = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RoleClaims", + schema: "identity", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedOn = table.Column(type: "datetimeoffset", nullable: false), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_RoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_RoleClaims_Roles_RoleId", + column: x => x.RoleId, + principalSchema: "identity", + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserClaims", + schema: "identity", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaims", x => x.Id); + table.ForeignKey( + name: "FK_UserClaims_Users_UserId", + column: x => x.UserId, + principalSchema: "identity", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogins", + schema: "identity", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogins_Users_UserId", + column: x => x.UserId, + principalSchema: "identity", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + schema: "identity", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_UserRoles_Roles_RoleId", + column: x => x.RoleId, + principalSchema: "identity", + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRoles_Users_UserId", + column: x => x.UserId, + principalSchema: "identity", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserTokens", + schema: "identity", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserTokens_Users_UserId", + column: x => x.UserId, + principalSchema: "identity", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_RoleClaims_RoleId", + schema: "identity", + table: "RoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + schema: "identity", + table: "Roles", + columns: new[] { "NormalizedName", "TenantId" }, + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_UserClaims_UserId", + schema: "identity", + table: "UserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogins_UserId", + schema: "identity", + table: "UserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + schema: "identity", + table: "UserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + schema: "identity", + table: "Users", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + schema: "identity", + table: "Users", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RoleClaims", + schema: "identity"); + + migrationBuilder.DropTable( + name: "UserClaims", + schema: "identity"); + + migrationBuilder.DropTable( + name: "UserLogins", + schema: "identity"); + + migrationBuilder.DropTable( + name: "UserRoles", + schema: "identity"); + + migrationBuilder.DropTable( + name: "UserTokens", + schema: "identity"); + + migrationBuilder.DropTable( + name: "Roles", + schema: "identity"); + + migrationBuilder.DropTable( + name: "Users", + schema: "identity"); + } + } +} diff --git a/api/migrations/MSSQL/Identity/IdentityDbContextModelSnapshot.cs b/api/migrations/MSSQL/Identity/IdentityDbContextModelSnapshot.cs new file mode 100644 index 000000000..1f9d71968 --- /dev/null +++ b/api/migrations/MSSQL/Identity/IdentityDbContextModelSnapshot.cs @@ -0,0 +1,356 @@ +// +using System; +using FSH.Framework.Infrastructure.Identity.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Identity +{ + [DbContext(typeof(IdentityDbContext))] + partial class IdentityDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.RoleClaims.FshRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetimeoffset"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.Roles.FshRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName", "TenantId") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Roles", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.Users.FshUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("ImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ObjectId") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("RefreshToken") + .HasColumnType("nvarchar(max)"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime2"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("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", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "identity"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Identity.RoleClaims.FshRoleClaim", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Roles.FshRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Roles.FshRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("FSH.Framework.Infrastructure.Identity.Users.FshUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/MSSQL.csproj b/api/migrations/MSSQL/MSSQL.csproj new file mode 100644 index 000000000..ce651b272 --- /dev/null +++ b/api/migrations/MSSQL/MSSQL.csproj @@ -0,0 +1,11 @@ + + + FSH.WebApi.Migrations.MSSQL + FSH.WebApi.Migrations.MSSQL + + + + + + + diff --git a/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.Designer.cs b/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.Designer.cs new file mode 100644 index 000000000..8c46e2d0b --- /dev/null +++ b/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.Designer.cs @@ -0,0 +1,69 @@ +// +using System; +using FSH.Framework.Infrastructure.Tenant.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Tenant +{ + [DbContext(typeof(TenantDbContext))] + [Migration("20240605195846_Add Tenant Schema")] + partial class AddTenantSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Tenant.FshTenantInfo", b => + { + b.Property("Id") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("AdminEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConnectionString") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Identifier") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Issuer") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ValidUpto") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("Identifier") + .IsUnique(); + + b.ToTable("Tenants", "tenant"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.cs b/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.cs new file mode 100644 index 000000000..27dd70fbc --- /dev/null +++ b/api/migrations/MSSQL/Tenant/20240605195846_Add Tenant Schema.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Tenant +{ + /// + public partial class AddTenantSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "tenant"); + + migrationBuilder.CreateTable( + name: "Tenants", + schema: "tenant", + columns: table => new + { + Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Identifier = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + ConnectionString = table.Column(type: "nvarchar(max)", nullable: false), + AdminEmail = table.Column(type: "nvarchar(max)", nullable: false), + IsActive = table.Column(type: "bit", nullable: false), + ValidUpto = table.Column(type: "datetime2", nullable: false), + Issuer = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Tenants", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Tenants_Identifier", + schema: "tenant", + table: "Tenants", + column: "Identifier", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Tenants", + schema: "tenant"); + } + } +} diff --git a/api/migrations/MSSQL/Tenant/TenantDbContextModelSnapshot.cs b/api/migrations/MSSQL/Tenant/TenantDbContextModelSnapshot.cs new file mode 100644 index 000000000..cb6311731 --- /dev/null +++ b/api/migrations/MSSQL/Tenant/TenantDbContextModelSnapshot.cs @@ -0,0 +1,66 @@ +// +using System; +using FSH.Framework.Infrastructure.Tenant.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Tenant +{ + [DbContext(typeof(TenantDbContext))] + partial class TenantDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.Framework.Infrastructure.Tenant.FshTenantInfo", b => + { + b.Property("Id") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("AdminEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConnectionString") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Identifier") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Issuer") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ValidUpto") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("Identifier") + .IsUnique(); + + b.ToTable("Tenants", "tenant"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.Designer.cs b/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.Designer.cs new file mode 100644 index 000000000..47a26f75b --- /dev/null +++ b/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.Designer.cs @@ -0,0 +1,69 @@ +// +using System; +using FSH.WebApi.Todo.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Todo +{ + [DbContext(typeof(TodoDbContext))] + [Migration("20240605195913_Add Todo Schema")] + partial class AddTodoSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("todo") + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.WebApi.Todo.Domain.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Note") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Title") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Todos", "todo"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.cs b/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.cs new file mode 100644 index 000000000..e9b091865 --- /dev/null +++ b/api/migrations/MSSQL/Todo/20240605195913_Add Todo Schema.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Todo +{ + /// + public partial class AddTodoSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "todo"); + + migrationBuilder.CreateTable( + name: "Todos", + schema: "todo", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Title = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + Note = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + TenantId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Todos", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Todos", + schema: "todo"); + } + } +} diff --git a/api/migrations/MSSQL/Todo/TodoDbContextModelSnapshot.cs b/api/migrations/MSSQL/Todo/TodoDbContextModelSnapshot.cs new file mode 100644 index 000000000..224b47323 --- /dev/null +++ b/api/migrations/MSSQL/Todo/TodoDbContextModelSnapshot.cs @@ -0,0 +1,66 @@ +// +using System; +using FSH.WebApi.Todo.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace FSH.WebApi.Migrations.MSSQL.Todo +{ + [DbContext(typeof(TodoDbContext))] + partial class TodoDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("todo") + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FSH.WebApi.Todo.Domain.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Note") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Title") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Todos", "todo"); + + b.HasAnnotation("Finbuckle:MultiTenant", true); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/server/Server.csproj b/api/server/Server.csproj index 948a1883e..a40334411 100644 --- a/api/server/Server.csproj +++ b/api/server/Server.csproj @@ -18,6 +18,7 @@ +