From 83e5502111e3652a1a8f636acd43b0f544ee9799 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Fri, 19 Mar 2021 17:01:49 -0700 Subject: [PATCH 01/23] Creation of EF Core Migrations - these execute using EF Tools, but are not integrated to run programmatically --- Oqtane.Client/Oqtane.Client.csproj | 8 +- .../DbContextOptionsBuilderExtensions.cs | 1 + .../Migrations/01000000_InitializeMaster.cs | 60 +++++++ .../Migrations/01000000_InitializeTenant.cs | 157 ++++++++++++++++++ .../01000100_AddAdditionalIndexesInMaster.cs | 50 ++++++ .../01000100_AddAdditionalIndexesInTenant.cs | 64 +++++++ ...000101_AddAdditionColumnToNotifications.cs | 33 ++++ .../Migrations/01000201_DropColumnFromPage.cs | 29 ++++ ...2000001_AddColumnToProfileAndUpdatePage.cs | 51 ++++++ .../02000101_UpdateIconColumnInPage.cs | 21 +++ .../Migrations/02000102_AddLanguageTable.cs | 26 +++ .../02000103_UpdatePageAndAddColumnToSite.cs | 41 +++++ ...2010000_AddIndexesForForeignKeyInMaster.cs | 34 ++++ .../EntityBuilders/AliasEntityBuilder.cs | 44 +++++ .../AspNetUserClaimsEntityBuilder.cs | 42 +++++ .../AspNetUsersEntityBuilder.cs | 73 ++++++++ .../AuditableBaseEntityBuilder.cs | 34 ++++ .../EntityBuilders/BaseEntityBuilder.cs | 118 +++++++++++++ .../DeletableAuditableBaseEntityBuilder.cs | 30 ++++ .../DeletableBaseEntityBuilder.cs | 30 ++++ .../EntityBuilders/FileEntityBuilder.cs | 54 ++++++ .../EntityBuilders/FolderEntityBuilder.cs | 54 ++++++ .../EntityBuilders/JobEntityBuilder.cs | 66 ++++++++ .../EntityBuilders/JobLogEntityBuilder.cs | 47 ++++++ .../EntityBuilders/LanguageEntityBuilder.cs | 47 ++++++ .../EntityBuilders/LogEntityBuilder.cs | 78 +++++++++ .../ModuleDefinitionsEntityBuilder.cs | 48 ++++++ .../EntityBuilders/ModuleEntityBuilder.cs | 44 +++++ .../NotificationEntityBuilder.cs | 65 ++++++++ .../EntityBuilders/PageEntityBuilder.cs | 80 +++++++++ .../EntityBuilders/PageModuleEntityBuilder.cs | 56 +++++++ .../EntityBuilders/PermissionEntityBuilder.cs | 60 +++++++ .../EntityBuilders/ProfileEntityBuilder.cs | 64 +++++++ .../EntityBuilders/RoleEntityBuilder.cs | 50 ++++++ .../EntityBuilders/SettingEntityBuilder.cs | 45 +++++ .../EntityBuilders/SiteEntityBuilder.cs | 67 ++++++++ .../EntityBuilders/TenantEntityBuilder.cs | 42 +++++ .../EntityBuilders/UserEntityBuilder.cs | 52 ++++++ .../EntityBuilders/UserRoleEntityBuilder.cs | 49 ++++++ .../Extensions/ColumnsBuilderExtensions.cs | 47 ++++++ .../CreateTableBuilderExtensions.cs | 24 +++ .../Migrations/Framework/ForeignKey.cs | 33 ++++ .../Migrations/Framework/PrimaryKey.cs | 21 +++ .../HtmlText/Repository/HtmlTextContext.cs | 3 +- Oqtane.Server/Oqtane.Server.csproj | 22 ++- .../Repository/Context/DBContextBase.cs | 16 +- .../Repository/Context/TenantDBContext.cs | 3 +- Oqtane.Shared/Oqtane.Shared.csproj | 2 +- Oqtane.Test/Oqtane.Test.csproj | 2 +- 49 files changed, 2170 insertions(+), 17 deletions(-) create mode 100644 Oqtane.Server/Migrations/01000000_InitializeMaster.cs create mode 100644 Oqtane.Server/Migrations/01000000_InitializeTenant.cs create mode 100644 Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs create mode 100644 Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs create mode 100644 Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs create mode 100644 Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs create mode 100644 Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs create mode 100644 Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs create mode 100644 Oqtane.Server/Migrations/02000102_AddLanguageTable.cs create mode 100644 Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs create mode 100644 Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs create mode 100644 Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs create mode 100644 Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs create mode 100644 Oqtane.Server/Migrations/Framework/ForeignKey.cs create mode 100644 Oqtane.Server/Migrations/Framework/PrimaryKey.cs diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj index f6ce11c8..86894b7a 100644 --- a/Oqtane.Client/Oqtane.Client.csproj +++ b/Oqtane.Client/Oqtane.Client.csproj @@ -28,11 +28,11 @@ - - - + + + - + diff --git a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs index e34d1563..4904d0d3 100644 --- a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs @@ -8,6 +8,7 @@ namespace Oqtane.Extensions public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string connectionString) { optionsBuilder.UseSqlServer(connectionString); + //optionsBuilder.UseSqlite("Data Source=Oqtane.db"); return optionsBuilder; } diff --git a/Oqtane.Server/Migrations/01000000_InitializeMaster.cs b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs new file mode 100644 index 00000000..0465e058 --- /dev/null +++ b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs @@ -0,0 +1,60 @@ +using System; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Migrations.Extensions; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(MasterDBContext))] + [Migration("Master.01.00.00.00")] + public class InitializeMaster : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create Tenant table + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + tenantEntityBuilder.Create(); + + //Create Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.Create(); + + //Create ModuleDefinitions Table + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + moduleDefinitionsEntityBuilder.Create(); + + //Create Job Table + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + jobEntityBuilder.Create(); + + //Create JobLog Table + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + jobLogEntityBuilder.Create(); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.Drop(); + + //Drop JobLog Table + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + jobLogEntityBuilder.Drop(); + + //Drop Tenant table + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + tenantEntityBuilder.Drop(); + + //Drop ModuleDefinitions Table + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + moduleDefinitionsEntityBuilder.Drop(); + + //Drop Job Table + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + jobEntityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/Migrations/01000000_InitializeTenant.cs b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs new file mode 100644 index 00000000..d977e508 --- /dev/null +++ b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs @@ -0,0 +1,157 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.01.00.00.00")] + public class InitializeTenant : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.Create(); + + //Create Page table + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.Create(); + pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); + + //Create Module table + var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder); + moduleEntityBuilder.Create(); + + //Create PageModule table + var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder); + pageModuleEntityBuilder.Create(); + + //Create User table + var userEntityBuilder = new UserEntityBuilder(migrationBuilder); + userEntityBuilder.Create(); + userEntityBuilder.AddIndex("IX_User", "Username", true); + + //Create Role table + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + roleEntityBuilder.Create(); + + //Create UserRole table + var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder); + userRoleEntityBuilder.Create(); + userRoleEntityBuilder.AddIndex("IX_UserRole", new [] {"RoleId", "UserId"}, true); + + //Create Permission table + var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder); + permissionEntityBuilder.Create(); + permissionEntityBuilder.AddIndex("IX_Permission", new [] {"SiteId", "EntityName", "EntityId", "PermissionName", "RoleId", "UserId"}, true); + + //Create Setting table + var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder); + settingEntityBuilder.Create(); + settingEntityBuilder.AddIndex("IX_Setting", new [] {"EntityName", "EntityId", "SettingName"}, true); + + //Create Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.Create(); + + //Create Log table + var logEntityBuilder = new LogEntityBuilder(migrationBuilder); + logEntityBuilder.Create(); + + //Create Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.Create(); + + //Create Folder table + var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder); + folderEntityBuilder.Create(); + folderEntityBuilder.AddIndex("IX_Folder", new [] {"SiteId", "Path"}, true); + + //Create File table + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + fileEntityBuilder.Create(); + + //Create AspNetUsers table + var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder); + aspNetUsersEntityBuilder.Create(); + aspNetUsersEntityBuilder.AddIndex("EmailIndex", "NormalizedEmail", true); + aspNetUsersEntityBuilder.AddIndex("UserNameIndex", "NormalizedUserName", true); + + //Create AspNetUserClaims table + var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder); + aspNetUserClaimsEntityBuilder.Create(); + aspNetUserClaimsEntityBuilder.AddIndex("IX_AspNetUserClaims_UserId", "UserId", true); + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop AspNetUserClaims table + var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder); + aspNetUserClaimsEntityBuilder.Drop(); + + //Drop AspNetUsers table + var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder); + aspNetUsersEntityBuilder.Drop(); + + //Drop File table + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + fileEntityBuilder.Drop(); + + //Drop Folder table + var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder); + folderEntityBuilder.Drop(); + + //Drop Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.Drop(); + + //Drop Log table + var logEntityBuilder = new LogEntityBuilder(migrationBuilder); + logEntityBuilder.Drop(); + + //Drop Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.Drop(); + + //Drop Setting table + var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder); + settingEntityBuilder.Drop(); + + //Drop Permission table + var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder); + permissionEntityBuilder.Drop(); + + //Drop UserRole table + var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder); + userRoleEntityBuilder.Drop(); + + //Drop Role table + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + roleEntityBuilder.Drop(); + + //Drop User table + var userEntityBuilder = new UserEntityBuilder(migrationBuilder); + userEntityBuilder.Drop(); + + //Drop PageModule table + var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder); + pageModuleEntityBuilder.Drop(); + + //Drop Module table + var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder); + moduleEntityBuilder.Drop(); + + //Drop Page table + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.Drop(); + + //Drop Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs new file mode 100644 index 00000000..7257bbb1 --- /dev/null +++ b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(MasterDBContext))] + [Migration("Master.01.00.01.00")] + public class AddAdditionalIndexesInMaster : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Update Tenant table + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + tenantEntityBuilder.AddIndex("IX_Tenant", "Name"); + + //Update Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.AddIndex("IX_Alias", "Name"); + + //Update ModuleDefinitions Table + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + moduleDefinitionsEntityBuilder.AddIndex("IX_ModuleDefinition", "ModuleDefinitionName"); + + //Update Job Table + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + jobEntityBuilder.AddIndex("IX_Job", "JobType"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Update Tenant table + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + tenantEntityBuilder.DropIndex("IX_Tenant"); + + //Update Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.DropIndex("IX_Alias"); + + //Update ModuleDefinitions Table + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + moduleDefinitionsEntityBuilder.DropIndex("IX_ModuleDefinition"); + + //Update Job Table + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + jobEntityBuilder.DropIndex("IX_Job"); + } + } +} diff --git a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs new file mode 100644 index 00000000..158c8b0f --- /dev/null +++ b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Migrations.Extensions; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.01.00.01.00")] + public class AddAdditionalIndexesInTenant : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create Index on Site + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.AddIndex("IX_Site", new [] {"TenantId", "Name"}, true); + + //Create Index on Role table + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + roleEntityBuilder.AddIndex("IX_Role", new [] {"SiteId", "Name"}, true); + + //Create Index on Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.AddIndex("IX_Profile", new [] {"SiteId", "Name"}, true); + + //Create Index on File table + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + fileEntityBuilder.AddIndex("IX_File", new [] {"FolderId", "Name"}, true); + + //Add Columns to Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.AddStringColumn("FromDisplayName", 50, true); + notificationEntityBuilder.AddStringColumn("FromEmail", 256, true); + notificationEntityBuilder.AddStringColumn("ToDisplayName", 50, true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Index on Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.DropIndex("IX_Site"); + + //Drop Index on Role table + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + roleEntityBuilder.DropIndex("IX_Role"); + + //Drop Index on Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.DropIndex("IX_Profile"); + + //Drop Index on File table + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + fileEntityBuilder.DropIndex("IX_File"); + + //Drop Columns from Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.DropColumn("FromDisplayName"); + notificationEntityBuilder.DropColumn("FromEmail"); + notificationEntityBuilder.DropColumn("ToDisplayName"); + } + + } +} diff --git a/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs new file mode 100644 index 00000000..7d01d0b0 --- /dev/null +++ b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.01.00.01.01")] + public class AddAdditionColumnToNotifications : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Add Column to Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.AddDateTimeColumn("SendOn", true); + + migrationBuilder.Sql( + @" + UPDATE Notification + SET SendOn = CreatedOn + WHERE SendOn IS NULL; + "); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Column from Notification table + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + notificationEntityBuilder.DropColumn("SendOn"); + } + } +} diff --git a/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs new file mode 100644 index 00000000..516aae4d --- /dev/null +++ b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.01.00.02.01")] + public class DropColumnFromPage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Drop Column from Page table + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.DropColumn("EditMode"); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Add Column to Page table + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.AddBooleanColumn("EditMode"); + } + } +} diff --git a/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs new file mode 100644 index 00000000..79555898 --- /dev/null +++ b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.00.00.01")] + public class AddColumnToProfileAndUpdatePage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Add Column to Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.AddStringColumn("Options", 2000, true); + + ///Update new field + migrationBuilder.Sql( + @" + UPDATE Profile + SET Options = '' + "); + + //Alter Column in Page table + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.DropIndex("IX_Page"); + pageEntityBuilder.AlterStringColumn("Path", 256); + pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Column from Profile table + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + profileEntityBuilder.DropColumn("Options"); + + //Alter Column in Page table + if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + { + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + pageEntityBuilder.DropIndex("IX_Page"); + pageEntityBuilder.AlterStringColumn("Path", 50); + pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); + } + } + } +} diff --git a/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs new file mode 100644 index 00000000..d62220ea --- /dev/null +++ b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.00.01.01")] + public class UpdateIconColumnInPage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + ///Update Icon Field in Page + migrationBuilder.Sql( + @" + UPDATE [Page] + SET Icon = IIF(Icon <> '', 'oi oi-' + Icon, ''); + "); + } + } +} diff --git a/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs b/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs new file mode 100644 index 00000000..21514c31 --- /dev/null +++ b/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.00.01.02")] + public class AddLanguageTable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create Language table + var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder); + languageEntityBuilder.Create(); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Language table + var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder); + languageEntityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs new file mode 100644 index 00000000..3b098e3a --- /dev/null +++ b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs @@ -0,0 +1,41 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.00.01.03")] + public class UpdatePageAndAddColumnToSite : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Add Column to Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.AddStringColumn("AdminContainerType", 200, true); + + //Update new column + migrationBuilder.Sql( + @" + UPDATE Site + SET AdminContainerType = '' + "); + + //Delete records from Page + migrationBuilder.Sql( + @" + DELETE FROM [Page] + WHERE Path = 'admin/tenants'; + "); + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Column from Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + siteEntityBuilder.DropColumn("AdminContainerType"); + } + } +} diff --git a/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs b/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs new file mode 100644 index 00000000..bbbeb06c --- /dev/null +++ b/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(MasterDBContext))] + [Migration("Master.02.01.00.00")] + public class AddIndexesForForeignKeyInMaster : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Update JobLog table + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + jobLogEntityBuilder.AddIndex("IX_JobLog_JobId", "JobId"); + + //Update Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.AddIndex("IX_Alias_TenantId", "TenantId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Update JobLog table + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + jobLogEntityBuilder.DropIndex("IX_JobLog_JobId"); + + //Update Alias table + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + aliasEntityBuilder.DropIndex("IX_Alias_TenantId"); + } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs new file mode 100644 index 00000000..fad6bd1a --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class AliasEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Alias"; + private readonly PrimaryKey _primaryKey = new("PK_Alias", x => x.AliasId); + private readonly ForeignKey _tenantForeignKey = new("FK_Alias_Tenant", x => x.TenantId, "Tenant", "TenantId", ReferentialAction.Cascade); + + public AliasEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_tenantForeignKey); + } + + protected override AliasEntityBuilder BuildTable(ColumnsBuilder table) + { + AliasId = table.AddAutoIncrementColumn("AliasId"); + Name = table.AddStringColumn("Name", 200); + TenantId = table.AddIntegerColumn("TenantId"); + SiteId = table.AddIntegerColumn("SiteId"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder AliasId { get; private set; } + + public OperationBuilder Name { get; private set; } + + public OperationBuilder SiteId { get; private set; } + + public OperationBuilder TenantId { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs new file mode 100644 index 00000000..a99c9067 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class AspNetUserClaimsEntityBuilder : BaseEntityBuilder + { + private const string _entityTableName = "AspNetUserClaims"; + private readonly PrimaryKey _primaryKey = new("PK_AspNetUserClaims", x => x.Id); + private readonly ForeignKey _aspNetUsersForeignKey = new("FK_AspNetUserClaims_AspNetUsers_UserId", x => x.UserId, "AspNetUsers", "Id", ReferentialAction.Cascade); + + public AspNetUserClaimsEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_aspNetUsersForeignKey); + } + + protected override AspNetUserClaimsEntityBuilder BuildTable(ColumnsBuilder table) + { + Id = table.AddAutoIncrementColumn("Id"); + UserId = table.AddStringColumn("UserId", 450); + ClaimType = table.AddMaxStringColumn("ClaimType", true); + ClaimValue = table.AddMaxStringColumn("ClaimValue", true); + + return this; + } + + public OperationBuilder Id { get; set; } + + public OperationBuilder UserId { get; set; } + + public OperationBuilder ClaimType { get; set; } + + public OperationBuilder ClaimValue { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs new file mode 100644 index 00000000..e6ac3b45 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs @@ -0,0 +1,73 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class AspNetUsersEntityBuilder : BaseEntityBuilder + { + private const string _entityTableName = "AspNetUsers"; + private readonly PrimaryKey _primaryKey = new("PK_AspNetUsers", x => x.Id); + + public AspNetUsersEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override AspNetUsersEntityBuilder BuildTable(ColumnsBuilder table) + { + Id = table.AddStringColumn("Id", 450); + UserName = table.AddStringColumn("Username", 256, true); + NormalizedUserName = table.AddStringColumn("NormalizedUserName", 256, true); + Email = table.AddStringColumn("Email", 256, true); + NormalizedEmail = table.AddStringColumn("NormalizedEmail", 256, true); + EmailConfirmed = table.AddBooleanColumn("EmailConfirmed"); + PasswordHash = table.AddMaxStringColumn("PasswordHash", true); + SecurityStamp = table.AddMaxStringColumn("SecurityStamp", true); + ConcurrencyStamp = table.AddMaxStringColumn("ConcurrencyStamp", true); + PhoneNumber = table.AddMaxStringColumn("PhoneNumber", true); + PhoneNumberConfirmed = table.AddBooleanColumn("PhoneNumberConfirmed"); + TwoFactorEnabled = table.AddBooleanColumn("TwoFactorEnabled"); + LockoutEnd = table.AddDateTimeOffsetColumn("LockoutEnd", true); + LockoutEnabled = table.AddBooleanColumn("LockoutEnabled"); + AccessFailedCount = table.AddIntegerColumn("AccessFailedCount"); + + return this; + } + + public OperationBuilder Id { get; set; } + + public OperationBuilder UserName { get; set; } + + public OperationBuilder NormalizedUserName { get; set; } + + public OperationBuilder Email { get; set; } + + public OperationBuilder NormalizedEmail { get; set; } + + public OperationBuilder EmailConfirmed { get; set; } + + public OperationBuilder PasswordHash { get; set; } + + public OperationBuilder SecurityStamp { get; set; } + + public OperationBuilder ConcurrencyStamp { get; set; } + + public OperationBuilder PhoneNumber { get; set; } + + public OperationBuilder PhoneNumberConfirmed { get; set; } + + public OperationBuilder TwoFactorEnabled { get; set; } + + public OperationBuilder LockoutEnd { get; set; } + + public OperationBuilder LockoutEnabled { get; set; } + + public OperationBuilder AccessFailedCount { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs new file mode 100644 index 00000000..9f805d6e --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable MemberCanBePrivate.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public abstract class AuditableBaseEntityBuilder : BaseEntityBuilder where TEntityBuilder : BaseEntityBuilder + { + protected AuditableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base (migrationBuilder) + { + } + + protected void AddAuditableColumns(ColumnsBuilder table) + { + CreatedBy = table.AddStringColumn("CreatedBy", 256); + CreatedOn = table.AddDateTimeColumn("CreatedOn"); + ModifiedBy = table.AddStringColumn("ModifiedBy", 256); + ModifiedOn = table.AddDateTimeColumn("ModifiedOn"); + } + + + public OperationBuilder CreatedBy { get; private set; } + + public OperationBuilder CreatedOn { get; private set; } + + public OperationBuilder ModifiedBy { get; private set; } + + public OperationBuilder ModifiedOn { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs new file mode 100644 index 00000000..d58a88a2 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +namespace Oqtane.Migrations.EntityBuilders +{ + public abstract class BaseEntityBuilder where TEntityBuilder : BaseEntityBuilder + { + private readonly MigrationBuilder _migrationBuilder; + + protected BaseEntityBuilder(MigrationBuilder migrationBuilder) + { + _migrationBuilder = migrationBuilder; + ForeignKeys = new List>(); + } + + private void AddKeys(CreateTableBuilder table) + { + table.AddPrimaryKey(PrimaryKey); + foreach (var foreignKey in ForeignKeys) + { + table.AddForeignKey(foreignKey); + } + + } + + protected abstract TEntityBuilder BuildTable(ColumnsBuilder table); + + protected string EntityTableName { get; init; } + + protected PrimaryKey PrimaryKey { get; init; } + + protected List> ForeignKeys { get; } + + public void AddBooleanColumn(string name) + { + _migrationBuilder.AddColumn(name, EntityTableName); + } + + public void AddDateTimeColumn(string name, bool nullable = false) + { + _migrationBuilder.AddColumn(name, EntityTableName, nullable: nullable); + } + + /// + /// Creates a Migration to add an Index to the Entity (table) + /// + /// The name of the Index to create + /// The name of the column to add to the index + /// A flag that determines if the Index should be Unique + public virtual void AddIndex(string indexName, string columnName, bool isUnique = false) + { + _migrationBuilder.CreateIndex( + name: indexName, + table: EntityTableName, + column: columnName, + unique: isUnique); + } + + /// + /// Creates a Migration to add an Index to the Entity (table) + /// + /// The name of the Index to create + /// The names of the columns to add to the index + /// A flag that determines if the Index should be Unique + public virtual void AddIndex(string indexName, string[] columnNames, bool isUnique = false) + { + _migrationBuilder.CreateIndex( + name: indexName, + table: EntityTableName, + columns: columnNames, + unique: isUnique); + } + + public void AddStringColumn(string name, int length, bool nullable = false) + { + _migrationBuilder.AddColumn(name, EntityTableName, maxLength: length, nullable: nullable); + } + + public void AlterStringColumn(string name, int length, bool nullable = false) + { + _migrationBuilder.AlterColumn(name, EntityTableName, maxLength: length, nullable: nullable); + } + + /// + /// Creates a Migration to Create the Entity (table) + /// + public void Create() + { + _migrationBuilder.CreateTable(EntityTableName, BuildTable, null, AddKeys); + } + + /// + /// Creates a Migration to Drop the Entity (table) + /// + public void Drop() + { + _migrationBuilder.DropTable(EntityTableName); + } + + public void DropColumn(string name) + { + _migrationBuilder.DropColumn(name, EntityTableName); + } + + /// + /// Creates a Migration to drop an Index from the Entity (table) + /// + /// The name of the Index to drop + public virtual void DropIndex(string indexName) + { + _migrationBuilder.DropIndex(indexName, EntityTableName); + } + } +} + diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs new file mode 100644 index 00000000..81cdd9e6 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable MemberCanBePrivate.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public abstract class DeletableAuditableBaseEntityBuilder : AuditableBaseEntityBuilder where TEntityBuilder : BaseEntityBuilder + { + protected DeletableAuditableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + } + + protected void AddDeletableColumns(ColumnsBuilder table) + { + DeletedBy = table.AddStringColumn("DeletedBy", 256, true); + DeletedOn = table.AddDateTimeColumn("DeletedOn", true); + IsDeleted = table.AddBooleanColumn("IsDeleted"); + } + + public OperationBuilder DeletedBy { get; private set; } + + public OperationBuilder DeletedOn { get; private set; } + + public OperationBuilder IsDeleted { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs new file mode 100644 index 00000000..c9bba190 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable MemberCanBePrivate.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public abstract class DeletableBaseEntityBuilder : BaseEntityBuilder where TEntityBuilder : BaseEntityBuilder + { + protected DeletableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + } + + protected void AddDeletableColumns(ColumnsBuilder table) + { + DeletedBy = table.AddStringColumn("DeletedBy", 256, true); + DeletedOn = table.AddDateTimeColumn("DeletedOn", true); + IsDeleted = table.AddBooleanColumn("IsDeleted"); + } + + public OperationBuilder DeletedBy { get; private set; } + + public OperationBuilder DeletedOn { get; private set; } + + public OperationBuilder IsDeleted { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs new file mode 100644 index 00000000..695935a1 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class FileEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "File"; + private readonly PrimaryKey _primaryKey = new("PK_File", x => x.FileId); + private readonly ForeignKey _folderForeignKey = new("FK_File_Folder", x => x.FolderId, "Folder", "FolderId", ReferentialAction.Cascade); + + public FileEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_folderForeignKey); + } + + protected override FileEntityBuilder BuildTable(ColumnsBuilder table) + { + FileId = table.AddAutoIncrementColumn("FileId"); + FolderId = table.AddIntegerColumn("FolderId"); + Name = table.AddStringColumn("Name", 50); + Extension = table.AddStringColumn("Extension", 50); + Size = table.AddIntegerColumn("Size"); + ImageHeight = table.AddIntegerColumn("ImageHeight"); + ImageWidth = table.AddIntegerColumn("ImageWidth"); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder FileId { get; set; } + + public OperationBuilder FolderId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder Extension { get; set; } + + public OperationBuilder Size { get; set; } + + public OperationBuilder ImageHeight { get; set; } + + public OperationBuilder ImageWidth { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs new file mode 100644 index 00000000..d7d5f63d --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class FolderEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "Folder"; + private readonly PrimaryKey _primaryKey = new("PK_Folder", x => x.FolderId); + private readonly ForeignKey _siteForeignKey = new("FK_Folder_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public FolderEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override FolderEntityBuilder BuildTable(ColumnsBuilder table) + { + FolderId = table.AddAutoIncrementColumn("FolderId"); + SiteId = table.AddIntegerColumn("SiteId"); + ParentId = table.AddIntegerColumn("ParentId", true); + Name = table.AddStringColumn("Name", 50); + Path = table.AddStringColumn("Path", 50); + Order = table.AddIntegerColumn("Order"); + IsSystem = table.AddBooleanColumn("IsSystem"); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder FolderId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder ParentId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder Path { get; set; } + + public OperationBuilder Order { get; set; } + + public OperationBuilder IsSystem { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs new file mode 100644 index 00000000..1cdda817 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs @@ -0,0 +1,66 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class JobEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Job"; + private readonly PrimaryKey _primaryKey = new("PK_Job", x => x.JobId); + + public JobEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override JobEntityBuilder BuildTable(ColumnsBuilder table) + { + JobId = table.AddAutoIncrementColumn("JobId"); + Name = table.AddStringColumn("Name", 200); + JobType = table.AddStringColumn("JobType", 200); + Frequency = table.AddStringColumn("Frequency", 1); + Interval = table.AddIntegerColumn("Interval"); + StartDate = table.AddDateTimeColumn("StartDate", true); + EndDate = table.AddDateTimeColumn("EndDate", true); + IsEnabled = table.AddBooleanColumn("IsEnabled"); + IsStarted = table.AddBooleanColumn("IsStarted"); + IsExecuting = table.AddBooleanColumn("IsExecuting"); + NextExecution = table.AddDateTimeColumn("NextExecution", true); + RetentionHistory = table.AddIntegerColumn("RetentionHistory"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder JobId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder JobType { get; set; } + + public OperationBuilder Frequency { get; set; } + + public OperationBuilder Interval { get; set; } + + public OperationBuilder StartDate { get; set; } + + public OperationBuilder EndDate { get; set; } + + public OperationBuilder IsEnabled { get; set; } + + public OperationBuilder IsStarted { get; set; } + + public OperationBuilder IsExecuting { get; set; } + + public OperationBuilder NextExecution { get; set; } + + public OperationBuilder RetentionHistory { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs new file mode 100644 index 00000000..e26c1f44 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class JobLogEntityBuilder : BaseEntityBuilder + { + private const string _entityTableName = "JobLog"; + private readonly PrimaryKey _primaryKey = new("PK_JobLog", x => x.JobLogId); + private readonly ForeignKey _jobLogForeignKey = new("FK_JobLog_Job", x => x.JobId, "Job", "JobId", ReferentialAction.Cascade); + + public JobLogEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_jobLogForeignKey); + } + + protected override JobLogEntityBuilder BuildTable(ColumnsBuilder table) + { + JobLogId = table.AddAutoIncrementColumn("JobLogId"); + JobId = table.AddIntegerColumn("JobId"); + StartDate = table.AddDateTimeColumn("StartDate"); + FinishDate = table.AddDateTimeColumn("FinishDate", true); + Succeeded = table.AddBooleanColumn("Succeeded", true); + Notes = table.AddMaxStringColumn("Notes", true); + + return this; + } + + public OperationBuilder JobLogId { get; private set; } + + public OperationBuilder JobId { get; private set; } + + public OperationBuilder StartDate { get; private set; } + + public OperationBuilder FinishDate { get; private set; } + + public OperationBuilder Succeeded { get; private set; } + + public OperationBuilder Notes { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs new file mode 100644 index 00000000..b32e07ec --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class LanguageEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Language"; + private readonly PrimaryKey _primaryKey = new("PK_Language", x => x.LanguageId); + private readonly ForeignKey _siteForeignKey = new("FK_Language_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public LanguageEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override LanguageEntityBuilder BuildTable(ColumnsBuilder table) + { + LanguageId = table.AddAutoIncrementColumn("LanguageId"); + SiteId = table.AddIntegerColumn("SiteId"); + Name = table.AddStringColumn("Name", 100); + Code = table.AddStringColumn("Code", 10); + IsDefault = table.AddBooleanColumn("IsDefault"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder LanguageId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder Code { get; set; } + + public OperationBuilder IsDefault { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs new file mode 100644 index 00000000..933e1256 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs @@ -0,0 +1,78 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class LogEntityBuilder : BaseEntityBuilder + { + private const string _entityTableName = "Log"; + private readonly PrimaryKey _primaryKey = new("PK_Log", x => x.LogId); + private readonly ForeignKey _siteForeignKey = new("FK_Log_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public LogEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override LogEntityBuilder BuildTable(ColumnsBuilder table) + { + LogId = table.AddAutoIncrementColumn("LogId"); + SiteId = table.AddIntegerColumn("SiteId", true); + LogDate = table.AddDateTimeColumn("LogDate"); + PageId = table.AddIntegerColumn("PageId", true); + ModuleId = table.AddIntegerColumn("ModuleId", true); + UserId = table.AddIntegerColumn("UserId", true); + Url = table.AddStringColumn("Url", 2048); + Server = table.AddStringColumn("Server", 200); + Category = table.AddStringColumn("Category", 200); + Feature = table.AddStringColumn("Feature", 200); + Function = table.AddStringColumn("Function", 20); + Level = table.AddStringColumn("Level", 20); + Message = table.AddMaxStringColumn("Message"); + MessageTemplate = table.AddMaxStringColumn("MessageTemplate"); + Exception = table.AddMaxStringColumn("Exception", true); + Properties = table.AddMaxStringColumn("Properties", true); + + return this; + } + + public OperationBuilder LogId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder LogDate { get; set; } + + public OperationBuilder PageId { get; set; } + + public OperationBuilder ModuleId { get; set; } + + public OperationBuilder UserId { get; set; } + + public OperationBuilder Url { get; set; } + + public OperationBuilder Server { get; set; } + + public OperationBuilder Category { get; set; } + + public OperationBuilder Feature { get; set; } + + public OperationBuilder Function { get; set; } + + public OperationBuilder Level { get; set; } + + public OperationBuilder Message { get; set; } + + public OperationBuilder MessageTemplate { get; set; } + + public OperationBuilder Exception { get; set; } + + public OperationBuilder Properties { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs new file mode 100644 index 00000000..5e7d5b50 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class ModuleDefinitionsEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "ModuleDefinition"; + private readonly PrimaryKey _primaryKey = new("PK_ModuleDefinition", x => x.ModuleDefinitionId); + + public ModuleDefinitionsEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override ModuleDefinitionsEntityBuilder BuildTable(ColumnsBuilder table) + { + ModuleDefinitionId = table.AddAutoIncrementColumn("ModuleDefinitionId"); + ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); + Name = table.AddStringColumn("Name", 200, true); + Description = table.AddStringColumn("Description", 2000, true); + Categories = table.AddStringColumn("Categories", 200, true); + Version = table.AddStringColumn("Version", 50, true); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder ModuleDefinitionId { get; private set; } + + public OperationBuilder ModuleDefinitionName { get; private set; } + + public OperationBuilder Name { get; private set; } + + public OperationBuilder Description { get; private set; } + + public OperationBuilder Categories { get; private set; } + + public OperationBuilder Version { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs new file mode 100644 index 00000000..96f8b270 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class ModuleEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Module"; + private readonly PrimaryKey _primaryKey = new("PK_Module", x => x.ModuleId); + private readonly ForeignKey _siteForeignKey = new("FK_Module_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public ModuleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override ModuleEntityBuilder BuildTable(ColumnsBuilder table) + { + ModuleId = table.AddAutoIncrementColumn("ModuleId"); + SiteId = table.AddIntegerColumn("SiteId"); + ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); + AllPages = table.AddBooleanColumn("AllPages"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder ModuleId { get; private set; } + + public OperationBuilder SiteId { get; private set; } + + public OperationBuilder ModuleDefinitionName { get; private set; } + + public OperationBuilder AllPages { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs new file mode 100644 index 00000000..2ee3779b --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs @@ -0,0 +1,65 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class NotificationEntityBuilder : DeletableBaseEntityBuilder + { + private const string _entityTableName = "Notification"; + private readonly PrimaryKey _primaryKey = new("PK_Notification", x => x.NotificationId); + private readonly ForeignKey _siteForeignKey = new("FK_Notification_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public NotificationEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override NotificationEntityBuilder BuildTable(ColumnsBuilder table) + { + NotificationId = table.AddAutoIncrementColumn("NotificationId"); + SiteId = table.AddIntegerColumn("SiteId"); + FromUserId = table.AddIntegerColumn("FromUserId", true); + ToUserId = table.AddIntegerColumn("ToUserId", true); + ToEmail = table.AddStringColumn("ToEmail", 256); + ParentId = table.AddIntegerColumn("ParentId", true); + Subject = table.AddStringColumn("Subject", 256); + Body = table.AddMaxStringColumn("Body"); + CreatedOn = table.AddDateTimeColumn("CreatedOn"); + IsDelivered = table.AddBooleanColumn("IsDelivered"); + DeliveredOn = table.AddDateTimeColumn("DeliveredOn", true); + + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder NotificationId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder FromUserId { get; set; } + + public OperationBuilder ToUserId { get; set; } + + public OperationBuilder ToEmail { get; set; } + + public OperationBuilder ParentId { get; set; } + + public OperationBuilder Subject { get; set; } + + public OperationBuilder Body { get; set; } + + public OperationBuilder CreatedOn { get; set; } + + public OperationBuilder IsDelivered { get; set; } + + public OperationBuilder DeliveredOn { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs new file mode 100644 index 00000000..49c75ba0 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs @@ -0,0 +1,80 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class PageEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "Page"; + private readonly PrimaryKey _primaryKey = new("PK_Page", x => x.PageId); + private readonly ForeignKey _siteForeignKey = new("FK_Page_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public PageEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override PageEntityBuilder BuildTable(ColumnsBuilder table) + { + PageId = table.AddAutoIncrementColumn("PageId"); + SiteId = table.AddIntegerColumn("SiteId"); + Path = table.AddStringColumn("Path", 50); + Name = table.AddStringColumn("Name", 50); + Title = table.AddStringColumn("Title", 200, true); + ThemeType = table.AddStringColumn("ThemeType", 200, true); + Icon = table.AddStringColumn("Icon", 50); + ParentId = table.AddIntegerColumn("ParentId", true); + Order = table.AddIntegerColumn("Order"); + IsNavigation = table.AddBooleanColumn("IsNavigation"); + Url = table.AddStringColumn("Url", 500, true); + LayoutType = table.AddStringColumn("LayoutType", 200); + EditMode = table.AddBooleanColumn("EditMode"); + UserId = table.AddIntegerColumn("UserId", true); + IsPersonalizable = table.AddBooleanColumn("IsPersonalizable"); + DefaultContainerType = table.AddStringColumn("DefaultContainerType", 200, true); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder PageId { get; private set; } + + public OperationBuilder SiteId { get; private set; } + + public OperationBuilder Path { get; private set; } + public OperationBuilder Name { get; private set; } + + public OperationBuilder Title { get; private set; } + + public OperationBuilder ThemeType { get; private set; } + + public OperationBuilder Icon { get; private set; } + + public OperationBuilder ParentId { get; private set; } + + public OperationBuilder Order { get; private set; } + + public OperationBuilder IsNavigation { get; private set; } + + public OperationBuilder Url { get; private set; } + + public OperationBuilder LayoutType { get; private set; } + + public OperationBuilder EditMode { get; private set; } + + public OperationBuilder UserId { get; private set; } + + public OperationBuilder IsPersonalizable { get; private set; } + + public OperationBuilder DefaultContainerType { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs new file mode 100644 index 00000000..ff9d0594 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs @@ -0,0 +1,56 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class PageModuleEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "PageModule"; + private readonly PrimaryKey _primaryKey = new("PK_PageModule", x => x.PageModuleId); + private readonly ForeignKey _moduleForeignKey = new("FK_PageModule_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.NoAction); + private readonly ForeignKey _pageForeignKey = new("FK_PageModule_Page", x => x.PageId, "Page", "PageId", ReferentialAction.Cascade); + + public PageModuleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_moduleForeignKey); + ForeignKeys.Add(_pageForeignKey); + } + + protected override PageModuleEntityBuilder BuildTable(ColumnsBuilder table) + { + PageModuleId = table.AddAutoIncrementColumn("PageModuleId"); + PageId = table.AddIntegerColumn("PageId"); + ModuleId = table.AddIntegerColumn("ModuleId"); + Title = table.AddStringColumn("Title", 200); + Pane = table.AddStringColumn("Pane", 50); + Order = table.AddIntegerColumn("Order"); + ContainerType = table.AddStringColumn("ContainerType", 200); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder PageModuleId { get; private set; } + + public OperationBuilder PageId { get; private set; } + + public OperationBuilder ModuleId { get; private set; } + + public OperationBuilder Title { get; private set; } + + public OperationBuilder Pane { get; private set; } + + public OperationBuilder Order { get; private set; } + + public OperationBuilder ContainerType { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs new file mode 100644 index 00000000..af383609 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs @@ -0,0 +1,60 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class PermissionEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Permission"; + private readonly PrimaryKey _primaryKey = new("PK_Permission", x => x.PermissionId); + private readonly ForeignKey _siteForeignKey = new("FK_Permission_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + private readonly ForeignKey _userForeignKey = new("FK_Permission_User", x => x.UserId, "User", "UserId", ReferentialAction.NoAction); + private readonly ForeignKey _roleForeignKey = new("FK_Permission_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction); + + public PermissionEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + ForeignKeys.Add(_userForeignKey); + ForeignKeys.Add(_roleForeignKey); + } + + protected override PermissionEntityBuilder BuildTable(ColumnsBuilder table) + { + PermissionId = table.AddAutoIncrementColumn("PermissionId"); + SiteId = table.AddIntegerColumn("SiteId"); + EntityName = table.AddStringColumn("EntityName", 50); + EntityId = table.AddIntegerColumn("EntityId"); + PermissionName = table.AddStringColumn("PermissionName", 50); + RoleId = table.AddIntegerColumn("RoleId", true); + UserId = table.AddIntegerColumn("UserId", true); + IsAuthorized = table.AddBooleanColumn("IsAuthorized"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder PermissionId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder EntityName { get; set; } + + public OperationBuilder EntityId { get; set; } + + public OperationBuilder PermissionName { get; set; } + + public OperationBuilder RoleId { get; set; } + + public OperationBuilder UserId { get; set; } + + public OperationBuilder IsAuthorized { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs new file mode 100644 index 00000000..b5e27469 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class ProfileEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Profile"; + private readonly PrimaryKey _primaryKey = new("PK_Profile", x => x.ProfileId); + private readonly ForeignKey _siteForeignKey = new("FK_Profile_Sites", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public ProfileEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override ProfileEntityBuilder BuildTable(ColumnsBuilder table) + { + ProfileId = table.AddAutoIncrementColumn("ProfileId"); + SiteId = table.AddIntegerColumn("SiteId", true); + Name = table.AddStringColumn("Name", 50); + Title = table.AddStringColumn("Title", 50); + Description = table.AddStringColumn("Description", 256, true); + Category = table.AddStringColumn("Category", 50); + ViewOrder = table.AddIntegerColumn("ViewOrder"); + MaxLength = table.AddIntegerColumn("MaxLength"); + DefaultValue = table.AddStringColumn("DefaultValue", 2000, true); + IsRequired = table.AddBooleanColumn("IsRequired"); + IsPrivate = table.AddBooleanColumn("IsPrivate"); + + AddAuditableColumns(table); + + return this; } + + public OperationBuilder ProfileId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder Title { get; set; } + + public OperationBuilder Description { get; set; } + + public OperationBuilder Category { get; set; } + + public OperationBuilder ViewOrder { get; set; } + + public OperationBuilder MaxLength { get; set; } + + public OperationBuilder DefaultValue { get; set; } + + public OperationBuilder IsRequired { get; set; } + + public OperationBuilder IsPrivate { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs new file mode 100644 index 00000000..67deafa1 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class RoleEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Role"; + private readonly PrimaryKey _primaryKey = new("PK_Role", x => x.RoleId); + private readonly ForeignKey _siteForeignKey = new("FK_Role_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); + + public RoleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_siteForeignKey); + } + + protected override RoleEntityBuilder BuildTable(ColumnsBuilder table) + { + RoleId = table.AddAutoIncrementColumn("RoleId"); + SiteId = table.AddIntegerColumn("SiteId", true); + Name = table.AddStringColumn("Name", 256); + Description = table.AddStringColumn("Description", 256); + IsAutoAssigned = table.AddBooleanColumn("IsAutoAssigned"); + IsSystem = table.AddBooleanColumn("IsSystem"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder RoleId { get; set; } + + public OperationBuilder SiteId { get; set; } + + public OperationBuilder Name { get; set; } + + public OperationBuilder Description { get; set; } + + public OperationBuilder IsAutoAssigned { get; set; } + + public OperationBuilder IsSystem { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs new file mode 100644 index 00000000..7f4bb07d --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class SettingEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Setting"; + private readonly PrimaryKey _primaryKey = new("PK_Setting", x => x.SettingId); + + public SettingEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override SettingEntityBuilder BuildTable(ColumnsBuilder table) + { + SettingId = table.AddAutoIncrementColumn("SettingId"); + EntityName = table.AddStringColumn("EntityName", 50); + EntityId = table.AddIntegerColumn("EntityId"); + SettingName = table.AddStringColumn("SettingName", 50); + SettingValue = table.AddMaxStringColumn("SettingValue"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder SettingId { get; set; } + + public OperationBuilder EntityName { get; set; } + + public OperationBuilder EntityId { get; set; } + + public OperationBuilder SettingName { get; set; } + + public OperationBuilder SettingValue { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs new file mode 100644 index 00000000..172ff1df --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class SiteEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "Site"; + private readonly PrimaryKey _primaryKey = new("PK_Site", x => x.SiteId); + + public SiteEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override SiteEntityBuilder BuildTable(ColumnsBuilder table) + { + SiteId = table.AddAutoIncrementColumn("SiteId"); + TenantId = table.AddIntegerColumn("TenantId"); + Name = table.AddStringColumn("Name", 200); + LogoFileId = table.AddIntegerColumn("LogoFileId", true); + FaviconFileId = table.AddIntegerColumn("FaviconFileId", true); + DefaultThemeType = table.AddStringColumn("DefaultThemeType", 200); + DefaultLayoutType = table.AddStringColumn("DefaultLayoutType", 200); + DefaultContainerType = table.AddStringColumn("DefaultContainerType", 200); + PwaIsEnabled = table.AddBooleanColumn("PwaIsEnabled"); + PwaAppIconFileId = table.AddIntegerColumn("PwaAppIconFileId", true); + PwaSplashIconFileId = table.AddIntegerColumn("PwaSplashIconFileId", true); + AllowRegistration = table.AddBooleanColumn("AllowRegistration"); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder SiteId { get; private set; } + + public OperationBuilder TenantId { get; private set; } + + public OperationBuilder Name { get; private set; } + + public OperationBuilder LogoFileId { get; private set; } + + public OperationBuilder FaviconFileId { get; private set; } + + public OperationBuilder DefaultThemeType { get; private set; } + + public OperationBuilder DefaultLayoutType { get; private set; } + + public OperationBuilder DefaultContainerType { get; private set; } + + public OperationBuilder PwaIsEnabled { get; private set; } + + public OperationBuilder PwaAppIconFileId { get; private set; } + + public OperationBuilder PwaSplashIconFileId { get; private set; } + + public OperationBuilder AllowRegistration { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs new file mode 100644 index 00000000..1cf04a30 --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class TenantEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "Tenant"; + private readonly PrimaryKey _primaryKey = new("PK_Tenant", x => x.TenantId); + + public TenantEntityBuilder(MigrationBuilder migrationBuilder): base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override TenantEntityBuilder BuildTable(ColumnsBuilder table) + { + TenantId = table.AddAutoIncrementColumn("TenantId"); + Name = table.AddStringColumn("Name", 100); + DBConnectionString = table.AddStringColumn("DBConnectionString", 1024); + Version = table.AddStringColumn("Version", 50, true); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder TenantId { get; private set; } + + public OperationBuilder Name { get;private set; } + + public OperationBuilder DBConnectionString { get; private set;} + + public OperationBuilder Version { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs new file mode 100644 index 00000000..cfcf6acb --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class UserEntityBuilder : DeletableAuditableBaseEntityBuilder + { + private const string _entityTableName = "User"; + private readonly PrimaryKey _primaryKey = new("PK_User", x => x.UserId); + + public UserEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override UserEntityBuilder BuildTable(ColumnsBuilder table) + { + UserId = table.AddAutoIncrementColumn("UserId"); + Username = table.AddStringColumn("Username", 256); + DisplayName = table.AddStringColumn("DisplayName", 50); + Email = table.AddStringColumn("Email", 256); + PhotoFileId = table.AddIntegerColumn("PhotoFileId", true); + LastLoginOn = table.AddDateTimeColumn("LastLoginOn", true); + LastIPAddress = table.AddStringColumn("LastIpAddress", 50); + + AddAuditableColumns(table); + AddDeletableColumns(table); + + return this; + } + + public OperationBuilder UserId { get; private set; } + + public OperationBuilder Username { get; private set; } + + public OperationBuilder DisplayName { get; private set; } + + public OperationBuilder Email { get; private set; } + + public OperationBuilder PhotoFileId { get; private set; } + + public OperationBuilder LastLoginOn { get; private set; } + + public OperationBuilder LastIPAddress { get; private set; } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs new file mode 100644 index 00000000..46ee993e --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Migrations.EntityBuilders +{ + public class UserRoleEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "UserRole"; + private readonly PrimaryKey _primaryKey = new("PK_UserRole", x => x.UserRoleId); + private readonly ForeignKey _userForeignKey = new("FK_UserRole_User", x => x.UserId, "User", "UserId", ReferentialAction.Cascade); + private readonly ForeignKey _roleForeignKey = new("FK_UserRole_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction); + + public UserRoleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_userForeignKey); + ForeignKeys.Add(_roleForeignKey); + } + + protected override UserRoleEntityBuilder BuildTable(ColumnsBuilder table) + { + UserRoleId = table.AddAutoIncrementColumn("UserRoleId"); + UserId = table.AddIntegerColumn("UserId"); + RoleId = table.AddIntegerColumn("RoleId"); + EffectiveDate = table.AddDateTimeColumn("EffectiveDate", true); + ExpiryDate = table.AddDateTimeColumn("ExpiryDate", true); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder UserRoleId { get; set; } + + public OperationBuilder UserId { get; set; } + + public OperationBuilder RoleId { get; set; } + + public OperationBuilder EffectiveDate { get; set; } + + public OperationBuilder ExpiryDate { get; set; } + } +} diff --git a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs new file mode 100644 index 00000000..5c9a3a4e --- /dev/null +++ b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs @@ -0,0 +1,47 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; + +namespace Oqtane.Migrations.Extensions +{ + public static class ColumnsBuilderExtensions + { + public static OperationBuilder AddAutoIncrementColumn(this ColumnsBuilder table, string name) + { + return table.Column(name: name, nullable: false) + .Annotation("SqlServer:Identity", "1, 1") + .Annotation("Sqlite:Autoincrement", true); + } + + public static OperationBuilder AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: name, nullable: nullable); + } + + public static OperationBuilder AddDateTimeColumn(this ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: name, nullable: nullable); + } + + public static OperationBuilder AddDateTimeOffsetColumn(this ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: name, nullable: nullable); + } + + public static OperationBuilder AddIntegerColumn(this ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: name, nullable: nullable); + } + + public static OperationBuilder AddMaxStringColumn(this ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: name, nullable: nullable); + } + + public static OperationBuilder AddStringColumn(this ColumnsBuilder table, string name, int length, bool nullable = false) + { + return table.Column(name: name, maxLength: length, nullable: nullable); + } + + } +} diff --git a/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs new file mode 100644 index 00000000..76a1b454 --- /dev/null +++ b/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.EntityBuilders; + +namespace Oqtane.Migrations.Extensions +{ + public static class CreateTableBuilderExtensions + { + public static void AddForeignKey(this CreateTableBuilder table, ForeignKey foreignKey) where TEntityBuilder : BaseEntityBuilder + { + table.ForeignKey( + name: foreignKey.Name, + column: foreignKey.Column, + principalTable: foreignKey.PrincipalTable, + principalColumn: foreignKey.PrincipalColumn, + onDelete: foreignKey.OnDeleteAction); + } + + public static void AddPrimaryKey(this CreateTableBuilder table, PrimaryKey primaryKey) where TEntityBuilder : BaseEntityBuilder + { + table.PrimaryKey(primaryKey.Name, primaryKey.Columns); + } + } +} diff --git a/Oqtane.Server/Migrations/Framework/ForeignKey.cs b/Oqtane.Server/Migrations/Framework/ForeignKey.cs new file mode 100644 index 00000000..d2a2260d --- /dev/null +++ b/Oqtane.Server/Migrations/Framework/ForeignKey.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations.EntityBuilders; + +namespace Oqtane.Migrations +{ + public readonly struct ForeignKey where TEntityBuilder : BaseEntityBuilder + { + public ForeignKey(string name, Expression> column, string principalTable, string principalColumn, ReferentialAction onDeleteAction) + { + Name = name; + Column = column; + PrincipalTable = principalTable; + PrincipalColumn = principalColumn; + OnDeleteAction = onDeleteAction; + } + + public string Name { get; } + + public Expression> Column { get;} + + public ReferentialAction OnDeleteAction { get; } + + public string PrincipalTable { get; } + + public string PrincipalColumn { get; } + + + } +} diff --git a/Oqtane.Server/Migrations/Framework/PrimaryKey.cs b/Oqtane.Server/Migrations/Framework/PrimaryKey.cs new file mode 100644 index 00000000..e6280c5f --- /dev/null +++ b/Oqtane.Server/Migrations/Framework/PrimaryKey.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq.Expressions; +using Oqtane.Migrations.EntityBuilders; + +namespace Oqtane.Migrations +{ + public readonly struct PrimaryKey where TEntityBuilder : BaseEntityBuilder + { + public PrimaryKey(string name, Expression> columns) + { + Name = name; + Columns = columns; + } + + public string Name { get; } + + public Expression> Columns { get;} + + + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index 70cd2065..e9ac5d12 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -2,6 +2,7 @@ using Oqtane.Modules.HtmlText.Models; using Oqtane.Repository; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; namespace Oqtane.Modules.HtmlText.Repository { @@ -9,7 +10,7 @@ namespace Oqtane.Modules.HtmlText.Repository { public virtual DbSet HtmlText { get; set; } - public HtmlTextContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) + public HtmlTextContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) { // ContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 4a6802f5..db1b8192 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -41,14 +41,19 @@ - - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - + @@ -65,4 +70,5 @@ - + + diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index 9d488f45..d6535f0c 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Oqtane.Extensions; using Oqtane.Models; @@ -13,11 +14,13 @@ namespace Oqtane.Repository { private ITenantResolver _tenantResolver; private IHttpContextAccessor _accessor; + private readonly IConfiguration _configuration; - public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor accessor) + public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) { _tenantResolver = tenantResolver; _accessor = accessor; + _configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) @@ -29,6 +32,17 @@ namespace Oqtane.Repository .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); optionsBuilder.UseOqtaneDatabase(connectionString); } + else + { + if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) + { + var connectionString = _configuration.GetConnectionString("DefaultConnection") + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + + optionsBuilder.UseOqtaneDatabase(connectionString); + } + + } base.OnConfiguring(optionsBuilder); } diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index d6fd06c4..4390739f 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Oqtane.Models; namespace Oqtane.Repository @@ -23,7 +24,7 @@ namespace Oqtane.Repository public virtual DbSet Language { get; set; } - public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) + public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) { // DBContextBase handles multi-tenant database connections } diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 65df5df5..0f973a79 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -20,7 +20,7 @@ - + diff --git a/Oqtane.Test/Oqtane.Test.csproj b/Oqtane.Test/Oqtane.Test.csproj index da295fb4..755b3eed 100644 --- a/Oqtane.Test/Oqtane.Test.csproj +++ b/Oqtane.Test/Oqtane.Test.csproj @@ -18,7 +18,7 @@ - + From 8f1c760e873ddd527f5c84b4086f51d69fcd0a29 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Sun, 21 Mar 2021 14:52:45 -0700 Subject: [PATCH 02/23] Updated the Installation of Oqtane to use Migrations --- Oqtane.Server/Controllers/SqlController.cs | 5 +- Oqtane.Server/Data/Oqtane.db | Bin 0 -> 200704 bytes .../Infrastructure/DatabaseManager.cs | 276 +++++++++--------- .../Infrastructure/Interfaces/IInstallable.cs | 5 +- .../Infrastructure/Interfaces/IMigratable.cs | 10 + .../HtmlText/Manager/HtmlTextManager.cs | 70 +++-- .../Migrations/01000000_InitializeModule.cs | 26 ++ .../EntityBuilders/HtmlTextEntityBuilder.cs | 43 +++ .../HtmlText/Repository/HtmlTextContext.cs | 2 +- .../HtmlText/Scripts/HtmlText.1.0.0.sql | 19 -- .../HtmlText/Scripts/HtmlText.Uninstall.sql | 2 - Oqtane.Server/Oqtane.Server.csproj | 10 +- .../Repository/Context/DBContextBase.cs | 50 ++-- Oqtane.Server/Repository/Context/DbConfig.cs | 20 ++ .../Repository/Context/DbContextUtils.cs | 2 +- .../Repository/Context/InstallationContext.cs | 3 + .../Repository/Context/MasterDBContext.cs | 33 ++- .../Repository/Context/TenantDBContext.cs | 2 +- .../Repository/Interfaces/IDbConfig.cs | 14 + .../Repository/Interfaces/ISqlRepository.cs | 4 +- Oqtane.Server/Repository/SqlRepository.cs | 6 +- Oqtane.Server/Startup.cs | 3 +- Oqtane.Server/appsettings.json | 6 +- .../wwwroot/Modules/Oqtane.Blogs/Module.css | 1 + .../wwwroot/Modules/Oqtane.Blogs/Module.js | 1 + .../wwwroot/Modules/Oqtane.Blogs/assets.json | 1 + Oqtane.Shared/Enums/MigrationType.cs | 8 + 27 files changed, 390 insertions(+), 232 deletions(-) create mode 100644 Oqtane.Server/Data/Oqtane.db create mode 100644 Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs create mode 100644 Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs create mode 100644 Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs delete mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql delete mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql create mode 100644 Oqtane.Server/Repository/Context/DbConfig.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IDbConfig.cs create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json create mode 100644 Oqtane.Shared/Enums/MigrationType.cs diff --git a/Oqtane.Server/Controllers/SqlController.cs b/Oqtane.Server/Controllers/SqlController.cs index 7e7bedcc..d2a13078 100644 --- a/Oqtane.Server/Controllers/SqlController.cs +++ b/Oqtane.Server/Controllers/SqlController.cs @@ -6,11 +6,8 @@ using Oqtane.Shared; using Oqtane.Infrastructure; using Oqtane.Repository; using Oqtane.Enums; -using System.Data.SqlClient; -using System.Data; -using System.Dynamic; -using Newtonsoft.Json; using System; +using Microsoft.Data.SqlClient; namespace Oqtane.Controllers { diff --git a/Oqtane.Server/Data/Oqtane.db b/Oqtane.Server/Data/Oqtane.db new file mode 100644 index 0000000000000000000000000000000000000000..d02cc5a4e260a659fdcdeb39c8340186f72a2eab GIT binary patch literal 200704 zcmeI5?{6E)dB?eyCCa*!d5NOz=^V%Fb(|A(w$JYMa4#C*N|Q_9o~0#^q^@$19J?k* z@+Q=-Zg**0`GG_}+sWOfKVAe#Ul%Bl7wwzAE6^7$`ldk9H!aYApe+#eUEUM{`l6lL z+2Q`Cl*FzL<||kfcb;dSnf*LJW@ahd-S;*upC~(yyJz~!8>N>@Cr*@pUr|b>(kc3V zjed)-EA-7taY27dvG+x9PnE9R_}M&_&Q*TFbS_r@r}E#GU!3yGEAu~@e|P@m$se42 zd+z6RKQ8^W^2?Z!M{cDoudYg;-tf)aBhsaFWZy5G+gWBHI zjNYZtT#wkM?dKU38iu(?hwo|IbewQ3A=+?uou)M+iSBeRLf$m*S_8+PrqUog=6K}y z?vOpwJJ>H8DOB4q51g@ov|in@ebcguJ4Lm9&(uB5X5e#hid&#swf%klh`XR#-Tjg2 z-8o9JHX1qiI%L=KeAo0X$Id!Zj9hn#>6790g97-WyhTmqI%m@vT07Ph145zDLW7J* zVg@nShO(${Os0FGG<$Q)OVzKPUXWjxrSDnxklfd|`?Zl}dVLXx!Br(p0NrS4+lrb| zQk9mWsDUa?3{~`1t6R$p@@s3-SlE8oxlLoVPk-n`{{D2vbX zt?O#KEy&<%V`)J?D@y}0g8*Of@L!&R14)uMK}3A<5yyqq_0vJegJiMwgU&ty`}(G@6DFKPZ>wl@;mZ3j#mww3q>(pq_^)z3v1< zAIW>lqCyQ!soG7Kd^jfdpr|V9wolx<<|tcw3Vj(dS2cTB;KXAr6}lIMNy5*m1(RC2 zPX=S(vUiIoXpsAUsK(X@Ufg4o?9ifYvzqY^T}2$1l1T3b#H~KNC4>gpN9~2OeEG8U znCEx8D5bB<$VpiP*R(=BEbn2ClWwSNV(=>$IBeIH-!FTEz+3f$>^IHG9! z9xt#Ybvd7KaZ0#u(?h}~+OztA%<)zIVqlYx&tFd_EQGtZD6c0|&6KnB62mo*k;7Bs zq;Z{|5o|JG+1d5opdjaNqo31MJlvMb@>_374_X1|eqU>DTD$yA;e`uBZsUoh7jktX zr%Y_Jj7jiGJEg!-ESE(Bwq3gS9r!7*VII>eqn}uizwwq-3bvSGpqXRe39kFOccicx7?!n#>=oT)Fx?SFTRQa#UzgGUX@)wmq zuH38qA#K1H2!H?xfB*=900@8p2!H?xfB*=9K$gJg=dMZF=LC!KW_~PZj|j@yW-7e4 zklTE9KHJRB?myg7OjaAI}t+9{#Uo0$>z`9J-oe|&)e2!H?xfB*=900@8p z2!H?xfB*>0FaezZXV|&8H4p#+5C8!X009sH0T2KI5C8!X2npc)k5B*s5C8!X009sH z0T2KI5C8!X0D;*jfb;+C`xti!0w4eaAOHd&00JNY0w4eaAOHe5|04!K00ck)1V8`; zKmY_l00ck)1VCW+3E=!c`##1Uf&d7B00@8p2!H?xfB*=900@8p`~Uy&@BbqXKmY_l z00ck)1V8`;KmY_l00cl_wh7?;KimGr-GKlIfB*=900@8p2!H?xfB*=903(3&KjHuc zKmY_l00ck)1V8`;KmY_l00d^A0M7rj?_=B{2!H?xfB*=900@8p2!H?xfB*>K{Erv_ z0T2KI5C8!X009sH0T2KI5CDPMCxG++?E4sZ2m&Ag0w4eaAOHd&00JNY0w4ea`2YV9 z10VnbAOHd&00JNY0w4eaAOHd&F#7~>{-1px;|@Up1V8`;KmY_l00ck)1V8`;Kw!D@ z%TlHE)6(gGsr=RQH5!tbo)3in;(VgC}kT=b{*1)l+sWixrIUf1FJ7kaa4)%*i3e`5u z183|Xtygz!-?VJvPEl>&Gj&h1nR9boCT@Xh)%N%GBkqD~b@xZ6cjqX@+Gyn5>yTZ` z^Ig-o96K8Z9xWC8%qoF zSy>v083g!(mlrZ)g=iC$xs`WLEy(BAq+MZ!v*)i%89Th4&s4l$SGlDJ-(4)rYirV@ zZct!3bpCoOG!zzD-WZixew`>f*+Lr>LDBQbGDsEk?1@~YQ*`|XO~-;+Icj5}M zbm)!;144$0DiaeMj!!&cH)@ZT3`K3;WFZ_zvZ^#&9ZkPs1Vw!kqe@3>Y8}m}Yh8uK zZ7h6QwluU2jV@dDTDM+nXfzEUeo!vUD=X5+7X*IVX)yynK|K#qY;6T>5>n}#2yq?Mcwv^d)FLgOHZLMBj&1R4-1@ljHN>Nf-p(=IkjL?EBDD@>|6G3 z@dOQW-w)N;`oN2OY?2*Xlxk;XX~}VdGTrAG5t{BYC1T^En4cQN8@Sd!U*$7itkY_;>$p~4?yK(;*9$fW z*>2BlSHN6q%$H?ZmL7j6s2R};vXFFMxO|9had3GYH--Ivlj^}&nY_V7Qm~EjH2Jej znsA1x${#=p_ebg4Ke^j#qWnioZA>9=5on*J`=!^UTY)>h4@VSD-{S?Aq%P+ZE=~#8 zZF)$!M0-{rkU74pUkq&W@%ih?goSX|7UlJ1s+n?@UShcBF>*Mbn5jzKxK7UqHW{$& z?D}p{kaM@u&uJ1GA zQeY^S%OU~WF5UYM{1n*GKeWo|Cl=&yyd{-_EoK;K=Gb?F>wfMy{cE|+bM%b8$WGks z^Z&)t9{n!=`TRee_`Bu*T>i5c{)9F>jjxAoxh$VOEB(j|T(jj7x8sb6`1wlG0iro# zE?V-6RGPZbJw`Gx)jX5JEo_d{-OP9N(V27mL-?!X@0^##kR0X#_dy}rJA*p0d z<%;X-M3||k`Q@AGGqip7k{&5!o*aoQuB$>wQ{r)Hr7WL6FMWD52&uNYOZfgIdiVKc zSVe*;u%fm+Kc_=0(mqCTG37j?BDnZ$r)l&opYci57}2|J+C`$4J7f+l+yNisLC`ag zP4y`}Xvq)8$fteok#s;#{FDqyp)8&)P)Ame9Dxm%wjahx(mGdMS0}N(R{m4dqxO*8Q1oJKUw1MCIeie&mm0zj!J)uV*SGxUkV=P{}Dg92-}}Y22N-v3>$WJoS@;o ze&dh{rkr2?rbJJoYR1l;WEcGCQk$u8}aC3EmRsG55H7tkO_sc~^p9y)<=kNG_+-4t9 zRv*6nxge^3#CHh7mYj^LuwNKe>?%?23ZjblIx?!5S}>XXLf)`E`YGYTl=#y2Olwjf zQ<2ralQZrw0FpMFSS*}0#}F{!>^8xCFKO+If(4e`uF?rCg=>E;pt{@>Gh&;gqu z00JNY0w4eaAOHd&00JNY0wC~w5y0R7f4=;I*?<5DfB*=900@8p2!H?xfB*=9z|$ar z^Z(PJ3Y#DR0w4eaAOHd&00JNY0w4eaAn<$9zn)*7yL;k)OK&dkEPb%_H*~b? z1tUJXakeaR= zut=>5nPKh`Rq1KlbdYc$A?jKFs7Tfz-oUl?eao>$@0iiL>62Z@JrJUl;rA_aujLMj zo4rXf_NIA%gV?+Nonn;+*)hi>|9x{bp3E{f2i@zC566~Ea!`sS+26BM69f zHS~T}>1a)@qZxIrs|1ZS>LOvwP#W5XMnkh+>(*-xZF#9W{z6$ke?~g|JsD%7YNDzm{f+qe9KAmT15;T4Tb`aV<&MAeTz zcP2=nN8b+;C^_i4WCBIjMXd8FCc?cSfhK*AOrY4r^HYT@A@)x4sGJ@S)NC0K=kg5ML`j%@VJOyPvUSA7I{Gu^$^mIGh&5} z_S*7@OW#!=pI@UfdtUnSGB3V4Gd!D&pvY>h3QxM_xinLVC)%oVWGH27amvL{Ak?Be z3OMCQTZk@NWuoFDVCKqnuQvAYIIi{WX@&LK1!|aY=>j=%QBWhFP>DQpEEbjNu|%XM z$}v}57v!r)T4wG`TMk{CEc9G)T@^x_$itV*@`ba~;i|}EHae4wpJ$44SSauej;R)z&B2@+|lmuTkb)DFqsyQ=g*bpix;I&Hv>Y3`1=b|Wb&<4Sl^j#E=<7W z%{`~EN0->cyji3wXgpw^WDTYD=#l)zvb?e)eX<(l!G^O-|ES5RXDyRM61_--Ll`jW z7!UgV>I-trNz_6-lQV(2TX?LZyZUjkH;D>K%!p-WsEjs=l^#F48>PcdV6 za!yL!Npoz|n&uRpVK&HJQZ%Ve;(6w7k>OC~8b*SFZY zCS7b(AxgdVgd-Eb|6lNo1I-`+0w4eaAOHd&00JNY0w4eaATUD&@caKWa}!(j<=~9y-T54HZx|rr)^W4p3;RVYclKae*VeS!~T||Vu*Fy4JhW_4`M%gyBZ6z3ZqOCIXF`op( z8jibXj;wE!p|Gr0cQ2OZ^K?Wx7*X3Ztxdy<%Y`{LgOQrdV@ABZp8JU$OY%H4S+bVfs7;nKxZgbB-b;k{J-)9(Ak_AJLPkauYn$Z`{g^*wW! zyhE(rJ2`L@N`GJteHx-gGpxJB^vUr0LBTXad8=reo6gYMv8EUh3WXLLWJD4(h(%l| zi~7c7x)(|dZ!Wb|Ft7Hx&r~J3BuqS+Toi=zx*Ai+TNS=`zAT?xlMYV>!K-hF!|+~T z&aKW9C0?APp}I5?Xpml_tFB2sSAF<>r7W+lNgvZ&Qp1F7GoprDHsF zT{6PC;<`E!=0$g@G}n_aUX(s52N7sEK27<7>C@sBe}5qvjd4*FlkwI>m=tU~C(i$Ayv_*$9{Kw`$Bue#lXZY(@;Ghm# zcZoY~U8kjztK^o_|F;qx_vRB0(ns0908pFXU?U# zArJro5C8!X009sH0T2KI5C8!X$PmEa|IZ*n0| s.Contains("Master.") && s.EndsWith(".sql",StringComparison.OrdinalIgnoreCase)); - - var upgrade = upgradeConfig.Build(); - if (upgrade.IsUpgradeRequired()) + try { - var upgradeResult = upgrade.PerformUpgrade(); - result.Success = upgradeResult.Successful; - if (!result.Success) + var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString}; + + using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) { - result.Message = upgradeResult.Error.Message; + // Push latest model into database + masterDbContext.Database.Migrate(); + result.Success = true; } } - else + catch (Exception ex) { - result.Success = true; + result.Message = ex.Message; } if (result.Success) @@ -251,10 +247,14 @@ namespace Oqtane.Infrastructure tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName); } - foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (var aliasName in install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { - var alias = new Alias { Name = aliasname, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; - db.Alias.Add(alias); + if (tenant != null) + { + var alias = new Alias { Name = aliasName, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; + db.Alias.Add(alias); + } + db.SaveChanges(); } _cache.Remove("aliases"); @@ -270,7 +270,7 @@ namespace Oqtane.Infrastructure { var result = new Installation { Success = false, Message = string.Empty }; - string[] versions = Constants.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var versions = Constants.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); using (var scope = _serviceScopeFactory.CreateScope()) { @@ -280,29 +280,28 @@ namespace Oqtane.Infrastructure { foreach (var tenant in db.Tenant.ToList()) { - MigrateScriptNamingConvention("Tenant", tenant.DBConnectionString); - - var upgradeConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(tenant.DBConnectionString)) - .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains("Tenant.") && s.EndsWith(".sql", StringComparison.OrdinalIgnoreCase)); - - var upgrade = upgradeConfig.Build(); - if (upgrade.IsUpgradeRequired()) + try { - var upgradeResult = upgrade.PerformUpgrade(); - result.Success = upgradeResult.Successful; - if (!result.Success) + var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString}; + using (var tenantDbContext = new TenantDBContext(dbConfig, null)) { - result.Message = upgradeResult.Error.Message; + // Push latest model into database + tenantDbContext.Database.Migrate(); + result.Success = true; } } + catch (Exception ex) + { + result.Message = ex.Message; + } // execute any version specific upgrade logic - string version = tenant.Version; - int index = Array.FindIndex(versions, item => item == version); + var version = tenant.Version; + var index = Array.FindIndex(versions, item => item == version); if (index != (versions.Length - 1)) { if (index == -1) index = 0; - for (int i = index; i < versions.Length; i++) + for (var i = index; i < versions.Length; i++) { upgrades.Upgrade(tenant, versions[i]); } @@ -328,53 +327,61 @@ namespace Oqtane.Infrastructure using (var scope = _serviceScopeFactory.CreateScope()) { - var moduledefinitions = scope.ServiceProvider.GetRequiredService(); + var moduleDefinitions = scope.ServiceProvider.GetRequiredService(); var sql = scope.ServiceProvider.GetRequiredService(); - foreach (var moduledefinition in moduledefinitions.GetModuleDefinitions()) + foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions()) { - if (!string.IsNullOrEmpty(moduledefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduledefinition.ServerManagerType)) + if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduleDefinition.ServerManagerType)) { - Type moduletype = Type.GetType(moduledefinition.ServerManagerType); - if (moduletype != null) + var moduleType = Type.GetType(moduleDefinition.ServerManagerType); + if (moduleType != null) { - string[] versions = moduledefinition.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) { foreach (var tenant in db.Tenant.ToList()) { - int index = Array.FindIndex(versions, item => item == moduledefinition.Version); - if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) + if (moduleType.GetInterface("IMigratable") != null) { - index = -1; + var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType) as IMigratable; + moduleObject.Migrate(tenant, MigrationType.Up); } - if (index != (versions.Length - 1)) + else { - if (index == -1) index = 0; - for (int i = index; i < versions.Length; i++) + var index = Array.FindIndex(versions, item => item == moduleDefinition.Version); + if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) { - try + index = -1; + } + if (index != (versions.Length - 1)) + { + if (index == -1) index = 0; + for (var i = index; i < versions.Length; i++) { - if (moduletype.GetInterface("IInstallable") != null) + try { - var moduleobject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduletype); - ((IInstallable)moduleobject).Install(tenant, versions[i]); + if (moduleType.GetInterface("IInstallable") != null) + { + var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType); + ((IInstallable)moduleObject).Install(tenant, versions[i]); + } + else + { + sql.ExecuteScript(tenant, moduleType.Assembly, Utilities.GetTypeName(moduleDefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); + } } - else + catch (Exception ex) { - sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); + result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message; } } - catch (Exception ex) - { - result.Message = "An Error Occurred Installing " + moduledefinition.Name + " Version " + versions[i] + " - " + ex.Message.ToString(); - } } } } - if (string.IsNullOrEmpty(result.Message) && moduledefinition.Version != versions[versions.Length - 1]) + if (string.IsNullOrEmpty(result.Message) && moduleDefinition.Version != versions[versions.Length - 1]) { - moduledefinition.Version = versions[versions.Length - 1]; - db.Entry(moduledefinition).State = EntityState.Modified; + moduleDefinition.Version = versions[versions.Length - 1]; + db.Entry(moduleDefinition).State = EntityState.Modified; db.SaveChanges(); } } @@ -401,8 +408,8 @@ namespace Oqtane.Infrastructure { // use the SiteState to set the Alias explicitly so the tenant can be resolved var aliases = scope.ServiceProvider.GetRequiredService(); - string firstalias = install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0]; - var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstalias); + var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0]; + var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias); var siteState = scope.ServiceProvider.GetRequiredService(); siteState.Alias = alias; @@ -413,82 +420,88 @@ namespace Oqtane.Infrastructure var tenants = scope.ServiceProvider.GetRequiredService(); var users = scope.ServiceProvider.GetRequiredService(); var roles = scope.ServiceProvider.GetRequiredService(); - var userroles = scope.ServiceProvider.GetRequiredService(); + var userRoles = scope.ServiceProvider.GetRequiredService(); var folders = scope.ServiceProvider.GetRequiredService(); var log = scope.ServiceProvider.GetRequiredService(); var identityUserManager = scope.ServiceProvider.GetRequiredService>(); var tenant = tenants.GetTenants().FirstOrDefault(item => item.Name == install.TenantName); - site = new Site + if (tenant != null) { - TenantId = tenant.TenantId, - Name = install.SiteName, - LogoFileId = null, - DefaultThemeType = install.DefaultTheme, - DefaultLayoutType = install.DefaultLayout, - DefaultContainerType = install.DefaultContainer, - SiteTemplateType = install.SiteTemplate - }; - site = sites.AddSite(site); - - IdentityUser identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); - if (identityUser == null) - { - identityUser = new IdentityUser { UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true }; - var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); - if (create.Succeeded) + site = new Site { - var user = new User - { - SiteId = site.SiteId, - Username = UserNames.Host, - Password = install.HostPassword, - Email = install.HostEmail, - DisplayName = install.HostName, - LastIPAddress = "", - LastLoginOn = null - }; + TenantId = tenant.TenantId, + Name = install.SiteName, + LogoFileId = null, + DefaultThemeType = install.DefaultTheme, + DefaultLayoutType = install.DefaultLayout, + DefaultContainerType = install.DefaultContainer, + SiteTemplateType = install.SiteTemplate + }; + site = sites.AddSite(site); - user = users.AddUser(user); - var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; - var userRole = new UserRole { UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null }; - userroles.AddUserRole(userRole); - - // add user folder - var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); - if (folder != null) + var identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); + if (identityUser == null) + { + identityUser = new IdentityUser {UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true}; + var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); + if (create.Succeeded) { - folders.AddFolder(new Folder + var user = new User { - SiteId = folder.SiteId, - ParentId = folder.FolderId, - Name = "My Folder", - Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), - Order = 1, - IsSystem = true, - Permissions = new List + SiteId = site.SiteId, + Username = UserNames.Host, + Password = install.HostPassword, + Email = install.HostEmail, + DisplayName = install.HostName, + LastIPAddress = "", + LastLoginOn = null + }; + + user = users.AddUser(user); + var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; + var userRole = new UserRole {UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null}; + userRoles.AddUserRole(userRole); + + // add user folder + var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); + if (folder != null) + { + folders.AddFolder(new Folder { - new Permission(PermissionNames.Browse, user.UserId, true), - new Permission(PermissionNames.View, RoleNames.Everyone, true), - new Permission(PermissionNames.Edit, user.UserId, true), - }.EncodePermissions(), - }); + SiteId = folder.SiteId, + ParentId = folder.FolderId, + Name = "My Folder", + Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), + Order = 1, + IsSystem = true, + Permissions = new List + { + new Permission(PermissionNames.Browse, user.UserId, true), + new Permission(PermissionNames.View, RoleNames.Everyone, true), + new Permission(PermissionNames.Edit, user.UserId, true), + }.EncodePermissions(), + }); + } } } + + foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) + { + alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName); + if (alias != null) + { + alias.SiteId = site.SiteId; + aliases.UpdateAlias(alias); + } + } + + tenant.Version = Constants.Version; + tenants.UpdateTenant(tenant); } - foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) - { - alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasname); - alias.SiteId = site.SiteId; - aliases.UpdateAlias(alias); - } - - tenant.Version = Constants.Version; - tenants.UpdateTenant(tenant); - - log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); + if (site != null) log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); } } } @@ -508,7 +521,7 @@ namespace Oqtane.Infrastructure private string DenormalizeConnectionString(string connectionString) { var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); - connectionString = connectionString.Replace(dataDirectory, "|DataDirectory|"); + connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|"); return connectionString; } @@ -567,18 +580,5 @@ namespace Oqtane.Infrastructure if (string.IsNullOrEmpty(value)) value = defaultValue; return value; } - - private void MigrateScriptNamingConvention(string scriptType, string connectionString) - { - // migrate to new naming convention for scripts - var migrateConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(connectionString)) - .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s == scriptType + ".00.00.00.00.sql"); - var migrate = migrateConfig.Build(); - if (migrate.IsUpgradeRequired()) - { - migrate.PerformUpgrade(); - } - } - } } diff --git a/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs b/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs index baef7184..48ed9bc8 100644 --- a/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs +++ b/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs @@ -1,10 +1,13 @@ -using Oqtane.Models; +using Microsoft.EntityFrameworkCore; +using Oqtane.Enums; +using Oqtane.Models; namespace Oqtane.Infrastructure { public interface IInstallable { bool Install(Tenant tenant, string version); + bool Uninstall(Tenant tenant); } } diff --git a/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs b/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs new file mode 100644 index 00000000..009268fc --- /dev/null +++ b/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs @@ -0,0 +1,10 @@ +using Oqtane.Enums; +using Oqtane.Models; + +namespace Oqtane.Infrastructure +{ + public interface IMigratable + { + bool Migrate(Tenant tenant, MigrationType migrationType); + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index 7e068076..d8afa1b2 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -1,40 +1,64 @@ -using Oqtane.Infrastructure; +using System; +using Oqtane.Infrastructure; using Oqtane.Models; using Oqtane.Repository; using Oqtane.Modules.HtmlText.Models; using Oqtane.Modules.HtmlText.Repository; using System.Net; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Enums; +// ReSharper disable ConvertToUsingDeclaration namespace Oqtane.Modules.HtmlText.Manager { - public class HtmlTextManager : IInstallable, IPortable + public class HtmlTextManager : IMigratable, IPortable { - private IHtmlTextRepository _htmlTexts; - private ISqlRepository _sql; + private readonly IHtmlTextRepository _htmlText; + private readonly ISqlRepository _sql; - public HtmlTextManager(IHtmlTextRepository htmltexts, ISqlRepository sql) + public HtmlTextManager(IHtmlTextRepository htmlText, ISqlRepository sql) { - _htmlTexts = htmltexts; + _htmlText = htmlText; _sql = sql; } - public bool Install(Tenant tenant, string version) + public bool Migrate(Tenant tenant, MigrationType migrationType) { - return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText." + version + ".sql"); - } + var result = true; - public bool Uninstall(Tenant tenant) - { - return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText.Uninstall.sql"); + var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString}; + using (var db = new HtmlTextContext(dbConfig, null)) + { + try + { + var migrator = db.GetService(); + if (migrationType == MigrationType.Down) + { + migrator.Migrate(Migration.InitialDatabase); + } + else + { + migrator.Migrate(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + result = false; + } + + } + return result; } public string ExportModule(Module module) { string content = ""; - HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId); - if (htmltext != null) + var htmlText = _htmlText.GetHtmlText(module.ModuleId); + if (htmlText != null) { - content = WebUtility.HtmlEncode(htmltext.Content); + content = WebUtility.HtmlEncode(htmlText.Content); } return content; } @@ -42,18 +66,18 @@ namespace Oqtane.Modules.HtmlText.Manager public void ImportModule(Module module, string content, string version) { content = WebUtility.HtmlDecode(content); - HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId); - if (htmltext != null) + var htmlText = _htmlText.GetHtmlText(module.ModuleId); + if (htmlText != null) { - htmltext.Content = content; - _htmlTexts.UpdateHtmlText(htmltext); + htmlText.Content = content; + _htmlText.UpdateHtmlText(htmlText); } else { - htmltext = new HtmlTextInfo(); - htmltext.ModuleId = module.ModuleId; - htmltext.Content = content; - _htmlTexts.AddHtmlText(htmltext); + htmlText = new HtmlTextInfo(); + htmlText.ModuleId = module.ModuleId; + htmlText.Content = content; + _htmlText.AddHtmlText(htmlText); } } } diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs new file mode 100644 index 00000000..2214df2c --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Modules.HtmlText.Migrations.EntityBuilders; +using Oqtane.Modules.HtmlText.Repository; + +namespace Oqtane.Modules.HtmlText.Migrations +{ + [DbContext(typeof(HtmlTextContext))] + [Migration("HtmlText.01.00.00.00")] + public class InitializeModule : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create HtmlText table + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + entityBuilder.Create(); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop HtmlText table + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + entityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs new file mode 100644 index 00000000..972c4c7d --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders +{ + public class HtmlTextEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "HtmlText"; + private readonly PrimaryKey _primaryKey = new("PK_HtmlText", x => x.HtmlTextId); + private readonly ForeignKey _moduleForeignKey = new("FK_HtmlText_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); + + public HtmlTextEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_moduleForeignKey); + } + + protected override HtmlTextEntityBuilder BuildTable(ColumnsBuilder table) + { + HtmlTextId = table.AddAutoIncrementColumn("HtmlTextId"); + ModuleId = table.AddIntegerColumn("ModuleId"); + Content = table.AddMaxStringColumn("Content"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder HtmlTextId { get; set; } + + public OperationBuilder ModuleId { get; set; } + + public OperationBuilder Content { get; set; } + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index e9ac5d12..f4aaf48c 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -10,7 +10,7 @@ namespace Oqtane.Modules.HtmlText.Repository { public virtual DbSet HtmlText { get; set; } - public HtmlTextContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) + public HtmlTextContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { // ContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql deleted file mode 100644 index 5c54eae2..00000000 --- a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql +++ /dev/null @@ -1,19 +0,0 @@ -CREATE TABLE [dbo].[HtmlText]( - [HtmlTextId] [int] IDENTITY(1,1) NOT NULL, - [ModuleId] [int] NOT NULL, - [Content] [nvarchar](max) NOT NULL, - [CreatedBy] [nvarchar](256) NOT NULL, - [CreatedOn] [datetime] NOT NULL, - [ModifiedBy] [nvarchar](256) NOT NULL, - [ModifiedOn] [datetime] NOT NULL, - CONSTRAINT [PK_HtmlText] PRIMARY KEY CLUSTERED - ( - [HtmlTextId] ASC - ) -) -GO - -ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId]) -REFERENCES [dbo].[Module] ([ModuleId]) -ON DELETE CASCADE -GO diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql deleted file mode 100644 index b0831b67..00000000 --- a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP TABLE [dbo].[HtmlText] -GO diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index db1b8192..a87d0533 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -20,6 +20,9 @@ + + + @@ -36,14 +39,12 @@ - - - + all @@ -67,6 +68,9 @@ + + + diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index d6535f0c..013675d0 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -7,48 +7,56 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; using Oqtane.Models; +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess namespace Oqtane.Repository { public class DBContextBase : IdentityUserContext { - private ITenantResolver _tenantResolver; - private IHttpContextAccessor _accessor; - private readonly IConfiguration _configuration; + private readonly IDbConfig _dbConfig; + private readonly ITenantResolver _tenantResolver; - public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) + public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver) { + _dbConfig = dbConfig; _tenantResolver = tenantResolver; - _accessor = accessor; - _configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - var tenant = _tenantResolver.GetTenant(); - if (tenant != null) + var connectionString = _dbConfig.ConnectionString; + + if (string.IsNullOrEmpty(connectionString) && _tenantResolver != null) + { + var tenant = _tenantResolver.GetTenant(); + var configuration = _dbConfig.Configuration; + + if (tenant != null) + { + connectionString = tenant.DBConnectionString + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + else + { + if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) + { + connectionString = configuration.GetConnectionString("DefaultConnection") + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + } + } + + if (!string.IsNullOrEmpty(connectionString)) { - var connectionString = tenant.DBConnectionString - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); optionsBuilder.UseOqtaneDatabase(connectionString); } - else - { - if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) - { - var connectionString = _configuration.GetConnectionString("DefaultConnection") - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); - optionsBuilder.UseOqtaneDatabase(connectionString); - } - - } base.OnConfiguring(optionsBuilder); } public override int SaveChanges() { - DbContextUtils.SaveChanges(this, _accessor); + DbContextUtils.SaveChanges(this, _dbConfig.Accessor); return base.SaveChanges(); } diff --git a/Oqtane.Server/Repository/Context/DbConfig.cs b/Oqtane.Server/Repository/Context/DbConfig.cs new file mode 100644 index 00000000..7bc5cb8a --- /dev/null +++ b/Oqtane.Server/Repository/Context/DbConfig.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace Oqtane.Repository +{ + public class DbConfig : IDbConfig + { + public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration) + { + Accessor = accessor; + Configuration = configuration; + } + + public IHttpContextAccessor Accessor { get; } + + public IConfiguration Configuration { get; } + + public string ConnectionString { get; set; } + } +} diff --git a/Oqtane.Server/Repository/Context/DbContextUtils.cs b/Oqtane.Server/Repository/Context/DbContextUtils.cs index 1b4014cb..aa204cad 100644 --- a/Oqtane.Server/Repository/Context/DbContextUtils.cs +++ b/Oqtane.Server/Repository/Context/DbContextUtils.cs @@ -6,7 +6,7 @@ using Oqtane.Models; namespace Oqtane.Repository { - public class DbContextUtils + public static class DbContextUtils { public static void SaveChanges(DbContext context, IHttpContextAccessor accessor) { diff --git a/Oqtane.Server/Repository/Context/InstallationContext.cs b/Oqtane.Server/Repository/Context/InstallationContext.cs index 6eaf5a65..52036bbe 100644 --- a/Oqtane.Server/Repository/Context/InstallationContext.cs +++ b/Oqtane.Server/Repository/Context/InstallationContext.cs @@ -22,5 +22,8 @@ namespace Oqtane.Repository public virtual DbSet Tenant { get; set; } public virtual DbSet ModuleDefinition { get; set; } public virtual DbSet Job { get; set; } + public virtual DbSet JobLog { get; set; } + + } } diff --git a/Oqtane.Server/Repository/Context/MasterDBContext.cs b/Oqtane.Server/Repository/Context/MasterDBContext.cs index dd94dedd..68ef6b07 100644 --- a/Oqtane.Server/Repository/Context/MasterDBContext.cs +++ b/Oqtane.Server/Repository/Context/MasterDBContext.cs @@ -1,31 +1,42 @@ using System; -using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Oqtane.Models; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable CheckNamespace + namespace Oqtane.Repository { public class MasterDBContext : DbContext { - private readonly IHttpContextAccessor _accessor; - private readonly IConfiguration _configuration; + private readonly IDbConfig _dbConfig; - public MasterDBContext(DbContextOptions options, IHttpContextAccessor accessor, IConfiguration configuration) : base(options) + public MasterDBContext(DbContextOptions options, IDbConfig dbConfig) : base(options) { - _accessor = accessor; - _configuration = configuration; + _dbConfig = dbConfig; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) - { - var connectionString = _configuration.GetConnectionString("DefaultConnection") - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + var connectionString = _dbConfig.ConnectionString; + var configuration = _dbConfig.Configuration; + if(string.IsNullOrEmpty(connectionString) && configuration != null) + { + if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) + { + connectionString = configuration.GetConnectionString("DefaultConnection") + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + + } + + if (!string.IsNullOrEmpty(connectionString)) + { optionsBuilder.UseOqtaneDatabase(connectionString); } base.OnConfiguring(optionsBuilder); @@ -39,7 +50,7 @@ namespace Oqtane.Repository public override int SaveChanges() { - DbContextUtils.SaveChanges(this, _accessor); + DbContextUtils.SaveChanges(this, _dbConfig.Accessor); return base.SaveChanges(); } diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index 4390739f..3e2f5d3d 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -24,7 +24,7 @@ namespace Oqtane.Repository public virtual DbSet Language { get; set; } - public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) + public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { // DBContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs new file mode 100644 index 00000000..6ba4cfbe --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace Oqtane.Repository +{ + public interface IDbConfig + { + public IHttpContextAccessor Accessor { get; } + + public IConfiguration Configuration { get; } + + public string ConnectionString { get; set; } + } +} diff --git a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs index a1402e3b..76a6f701 100644 --- a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs @@ -1,5 +1,5 @@ -using System.Data.SqlClient; -using System.Reflection; +using System.Reflection; +using Microsoft.Data.SqlClient; using Oqtane.Models; namespace Oqtane.Repository diff --git a/Oqtane.Server/Repository/SqlRepository.cs b/Oqtane.Server/Repository/SqlRepository.cs index fcc4caf3..037a9e42 100644 --- a/Oqtane.Server/Repository/SqlRepository.cs +++ b/Oqtane.Server/Repository/SqlRepository.cs @@ -1,9 +1,9 @@ using System; using System.Data; -using System.Data.SqlClient; using System.IO; using System.Linq; using System.Reflection; +using Microsoft.Data.SqlClient; using Oqtane.Models; namespace Oqtane.Repository @@ -59,8 +59,8 @@ namespace Oqtane.Repository public int ExecuteNonQuery(Tenant tenant, string query) { - SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); - SqlCommand cmd = conn.CreateCommand(); + var conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); + var cmd = conn.CreateCommand(); using (conn) { PrepareCommand(conn, cmd, query); diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index ba2a7d89..5ba2ff1b 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -130,6 +130,7 @@ namespace Oqtane services.AddSingleton(); + services.AddScoped(); services.AddDbContext(options => { }); services.AddDbContext(options => { }); @@ -211,7 +212,7 @@ namespace Oqtane services.AddTransient(); services.AddTransient(); - // load the external assemblies into the app domain, install services + // load the external assemblies into the app domain, install services services.AddOqtane(_runtime, _supportedCultures); services.AddMvc() diff --git a/Oqtane.Server/appsettings.json b/Oqtane.Server/appsettings.json index 1af87b4c..06f423f8 100644 --- a/Oqtane.Server/appsettings.json +++ b/Oqtane.Server/appsettings.json @@ -1,6 +1,10 @@ { + "Database": { + "DatabaseType": "", + "DatabaseEngineVersion": "" + }, "ConnectionStrings": { - "DefaultConnection": "" + "DefaultConnection": "Data Source=.;Initial Catalog=Oqtane-Migrations;Integrated Security=SSPI;" }, "Runtime": "Server", "Installation": { diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css new file mode 100644 index 00000000..0856a263 --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css @@ -0,0 +1 @@ +/* Module Custom Styles */ \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js new file mode 100644 index 00000000..1b415a08 --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js @@ -0,0 +1 @@ +/* Module Script */ \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json new file mode 100644 index 00000000..72f421fc --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json @@ -0,0 +1 @@ +["\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.pdb","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.css","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.js"] \ No newline at end of file diff --git a/Oqtane.Shared/Enums/MigrationType.cs b/Oqtane.Shared/Enums/MigrationType.cs new file mode 100644 index 00000000..e428520a --- /dev/null +++ b/Oqtane.Shared/Enums/MigrationType.cs @@ -0,0 +1,8 @@ +namespace Oqtane.Enums +{ + public enum MigrationType + { + Up, + Down + } +} From cbcfc8849256c986e0e3017ff96702d9df7e8a8e Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Tue, 23 Mar 2021 11:06:18 -0700 Subject: [PATCH 03/23] Add support for Sqlite - Installation path tested but AddSite not supported yet --- .gitignore | 1 + Oqtane.Client/UI/Installer.razor | 53 ++++++++----- Oqtane.Server/Data/Oqtane.db | Bin 200704 -> 0 bytes .../DbContextOptionsBuilderExtensions.cs | 14 +++- .../Infrastructure/DatabaseManager.cs | 75 ++++++++++-------- .../Infrastructure/InstallationManager.cs | 1 + .../Infrastructure/Interfaces/IMigratable.cs | 10 --- .../Migrations/01000000_InitializeTenant.cs | 6 ++ .../Migrations/01000201_DropColumnFromPage.cs | 2 +- .../02010001_AddDatabaseTypeColumnToTenant.cs | 27 +++++++ .../EntityBuilders/PageEntityBuilder.cs | 3 - .../HtmlText/Manager/HtmlTextManager.cs | 43 +++------- Oqtane.Server/Modules/MigratableModuleBase.cs | 42 ++++++++++ .../Repository/Context/DBContextBase.cs | 38 ++++++--- Oqtane.Server/Repository/Context/DbConfig.cs | 2 + .../Repository/Context/InstallationContext.cs | 6 +- .../Repository/Context/MasterDBContext.cs | 5 +- .../Repository/Interfaces/IDbConfig.cs | 1 + Oqtane.Server/appsettings.json | 4 +- Oqtane.Shared/Models/Tenant.cs | 1 + Oqtane.Shared/Shared/InstallConfig.cs | 1 + Oqtane.Shared/Shared/SettingKeys.cs | 8 +- 22 files changed, 227 insertions(+), 116 deletions(-) delete mode 100644 Oqtane.Server/Data/Oqtane.db delete mode 100644 Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs create mode 100644 Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs create mode 100644 Oqtane.Server/Modules/MigratableModuleBase.cs diff --git a/.gitignore b/.gitignore index 98408e86..29b72c2a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ msbuild.binlog Oqtane.Server/appsettings.json Oqtane.Server/Data/*.mdf Oqtane.Server/Data/*.ldf +Oqtane.Server/Data/*.db /Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml Oqtane.Server/Content diff --git a/Oqtane.Client/UI/Installer.razor b/Oqtane.Client/UI/Installer.razor index 9231e092..5983c253 100644 --- a/Oqtane.Client/UI/Installer.razor +++ b/Oqtane.Client/UI/Installer.razor @@ -27,10 +27,19 @@ - + + + + + + + + + @@ -38,7 +47,7 @@ - + @@ -46,7 +55,7 @@ - + @@ -129,6 +138,7 @@ @code { private string _databaseType = "LocalDB"; private string _serverName = "(LocalDb)\\MSSQLLocalDB"; + private string _fileName = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm") + ".db"; private string _databaseName = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm"); private string _username = string.Empty; private string _password = string.Empty; @@ -138,6 +148,8 @@ private string _hostEmail = string.Empty; private string _message = string.Empty; private string _integratedSecurityDisplay = "display: none;"; + private string _fileFieldsDisplay = "display: none;"; + private string _serverFieldsDisplay = "display: none;"; private string _loadingDisplay = "display: none;"; protected override async Task OnAfterRenderAsync(bool firstRender) @@ -158,33 +170,38 @@ private async Task Install() { - if (_serverName != "" && _databaseName != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "") + if (((_serverName != "" && _databaseName != "") || _fileName !="") && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "") { _loadingDisplay = ""; StateHasChanged(); var connectionstring = ""; - if (_databaseType == "LocalDB") + switch (_databaseType) { - connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;"; - } - else - { - connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";"; - if (_integratedSecurityDisplay == "display: none;") - { - connectionstring += "Integrated Security=SSPI;"; - } - else - { - connectionstring += "User ID=" + _username + ";Password=" + _password; - } + case "LocalDB": + connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;"; + break; + case "SQLServer": + connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";"; + if (_integratedSecurityDisplay == "display: none;") + { + connectionstring += "Integrated Security=SSPI;"; + } + else + { + connectionstring += "User ID=" + _username + ";Password=" + _password; + } + break; + case "Sqlite": + connectionstring = "Data Source=" + _fileName; + break; } Uri uri = new Uri(NavigationManager.Uri); var config = new InstallConfig { + DatabaseType = _databaseType, ConnectionString = connectionstring, Aliases = uri.Authority, HostEmail = _hostEmail, diff --git a/Oqtane.Server/Data/Oqtane.db b/Oqtane.Server/Data/Oqtane.db deleted file mode 100644 index d02cc5a4e260a659fdcdeb39c8340186f72a2eab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200704 zcmeI5?{6E)dB?eyCCa*!d5NOz=^V%Fb(|A(w$JYMa4#C*N|Q_9o~0#^q^@$19J?k* z@+Q=-Zg**0`GG_}+sWOfKVAe#Ul%Bl7wwzAE6^7$`ldk9H!aYApe+#eUEUM{`l6lL z+2Q`Cl*FzL<||kfcb;dSnf*LJW@ahd-S;*upC~(yyJz~!8>N>@Cr*@pUr|b>(kc3V zjed)-EA-7taY27dvG+x9PnE9R_}M&_&Q*TFbS_r@r}E#GU!3yGEAu~@e|P@m$se42 zd+z6RKQ8^W^2?Z!M{cDoudYg;-tf)aBhsaFWZy5G+gWBHI zjNYZtT#wkM?dKU38iu(?hwo|IbewQ3A=+?uou)M+iSBeRLf$m*S_8+PrqUog=6K}y z?vOpwJJ>H8DOB4q51g@ov|in@ebcguJ4Lm9&(uB5X5e#hid&#swf%klh`XR#-Tjg2 z-8o9JHX1qiI%L=KeAo0X$Id!Zj9hn#>6790g97-WyhTmqI%m@vT07Ph145zDLW7J* zVg@nShO(${Os0FGG<$Q)OVzKPUXWjxrSDnxklfd|`?Zl}dVLXx!Br(p0NrS4+lrb| zQk9mWsDUa?3{~`1t6R$p@@s3-SlE8oxlLoVPk-n`{{D2vbX zt?O#KEy&<%V`)J?D@y}0g8*Of@L!&R14)uMK}3A<5yyqq_0vJegJiMwgU&ty`}(G@6DFKPZ>wl@;mZ3j#mww3q>(pq_^)z3v1< zAIW>lqCyQ!soG7Kd^jfdpr|V9wolx<<|tcw3Vj(dS2cTB;KXAr6}lIMNy5*m1(RC2 zPX=S(vUiIoXpsAUsK(X@Ufg4o?9ifYvzqY^T}2$1l1T3b#H~KNC4>gpN9~2OeEG8U znCEx8D5bB<$VpiP*R(=BEbn2ClWwSNV(=>$IBeIH-!FTEz+3f$>^IHG9! z9xt#Ybvd7KaZ0#u(?h}~+OztA%<)zIVqlYx&tFd_EQGtZD6c0|&6KnB62mo*k;7Bs zq;Z{|5o|JG+1d5opdjaNqo31MJlvMb@>_374_X1|eqU>DTD$yA;e`uBZsUoh7jktX zr%Y_Jj7jiGJEg!-ESE(Bwq3gS9r!7*VII>eqn}uizwwq-3bvSGpqXRe39kFOccicx7?!n#>=oT)Fx?SFTRQa#UzgGUX@)wmq zuH38qA#K1H2!H?xfB*=900@8p2!H?xfB*=9K$gJg=dMZF=LC!KW_~PZj|j@yW-7e4 zklTE9KHJRB?myg7OjaAI}t+9{#Uo0$>z`9J-oe|&)e2!H?xfB*=900@8p z2!H?xfB*>0FaezZXV|&8H4p#+5C8!X009sH0T2KI5C8!X2npc)k5B*s5C8!X009sH z0T2KI5C8!X0D;*jfb;+C`xti!0w4eaAOHd&00JNY0w4eaAOHe5|04!K00ck)1V8`; zKmY_l00ck)1VCW+3E=!c`##1Uf&d7B00@8p2!H?xfB*=900@8p`~Uy&@BbqXKmY_l z00ck)1V8`;KmY_l00cl_wh7?;KimGr-GKlIfB*=900@8p2!H?xfB*=903(3&KjHuc zKmY_l00ck)1V8`;KmY_l00d^A0M7rj?_=B{2!H?xfB*=900@8p2!H?xfB*>K{Erv_ z0T2KI5C8!X009sH0T2KI5CDPMCxG++?E4sZ2m&Ag0w4eaAOHd&00JNY0w4ea`2YV9 z10VnbAOHd&00JNY0w4eaAOHd&F#7~>{-1px;|@Up1V8`;KmY_l00ck)1V8`;Kw!D@ z%TlHE)6(gGsr=RQH5!tbo)3in;(VgC}kT=b{*1)l+sWixrIUf1FJ7kaa4)%*i3e`5u z183|Xtygz!-?VJvPEl>&Gj&h1nR9boCT@Xh)%N%GBkqD~b@xZ6cjqX@+Gyn5>yTZ` z^Ig-o96K8Z9xWC8%qoF zSy>v083g!(mlrZ)g=iC$xs`WLEy(BAq+MZ!v*)i%89Th4&s4l$SGlDJ-(4)rYirV@ zZct!3bpCoOG!zzD-WZixew`>f*+Lr>LDBQbGDsEk?1@~YQ*`|XO~-;+Icj5}M zbm)!;144$0DiaeMj!!&cH)@ZT3`K3;WFZ_zvZ^#&9ZkPs1Vw!kqe@3>Y8}m}Yh8uK zZ7h6QwluU2jV@dDTDM+nXfzEUeo!vUD=X5+7X*IVX)yynK|K#qY;6T>5>n}#2yq?Mcwv^d)FLgOHZLMBj&1R4-1@ljHN>Nf-p(=IkjL?EBDD@>|6G3 z@dOQW-w)N;`oN2OY?2*Xlxk;XX~}VdGTrAG5t{BYC1T^En4cQN8@Sd!U*$7itkY_;>$p~4?yK(;*9$fW z*>2BlSHN6q%$H?ZmL7j6s2R};vXFFMxO|9had3GYH--Ivlj^}&nY_V7Qm~EjH2Jej znsA1x${#=p_ebg4Ke^j#qWnioZA>9=5on*J`=!^UTY)>h4@VSD-{S?Aq%P+ZE=~#8 zZF)$!M0-{rkU74pUkq&W@%ih?goSX|7UlJ1s+n?@UShcBF>*Mbn5jzKxK7UqHW{$& z?D}p{kaM@u&uJ1GA zQeY^S%OU~WF5UYM{1n*GKeWo|Cl=&yyd{-_EoK;K=Gb?F>wfMy{cE|+bM%b8$WGks z^Z&)t9{n!=`TRee_`Bu*T>i5c{)9F>jjxAoxh$VOEB(j|T(jj7x8sb6`1wlG0iro# zE?V-6RGPZbJw`Gx)jX5JEo_d{-OP9N(V27mL-?!X@0^##kR0X#_dy}rJA*p0d z<%;X-M3||k`Q@AGGqip7k{&5!o*aoQuB$>wQ{r)Hr7WL6FMWD52&uNYOZfgIdiVKc zSVe*;u%fm+Kc_=0(mqCTG37j?BDnZ$r)l&opYci57}2|J+C`$4J7f+l+yNisLC`ag zP4y`}Xvq)8$fteok#s;#{FDqyp)8&)P)Ame9Dxm%wjahx(mGdMS0}N(R{m4dqxO*8Q1oJKUw1MCIeie&mm0zj!J)uV*SGxUkV=P{}Dg92-}}Y22N-v3>$WJoS@;o ze&dh{rkr2?rbJJoYR1l;WEcGCQk$u8}aC3EmRsG55H7tkO_sc~^p9y)<=kNG_+-4t9 zRv*6nxge^3#CHh7mYj^LuwNKe>?%?23ZjblIx?!5S}>XXLf)`E`YGYTl=#y2Olwjf zQ<2ralQZrw0FpMFSS*}0#}F{!>^8xCFKO+If(4e`uF?rCg=>E;pt{@>Gh&;gqu z00JNY0w4eaAOHd&00JNY0wC~w5y0R7f4=;I*?<5DfB*=900@8p2!H?xfB*=9z|$ar z^Z(PJ3Y#DR0w4eaAOHd&00JNY0w4eaAn<$9zn)*7yL;k)OK&dkEPb%_H*~b? z1tUJXakeaR= zut=>5nPKh`Rq1KlbdYc$A?jKFs7Tfz-oUl?eao>$@0iiL>62Z@JrJUl;rA_aujLMj zo4rXf_NIA%gV?+Nonn;+*)hi>|9x{bp3E{f2i@zC566~Ea!`sS+26BM69f zHS~T}>1a)@qZxIrs|1ZS>LOvwP#W5XMnkh+>(*-xZF#9W{z6$ke?~g|JsD%7YNDzm{f+qe9KAmT15;T4Tb`aV<&MAeTz zcP2=nN8b+;C^_i4WCBIjMXd8FCc?cSfhK*AOrY4r^HYT@A@)x4sGJ@S)NC0K=kg5ML`j%@VJOyPvUSA7I{Gu^$^mIGh&5} z_S*7@OW#!=pI@UfdtUnSGB3V4Gd!D&pvY>h3QxM_xinLVC)%oVWGH27amvL{Ak?Be z3OMCQTZk@NWuoFDVCKqnuQvAYIIi{WX@&LK1!|aY=>j=%QBWhFP>DQpEEbjNu|%XM z$}v}57v!r)T4wG`TMk{CEc9G)T@^x_$itV*@`ba~;i|}EHae4wpJ$44SSauej;R)z&B2@+|lmuTkb)DFqsyQ=g*bpix;I&Hv>Y3`1=b|Wb&<4Sl^j#E=<7W z%{`~EN0->cyji3wXgpw^WDTYD=#l)zvb?e)eX<(l!G^O-|ES5RXDyRM61_--Ll`jW z7!UgV>I-trNz_6-lQV(2TX?LZyZUjkH;D>K%!p-WsEjs=l^#F48>PcdV6 za!yL!Npoz|n&uRpVK&HJQZ%Ve;(6w7k>OC~8b*SFZY zCS7b(AxgdVgd-Eb|6lNo1I-`+0w4eaAOHd&00JNY0w4eaATUD&@caKWa}!(j<=~9y-T54HZx|rr)^W4p3;RVYclKae*VeS!~T||Vu*Fy4JhW_4`M%gyBZ6z3ZqOCIXF`op( z8jibXj;wE!p|Gr0cQ2OZ^K?Wx7*X3Ztxdy<%Y`{LgOQrdV@ABZp8JU$OY%H4S+bVfs7;nKxZgbB-b;k{J-)9(Ak_AJLPkauYn$Z`{g^*wW! zyhE(rJ2`L@N`GJteHx-gGpxJB^vUr0LBTXad8=reo6gYMv8EUh3WXLLWJD4(h(%l| zi~7c7x)(|dZ!Wb|Ft7Hx&r~J3BuqS+Toi=zx*Ai+TNS=`zAT?xlMYV>!K-hF!|+~T z&aKW9C0?APp}I5?Xpml_tFB2sSAF<>r7W+lNgvZ&Qp1F7GoprDHsF zT{6PC;<`E!=0$g@G}n_aUX(s52N7sEK27<7>C@sBe}5qvjd4*FlkwI>m=tU~C(i$Ayv_*$9{Kw`$Bue#lXZY(@;Ghm# zcZoY~U8kjztK^o_|F;qx_vRB0(ns0908pFXU?U# zArJro5C8!X009sH0T2KI5C8!X$PmEa|IZ*n0|(), dbConfig)) { @@ -216,6 +217,7 @@ namespace Oqtane.Infrastructure if (result.Success) { UpdateConnectionString(install.ConnectionString); + UpdateDatabaseType(install.DatabaseType); } } else @@ -232,12 +234,18 @@ namespace Oqtane.Infrastructure if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases)) { - using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) + using (var db = new InstallationContext(install.DatabaseType, NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) { Tenant tenant; if (install.IsNewTenant) { - tenant = new Tenant { Name = install.TenantName, DBConnectionString = DenormalizeConnectionString(install.ConnectionString), CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; + tenant = new Tenant { Name = install.TenantName, + DBConnectionString = DenormalizeConnectionString(install.ConnectionString), + DBType = install.DatabaseType, + CreatedBy = "", + CreatedOn = DateTime.UtcNow, + ModifiedBy = "", + ModifiedOn = DateTime.UtcNow }; db.Tenant.Add(tenant); db.SaveChanges(); _cache.Remove("tenants"); @@ -276,13 +284,15 @@ namespace Oqtane.Infrastructure { var upgrades = scope.ServiceProvider.GetRequiredService(); - using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) + var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; + var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); + using (var db = new InstallationContext(databaseType, connectionString)) { foreach (var tenant in db.Tenant.ToList()) { try { - var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString}; + var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; using (var tenantDbContext = new TenantDBContext(dbConfig, null)) { // Push latest model into database @@ -337,44 +347,37 @@ namespace Oqtane.Infrastructure if (moduleType != null) { var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) - { + var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; + var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); + using (var db = new InstallationContext(databaseType, connectionString)) { foreach (var tenant in db.Tenant.ToList()) { - if (moduleType.GetInterface("IMigratable") != null) + var index = Array.FindIndex(versions, item => item == moduleDefinition.Version); + if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) { - var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType) as IMigratable; - moduleObject.Migrate(tenant, MigrationType.Up); + index = -1; } - else + if (index != (versions.Length - 1)) { - var index = Array.FindIndex(versions, item => item == moduleDefinition.Version); - if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) + if (index == -1) index = 0; + for (var i = index; i < versions.Length; i++) { - index = -1; - } - if (index != (versions.Length - 1)) - { - if (index == -1) index = 0; - for (var i = index; i < versions.Length; i++) + try { - try + if (moduleType.GetInterface("IInstallable") != null) { - if (moduleType.GetInterface("IInstallable") != null) - { - var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType); - ((IInstallable)moduleObject).Install(tenant, versions[i]); - } - else - { - sql.ExecuteScript(tenant, moduleType.Assembly, Utilities.GetTypeName(moduleDefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); - } + var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType) as IInstallable; + moduleObject?.Install(tenant, versions[i]); } - catch (Exception ex) + else { - result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message; + sql.ExecuteScript(tenant, moduleType.Assembly, Utilities.GetTypeName(moduleDefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); } } + catch (Exception ex) + { + result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message; + } } } } @@ -530,11 +533,17 @@ namespace Oqtane.Infrastructure connectionString = DenormalizeConnectionString(connectionString); if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString) { - AddOrUpdateAppSetting($"ConnectionStrings:{SettingKeys.ConnectionStringKey}", connectionString); + AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString); _config.Reload(); } } + public void UpdateDatabaseType(string databaseType) + { + AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType); + _config.Reload(); + } + public void AddOrUpdateAppSetting(string sectionPathKey, T value) { try diff --git a/Oqtane.Server/Infrastructure/InstallationManager.cs b/Oqtane.Server/Infrastructure/InstallationManager.cs index 3b627c70..3962baf5 100644 --- a/Oqtane.Server/Infrastructure/InstallationManager.cs +++ b/Oqtane.Server/Infrastructure/InstallationManager.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Hosting; using Oqtane.Shared; +// ReSharper disable AssignNullToNotNullAttribute namespace Oqtane.Infrastructure { diff --git a/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs b/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs deleted file mode 100644 index 009268fc..00000000 --- a/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Oqtane.Enums; -using Oqtane.Models; - -namespace Oqtane.Infrastructure -{ - public interface IMigratable - { - bool Migrate(Tenant tenant, MigrationType migrationType); - } -} diff --git a/Oqtane.Server/Migrations/01000000_InitializeTenant.cs b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs index d977e508..fe1b8b1e 100644 --- a/Oqtane.Server/Migrations/01000000_InitializeTenant.cs +++ b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs @@ -21,6 +21,12 @@ namespace Oqtane.Migrations pageEntityBuilder.Create(); pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); + //Add Column to Page table (for Sql Server only) we will drop it later for Sql Server only + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer") + { + pageEntityBuilder.AddBooleanColumn("EditMode"); + } + //Create Module table var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder); moduleEntityBuilder.Create(); diff --git a/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs index 516aae4d..9ee79ff7 100644 --- a/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs +++ b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs @@ -12,7 +12,7 @@ namespace Oqtane.Migrations protected override void Up(MigrationBuilder migrationBuilder) { //Drop Column from Page table - if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer") { var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); pageEntityBuilder.DropColumn("EditMode"); diff --git a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs new file mode 100644 index 00000000..bfea92bd --- /dev/null +++ b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(MasterDBContext))] + [Migration("Master.02.01.00.01")] + public class AddDatabaseTypeColumnToTenant : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Add Column to Site table + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + tenantEntityBuilder.AddStringColumn("DBType", 200, true); + + //Update new column + migrationBuilder.Sql( + @" + UPDATE Tenant + SET DBType = 'SqlServer' + "); + + } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs index 49c75ba0..c259b945 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs @@ -35,7 +35,6 @@ namespace Oqtane.Migrations.EntityBuilders IsNavigation = table.AddBooleanColumn("IsNavigation"); Url = table.AddStringColumn("Url", 500, true); LayoutType = table.AddStringColumn("LayoutType", 200); - EditMode = table.AddBooleanColumn("EditMode"); UserId = table.AddIntegerColumn("UserId", true); IsPersonalizable = table.AddBooleanColumn("IsPersonalizable"); DefaultContainerType = table.AddStringColumn("DefaultContainerType", 200, true); @@ -69,8 +68,6 @@ namespace Oqtane.Migrations.EntityBuilders public OperationBuilder LayoutType { get; private set; } - public OperationBuilder EditMode { get; private set; } - public OperationBuilder UserId { get; private set; } public OperationBuilder IsPersonalizable { get; private set; } diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index d8afa1b2..4329a4c7 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -12,7 +12,7 @@ using Oqtane.Enums; namespace Oqtane.Modules.HtmlText.Manager { - public class HtmlTextManager : IMigratable, IPortable + public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable { private readonly IHtmlTextRepository _htmlText; private readonly ISqlRepository _sql; @@ -23,35 +23,6 @@ namespace Oqtane.Modules.HtmlText.Manager _sql = sql; } - public bool Migrate(Tenant tenant, MigrationType migrationType) - { - var result = true; - - var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString}; - using (var db = new HtmlTextContext(dbConfig, null)) - { - try - { - var migrator = db.GetService(); - if (migrationType == MigrationType.Down) - { - migrator.Migrate(Migration.InitialDatabase); - } - else - { - migrator.Migrate(); - } - } - catch (Exception e) - { - Console.WriteLine(e); - result = false; - } - - } - return result; - } - public string ExportModule(Module module) { string content = ""; @@ -80,5 +51,17 @@ namespace Oqtane.Modules.HtmlText.Manager _htmlText.AddHtmlText(htmlText); } } + + public bool Install(Tenant tenant, string version) + { + var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; + return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Up); + } + + public bool Uninstall(Tenant tenant) + { + var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; + return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Down); + } } } diff --git a/Oqtane.Server/Modules/MigratableModuleBase.cs b/Oqtane.Server/Modules/MigratableModuleBase.cs new file mode 100644 index 00000000..c282d324 --- /dev/null +++ b/Oqtane.Server/Modules/MigratableModuleBase.cs @@ -0,0 +1,42 @@ +using System; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Enums; +using Oqtane.Models; +using Oqtane.Modules.HtmlText.Repository; +using Oqtane.Repository; + +namespace Oqtane.Modules +{ + public class MigratableModuleBase + { + public bool Migrate(DBContextBase dbContext, Tenant tenant, MigrationType migrationType) + { + var result = true; + + using (dbContext) + { + try + { + var migrator = dbContext.GetService(); + if (migrationType == MigrationType.Down) + { + migrator.Migrate(Migration.InitialDatabase); + } + else + { + migrator.Migrate(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + result = false; + } + + } + return result; + + } + } +} diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index 013675d0..550665da 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -7,48 +7,62 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; using Oqtane.Models; +using Oqtane.Shared; + // ReSharper disable BuiltInTypeReferenceStyleForMemberAccess namespace Oqtane.Repository { public class DBContextBase : IdentityUserContext { - private readonly IDbConfig _dbConfig; private readonly ITenantResolver _tenantResolver; + private readonly IHttpContextAccessor _accessor; + private readonly IConfiguration _configuration; + private string _connectionString; + private string _databaseType; + + public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor httpContextAccessor) + { + _connectionString = String.Empty; + _tenantResolver = tenantResolver; + _accessor = httpContextAccessor; + } public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver) { - _dbConfig = dbConfig; + _accessor = dbConfig.Accessor; + _configuration = dbConfig.Configuration; + _connectionString = dbConfig.ConnectionString; + _databaseType = dbConfig.DatabaseType; _tenantResolver = tenantResolver; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - var connectionString = _dbConfig.ConnectionString; - - if (string.IsNullOrEmpty(connectionString) && _tenantResolver != null) + if (string.IsNullOrEmpty(_connectionString) && _tenantResolver != null) { var tenant = _tenantResolver.GetTenant(); - var configuration = _dbConfig.Configuration; if (tenant != null) { - connectionString = tenant.DBConnectionString + _connectionString = tenant.DBConnectionString .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + _databaseType = tenant.DBType; } else { - if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) + if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) { - connectionString = configuration.GetConnectionString("DefaultConnection") + _connectionString = _configuration.GetConnectionString("DefaultConnection") .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); } + _databaseType = _configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; } } - if (!string.IsNullOrEmpty(connectionString)) + if (!string.IsNullOrEmpty(_connectionString) && !string.IsNullOrEmpty(_databaseType)) { - optionsBuilder.UseOqtaneDatabase(connectionString); + optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); } base.OnConfiguring(optionsBuilder); @@ -56,7 +70,7 @@ namespace Oqtane.Repository public override int SaveChanges() { - DbContextUtils.SaveChanges(this, _dbConfig.Accessor); + DbContextUtils.SaveChanges(this, _accessor); return base.SaveChanges(); } diff --git a/Oqtane.Server/Repository/Context/DbConfig.cs b/Oqtane.Server/Repository/Context/DbConfig.cs index 7bc5cb8a..7cc636ef 100644 --- a/Oqtane.Server/Repository/Context/DbConfig.cs +++ b/Oqtane.Server/Repository/Context/DbConfig.cs @@ -16,5 +16,7 @@ namespace Oqtane.Repository public IConfiguration Configuration { get; } public string ConnectionString { get; set; } + + public string DatabaseType { get; set; } } } diff --git a/Oqtane.Server/Repository/Context/InstallationContext.cs b/Oqtane.Server/Repository/Context/InstallationContext.cs index 52036bbe..061aecbb 100644 --- a/Oqtane.Server/Repository/Context/InstallationContext.cs +++ b/Oqtane.Server/Repository/Context/InstallationContext.cs @@ -9,14 +9,16 @@ namespace Oqtane.Repository public class InstallationContext : DbContext { private readonly string _connectionString; + private readonly string _databaseType; - public InstallationContext(string connectionString) + public InstallationContext(string databaseType, string connectionString) { _connectionString = connectionString; + _databaseType = databaseType; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseOqtaneDatabase(_connectionString); + => optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); public virtual DbSet Alias { get; set; } public virtual DbSet Tenant { get; set; } diff --git a/Oqtane.Server/Repository/Context/MasterDBContext.cs b/Oqtane.Server/Repository/Context/MasterDBContext.cs index 68ef6b07..04f61176 100644 --- a/Oqtane.Server/Repository/Context/MasterDBContext.cs +++ b/Oqtane.Server/Repository/Context/MasterDBContext.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore; using Oqtane.Models; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; +using Oqtane.Shared; // ReSharper disable BuiltInTypeReferenceStyleForMemberAccess // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,6 +25,7 @@ namespace Oqtane.Repository { var connectionString = _dbConfig.ConnectionString; var configuration = _dbConfig.Configuration; + var databaseType = _dbConfig.DatabaseType; if(string.IsNullOrEmpty(connectionString) && configuration != null) { @@ -33,11 +35,12 @@ namespace Oqtane.Repository .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); } + databaseType = configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; } if (!string.IsNullOrEmpty(connectionString)) { - optionsBuilder.UseOqtaneDatabase(connectionString); + optionsBuilder.UseOqtaneDatabase(databaseType, connectionString); } base.OnConfiguring(optionsBuilder); } diff --git a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs index 6ba4cfbe..cde50726 100644 --- a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs +++ b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs @@ -10,5 +10,6 @@ namespace Oqtane.Repository public IConfiguration Configuration { get; } public string ConnectionString { get; set; } + public string DatabaseType { get; set; } } } diff --git a/Oqtane.Server/appsettings.json b/Oqtane.Server/appsettings.json index 06f423f8..33858f9e 100644 --- a/Oqtane.Server/appsettings.json +++ b/Oqtane.Server/appsettings.json @@ -1,10 +1,10 @@ { "Database": { - "DatabaseType": "", + "DatabaseType": "Sqlite", "DatabaseEngineVersion": "" }, "ConnectionStrings": { - "DefaultConnection": "Data Source=.;Initial Catalog=Oqtane-Migrations;Integrated Security=SSPI;" + "DefaultConnection": "Data Source=Oqtane.db" }, "Runtime": "Server", "Installation": { diff --git a/Oqtane.Shared/Models/Tenant.cs b/Oqtane.Shared/Models/Tenant.cs index 645f1e97..d0891563 100644 --- a/Oqtane.Shared/Models/Tenant.cs +++ b/Oqtane.Shared/Models/Tenant.cs @@ -7,6 +7,7 @@ namespace Oqtane.Models public int TenantId { get; set; } public string Name { get; set; } public string DBConnectionString { get; set; } + public string DBType { get; set; } public string Version { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } diff --git a/Oqtane.Shared/Shared/InstallConfig.cs b/Oqtane.Shared/Shared/InstallConfig.cs index 7658e97d..5ca5284d 100644 --- a/Oqtane.Shared/Shared/InstallConfig.cs +++ b/Oqtane.Shared/Shared/InstallConfig.cs @@ -3,6 +3,7 @@ namespace Oqtane.Shared public class InstallConfig { public string ConnectionString { get; set; } + public string DatabaseType { get; set; } public string Aliases { get; set; } public string TenantName { get; set; } public bool IsNewTenant { get; set; } diff --git a/Oqtane.Shared/Shared/SettingKeys.cs b/Oqtane.Shared/Shared/SettingKeys.cs index 6524e333..0656bbc5 100644 --- a/Oqtane.Shared/Shared/SettingKeys.cs +++ b/Oqtane.Shared/Shared/SettingKeys.cs @@ -2,12 +2,18 @@ { public static class SettingKeys { + public const string ConnectionStringsSection = "ConnectionStrings"; + public const string DatabaseSection = "Database"; public const string InstallationSection = "Installation"; + + public const string ConnectionStringKey = "DefaultConnection"; + + public const string DatabaseTypeKey = "DatabaseType"; + public const string DefaultAliasKey = "DefaultAlias"; public const string HostPasswordKey = "HostPassword"; public const string HostEmailKey = "HostEmail"; public const string SiteTemplateKey = "SiteTemplate"; - public const string ConnectionStringKey = "DefaultConnection"; public const string DefaultThemeKey = "DefaultTheme"; public const string DefaultLayoutKey = "DefaultLayout"; public const string DefaultContainerKey = "DefaultContainer"; From 3a032f401ac6ad7a2d96ffbec2c6f05853c78295 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 24 Mar 2021 11:45:44 -0700 Subject: [PATCH 04/23] Added IDatabase interface and refactored to use it to handle database type - updated Installer to dynamically add databases to selector --- Oqtane.Client/Program.cs | 18 +++++++++-- Oqtane.Client/UI/Installer.razor | 21 +++++++++---- Oqtane.Server/Databases/LocalDbDatabase.cs | 16 ++++++++++ Oqtane.Server/Databases/SqlServerDatabase.cs | 17 ++++++++++ Oqtane.Server/Databases/SqliteDatabase.cs | 17 ++++++++++ .../DbContextOptionsBuilderExtensions.cs | 17 +++++----- .../OqtaneServiceCollectionExtensions.cs | 12 +++++++ .../Infrastructure/DatabaseManager.cs | 31 +++++++++++-------- .../02010001_AddDatabaseTypeColumnToTenant.cs | 2 +- .../Extensions/ColumnsBuilderExtensions.cs | 5 +-- .../Repository/Context/DBContextBase.cs | 2 -- Oqtane.Shared/Interfaces/IDatabase.cs | 13 ++++++++ Oqtane.Shared/Models/Database.cs | 9 ++++++ Oqtane.Shared/Oqtane.Shared.csproj | 1 + 14 files changed, 145 insertions(+), 36 deletions(-) create mode 100644 Oqtane.Server/Databases/LocalDbDatabase.cs create mode 100644 Oqtane.Server/Databases/SqlServerDatabase.cs create mode 100644 Oqtane.Server/Databases/SqliteDatabase.cs create mode 100644 Oqtane.Shared/Interfaces/IDatabase.cs create mode 100644 Oqtane.Shared/Models/Database.cs diff --git a/Oqtane.Client/Program.cs b/Oqtane.Client/Program.cs index 558b8290..ff57e0bf 100644 --- a/Oqtane.Client/Program.cs +++ b/Oqtane.Client/Program.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.DependencyInjection; using Microsoft.JSInterop; +using Oqtane.Interfaces; using Oqtane.Modules; using Oqtane.Providers; using Oqtane.Services; @@ -74,8 +75,8 @@ namespace Oqtane.Client var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies(); foreach (var assembly in assemblies) { - // dynamically register module services - var implementationTypes = assembly.GetInterfaces(); + // dynamically register module services + var implementationTypes = assembly.GetInterfaces(); foreach (var implementationType in implementationTypes) { if (implementationType.AssemblyQualifiedName != null) @@ -85,6 +86,17 @@ namespace Oqtane.Client } } + // dynamically register database providers + var databaseTypes = assembly.GetInterfaces(); + foreach (var databaseType in databaseTypes) + { + if (databaseType.AssemblyQualifiedName != null) + { + var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, Oqtane.Shared"); + builder.Services.AddScoped(serviceType ?? databaseType, databaseType); + } + } + // register client startup services var startUps = assembly.GetInstances(); foreach (var startup in startUps) @@ -115,7 +127,7 @@ namespace Oqtane.Client private static async Task LoadClientAssemblies(HttpClient http) { - // get list of loaded assemblies on the client + // get list of loaded assemblies on the client var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList(); // get assemblies from server and load into client app domain diff --git a/Oqtane.Client/UI/Installer.razor b/Oqtane.Client/UI/Installer.razor index 5983c253..8f140012 100644 --- a/Oqtane.Client/UI/Installer.razor +++ b/Oqtane.Client/UI/Installer.razor @@ -1,3 +1,4 @@ +@using Oqtane.Interfaces @namespace Oqtane.UI @inject NavigationManager NavigationManager @inject IInstallationService InstallationService @@ -5,6 +6,7 @@ @inject IUserService UserService @inject IJSRuntime JSRuntime @inject IStringLocalizer Localizer +@inject IEnumerable Databases
@@ -25,9 +27,12 @@ @@ -148,8 +153,6 @@ private string _hostEmail = string.Empty; private string _message = string.Empty; private string _integratedSecurityDisplay = "display: none;"; - private string _fileFieldsDisplay = "display: none;"; - private string _serverFieldsDisplay = "display: none;"; private string _loadingDisplay = "display: none;"; protected override async Task OnAfterRenderAsync(bool firstRender) @@ -176,10 +179,12 @@ StateHasChanged(); var connectionstring = ""; + var fullyQualifiedType = ""; switch (_databaseType) { case "LocalDB": connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;"; + fullyQualifiedType = "Oqtane.Repository.Databases.LocalDbDatabase, Oqtane.Server"; break; case "SQLServer": connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";"; @@ -191,9 +196,11 @@ { connectionstring += "User ID=" + _username + ";Password=" + _password; } + fullyQualifiedType = "Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server"; break; case "Sqlite": connectionstring = "Data Source=" + _fileName; + fullyQualifiedType = "Oqtane.Repository.Databases.SqliteDatabase, Oqtane.Server"; break; } @@ -201,7 +208,7 @@ var config = new InstallConfig { - DatabaseType = _databaseType, + DatabaseType = fullyQualifiedType, ConnectionString = connectionstring, Aliases = uri.Authority, HostEmail = _hostEmail, @@ -211,6 +218,8 @@ IsNewTenant = true, SiteName = Constants.DefaultSite }; + + var installation = await InstallationService.Install(config); if (installation.Success) diff --git a/Oqtane.Server/Databases/LocalDbDatabase.cs b/Oqtane.Server/Databases/LocalDbDatabase.cs new file mode 100644 index 00000000..0100c208 --- /dev/null +++ b/Oqtane.Server/Databases/LocalDbDatabase.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Oqtane.Interfaces; + +namespace Oqtane.Repository.Databases +{ + public class LocalDbDatabase : IDatabase + { + public string FriendlyName => "Local Database"; + public string Name => "LocalDB"; + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseSqlServer(connectionString); + } + } +} diff --git a/Oqtane.Server/Databases/SqlServerDatabase.cs b/Oqtane.Server/Databases/SqlServerDatabase.cs new file mode 100644 index 00000000..5b33d3cd --- /dev/null +++ b/Oqtane.Server/Databases/SqlServerDatabase.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Oqtane.Interfaces; + +namespace Oqtane.Repository.Databases +{ + public class SqlServerDatabase : IDatabase + { + public string FriendlyName => "SQL Server"; + + public string Name => "SqlServer"; + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseSqlServer(connectionString); + } + } +} diff --git a/Oqtane.Server/Databases/SqliteDatabase.cs b/Oqtane.Server/Databases/SqliteDatabase.cs new file mode 100644 index 00000000..4ac9a756 --- /dev/null +++ b/Oqtane.Server/Databases/SqliteDatabase.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Oqtane.Interfaces; + +namespace Oqtane.Repository.Databases +{ + public class SqliteDatabase : IDatabase + { + public string FriendlyName => Name; + + public string Name => "Sqlite"; + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseSqlite(connectionString); + } + } +} diff --git a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs index 485423a4..e9c53a1b 100644 --- a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs @@ -1,5 +1,10 @@ +using System; using System.Diagnostics.CodeAnalysis; +using System.Linq; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Oqtane.Interfaces; +// ReSharper disable ConvertToUsingDeclaration namespace Oqtane.Extensions { @@ -7,16 +12,10 @@ namespace Oqtane.Extensions { public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString) { - switch (databaseType) - { - case "SqlServer": - optionsBuilder.UseSqlServer(connectionString); + var type = Type.GetType(databaseType); + var database = Activator.CreateInstance(type) as IDatabase; - break; - case "Sqlite": - optionsBuilder.UseSqlite(connectionString); - break; - } + database.UseDatabase(optionsBuilder, connectionString); return optionsBuilder; } diff --git a/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs b/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs index 36c41601..bf1064b3 100644 --- a/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs +++ b/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.Loader; using Microsoft.Extensions.Hosting; using Oqtane.Infrastructure; +using Oqtane.Interfaces; using Oqtane.Modules; using Oqtane.Services; using Oqtane.Shared; @@ -46,6 +47,17 @@ namespace Microsoft.Extensions.DependencyInjection } } + // dynamically register database providers + var databaseTypes = assembly.GetInterfaces(); + foreach (var databaseType in databaseTypes) + { + if (databaseType.AssemblyQualifiedName != null) + { + var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, Oqtane.Shared"); + services.AddScoped(serviceType ?? databaseType, databaseType); + } + } + // dynamically register hosted services var serviceTypes = assembly.GetTypes(hostedServiceType); foreach (var serviceType in serviceTypes) diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs index 1d2a2799..f91da21d 100644 --- a/Oqtane.Server/Infrastructure/DatabaseManager.cs +++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs @@ -234,18 +234,18 @@ namespace Oqtane.Infrastructure if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases)) { - using (var db = new InstallationContext(install.DatabaseType, NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) + using (var db = GetInstallationContext()) { Tenant tenant; if (install.IsNewTenant) { tenant = new Tenant { Name = install.TenantName, - DBConnectionString = DenormalizeConnectionString(install.ConnectionString), - DBType = install.DatabaseType, - CreatedBy = "", - CreatedOn = DateTime.UtcNow, - ModifiedBy = "", - ModifiedOn = DateTime.UtcNow }; + DBConnectionString = DenormalizeConnectionString(install.ConnectionString), + DBType = install.DatabaseType, + CreatedBy = "", + CreatedOn = DateTime.UtcNow, + ModifiedBy = "", + ModifiedOn = DateTime.UtcNow }; db.Tenant.Add(tenant); db.SaveChanges(); _cache.Remove("tenants"); @@ -274,6 +274,14 @@ namespace Oqtane.Infrastructure return result; } + private InstallationContext GetInstallationContext() + { + var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; + var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); + + return new InstallationContext(databaseType, connectionString); + } + private Installation MigrateTenants(InstallConfig install) { var result = new Installation { Success = false, Message = string.Empty }; @@ -284,9 +292,7 @@ namespace Oqtane.Infrastructure { var upgrades = scope.ServiceProvider.GetRequiredService(); - var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; - var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); - using (var db = new InstallationContext(databaseType, connectionString)) + using (var db = GetInstallationContext()) { foreach (var tenant in db.Tenant.ToList()) { @@ -347,9 +353,8 @@ namespace Oqtane.Infrastructure if (moduleType != null) { var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; - var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); - using (var db = new InstallationContext(databaseType, connectionString)) { + using (var db = GetInstallationContext()) + { foreach (var tenant in db.Tenant.ToList()) { var index = Array.FindIndex(versions, item => item == moduleDefinition.Version); diff --git a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs index bfea92bd..9d76ada3 100644 --- a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs +++ b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs @@ -19,7 +19,7 @@ namespace Oqtane.Migrations migrationBuilder.Sql( @" UPDATE Tenant - SET DBType = 'SqlServer' + SET DBType = 'Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server' "); } diff --git a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs index 5c9a3a4e..ecd272db 100644 --- a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs +++ b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs @@ -9,8 +9,9 @@ namespace Oqtane.Migrations.Extensions public static OperationBuilder AddAutoIncrementColumn(this ColumnsBuilder table, string name) { return table.Column(name: name, nullable: false) - .Annotation("SqlServer:Identity", "1, 1") - .Annotation("Sqlite:Autoincrement", true); + .Annotation("SqlServer:Identity", "1, 1") + .Annotation("Sqlite:Autoincrement", true) + .Annotation("MySql:ValueGeneratedOnAdd", true); } public static OperationBuilder AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false) diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index 550665da..5ee8b6c1 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -1,12 +1,10 @@ using System; -using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; -using Oqtane.Models; using Oqtane.Shared; // ReSharper disable BuiltInTypeReferenceStyleForMemberAccess diff --git a/Oqtane.Shared/Interfaces/IDatabase.cs b/Oqtane.Shared/Interfaces/IDatabase.cs new file mode 100644 index 00000000..8a03d74b --- /dev/null +++ b/Oqtane.Shared/Interfaces/IDatabase.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; + +namespace Oqtane.Interfaces +{ + public interface IDatabase + { + public string FriendlyName { get; } + + public string Name { get; } + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); + } +} diff --git a/Oqtane.Shared/Models/Database.cs b/Oqtane.Shared/Models/Database.cs new file mode 100644 index 00000000..e1855242 --- /dev/null +++ b/Oqtane.Shared/Models/Database.cs @@ -0,0 +1,9 @@ +namespace Oqtane.Models +{ + public class Database + { + public string Name { get; set; } + + public string Type { get; set; } + } +} diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 0f973a79..44aaab47 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -18,6 +18,7 @@ + From 2fb63e81176a5556c87d100fc3a925eb185efbe9 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Sat, 27 Mar 2021 11:16:16 -0700 Subject: [PATCH 05/23] Added suuport to inject an IOqtaneDatabase in EntityBuilders to allow each Database to control certain Migration behaviors. Also updated Installer to dynamically build Database Configuration section --- Oqtane.Client/Program.cs | 2 +- Oqtane.Client/UI/Installer.razor | 148 ++++++------------ Oqtane.Database.MySQL/MySQLDatabase.cs | 66 ++++++++ .../Oqtane.Database.MySQL.csproj | 16 ++ .../Oqtane.Database.PostgreSQL.csproj | 18 +++ .../PostgreSQLDatabase.cs | 81 ++++++++++ .../Oqtane.Database.Sqlite.csproj | 15 ++ Oqtane.Database.Sqlite/SqliteDatabase.cs | 54 +++++++ .../Databases/Interfaces/IMultiDatabase.cs | 10 ++ Oqtane.Server/Databases/LocalDbDatabase.cs | 36 ++++- Oqtane.Server/Databases/SqlServerDatabase.cs | 62 ++++++-- .../Databases/SqlServerDatabaseBase.cs | 39 +++++ Oqtane.Server/Databases/SqliteDatabase.cs | 17 -- .../DbContextOptionsBuilderExtensions.cs | 12 +- .../OqtaneServiceCollectionExtensions.cs | 4 +- .../Infrastructure/DatabaseManager.cs | 132 ++++++++++------ .../Migrations/01000000_InitializeMaster.cs | 29 ++-- .../Migrations/01000000_InitializeTenant.cs | 74 +++++---- .../01000100_AddAdditionalIndexesInMaster.cs | 26 +-- .../01000100_AddAdditionalIndexesInTenant.cs | 29 ++-- ...000101_AddAdditionColumnToNotifications.cs | 12 +- .../Migrations/01000201_DropColumnFromPage.cs | 14 +- ...2000001_AddColumnToProfileAndUpdatePage.cs | 23 +-- .../02000101_UpdateIconColumnInPage.cs | 13 +- .../Migrations/02000102_AddLanguageTable.cs | 12 +- .../02000103_UpdatePageAndAddColumnToSite.cs | 16 +- ...2010000_AddIndexesForForeignKeyInMaster.cs | 16 +- .../02010001_AddDatabaseTypeColumnToTenant.cs | 21 ++- .../EntityBuilders/AliasEntityBuilder.cs | 5 +- .../AspNetUserClaimsEntityBuilder.cs | 5 +- .../AspNetUsersEntityBuilder.cs | 3 +- .../AuditableBaseEntityBuilder.cs | 3 +- .../EntityBuilders/BaseEntityBuilder.cs | 7 +- .../DeletableAuditableBaseEntityBuilder.cs | 3 +- .../DeletableBaseEntityBuilder.cs | 3 +- .../EntityBuilders/FileEntityBuilder.cs | 5 +- .../EntityBuilders/FolderEntityBuilder.cs | 5 +- .../EntityBuilders/JobEntityBuilder.cs | 5 +- .../EntityBuilders/JobLogEntityBuilder.cs | 5 +- .../EntityBuilders/LanguageEntityBuilder.cs | 5 +- .../EntityBuilders/LogEntityBuilder.cs | 5 +- .../ModuleDefinitionsEntityBuilder.cs | 5 +- .../EntityBuilders/ModuleEntityBuilder.cs | 5 +- .../NotificationEntityBuilder.cs | 5 +- .../EntityBuilders/PageEntityBuilder.cs | 14 +- .../EntityBuilders/PageModuleEntityBuilder.cs | 5 +- .../EntityBuilders/PermissionEntityBuilder.cs | 5 +- .../EntityBuilders/ProfileEntityBuilder.cs | 5 +- .../EntityBuilders/RoleEntityBuilder.cs | 5 +- .../EntityBuilders/SettingEntityBuilder.cs | 5 +- .../EntityBuilders/SiteEntityBuilder.cs | 5 +- .../EntityBuilders/TenantEntityBuilder.cs | 5 +- .../EntityBuilders/UserEntityBuilder.cs | 5 +- .../EntityBuilders/UserRoleEntityBuilder.cs | 5 +- .../Extensions/ColumnsBuilderExtensions.cs | 12 +- .../Framework/MultiDatabaseMigration.cs | 19 +++ .../MultiDatabaseMigrationsAssembly.cs | 45 ++++++ .../HtmlText/Manager/HtmlTextManager.cs | 13 +- .../Migrations/01000000_InitializeModule.cs | 13 +- .../EntityBuilders/HtmlTextEntityBuilder.cs | 5 +- .../HtmlText/Repository/HtmlTextContext.cs | 17 +- Oqtane.Server/Oqtane.Server.csproj | 4 +- .../Repository/Context/DBContextBase.cs | 20 ++- Oqtane.Server/Repository/Context/DbConfig.cs | 7 +- .../Repository/Context/InstallationContext.cs | 17 +- .../Repository/Context/MasterDBContext.cs | 26 ++- .../Repository/Context/TenantDBContext.cs | 20 +-- .../Repository/Interfaces/IDbConfig.cs | 5 + Oqtane.Server/Startup.cs | 8 +- Oqtane.Shared/Interfaces/IDatabase.cs | 13 -- Oqtane.Shared/Interfaces/IOqtaneDatabase.cs | 25 +++ Oqtane.Shared/Models/ConnectionStringField.cs | 11 ++ Oqtane.Shared/Oqtane.Shared.csproj | 7 + Oqtane.sln | 18 +++ 74 files changed, 1028 insertions(+), 407 deletions(-) create mode 100644 Oqtane.Database.MySQL/MySQLDatabase.cs create mode 100644 Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj create mode 100644 Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj create mode 100644 Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs create mode 100644 Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj create mode 100644 Oqtane.Database.Sqlite/SqliteDatabase.cs create mode 100644 Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs create mode 100644 Oqtane.Server/Databases/SqlServerDatabaseBase.cs delete mode 100644 Oqtane.Server/Databases/SqliteDatabase.cs create mode 100644 Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs create mode 100644 Oqtane.Server/Migrations/Framework/MultiDatabaseMigrationsAssembly.cs delete mode 100644 Oqtane.Shared/Interfaces/IDatabase.cs create mode 100644 Oqtane.Shared/Interfaces/IOqtaneDatabase.cs create mode 100644 Oqtane.Shared/Models/ConnectionStringField.cs diff --git a/Oqtane.Client/Program.cs b/Oqtane.Client/Program.cs index ff57e0bf..7418a201 100644 --- a/Oqtane.Client/Program.cs +++ b/Oqtane.Client/Program.cs @@ -87,7 +87,7 @@ namespace Oqtane.Client } // dynamically register database providers - var databaseTypes = assembly.GetInterfaces(); + var databaseTypes = assembly.GetInterfaces(); foreach (var databaseType in databaseTypes) { if (databaseType.AssemblyQualifiedName != null) diff --git a/Oqtane.Client/UI/Installer.razor b/Oqtane.Client/UI/Installer.razor index 8f140012..3c013711 100644 --- a/Oqtane.Client/UI/Installer.razor +++ b/Oqtane.Client/UI/Installer.razor @@ -1,4 +1,5 @@ @using Oqtane.Interfaces +@using System.Reflection @namespace Oqtane.UI @inject NavigationManager NavigationManager @inject IInstallationService InstallationService @@ -6,7 +7,7 @@ @inject IUserService UserService @inject IJSRuntime JSRuntime @inject IStringLocalizer Localizer -@inject IEnumerable Databases +@inject IEnumerable Databases
@@ -36,57 +37,50 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @{ + _selectedDatabase = Databases.Single(d => d.Name == _databaseType); + foreach (var field in _selectedDatabase.ConnectionStringFields) + { + if (field.Name != "IntegratedSecurity") + { + var isVisible = ""; + var fieldType = (field.Name == "Pwd") ? "password" : "text"; + if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" ) + { + var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity"); + if (intSecurityField != null) + { + isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : ""; + } + } + + field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm")); + + + + + + + + + + } + else + { + + + + + + + + + } + } + }
@@ -141,18 +135,13 @@
@code { + private IOqtaneDatabase _selectedDatabase; private string _databaseType = "LocalDB"; - private string _serverName = "(LocalDb)\\MSSQLLocalDB"; - private string _fileName = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm") + ".db"; - private string _databaseName = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm"); - private string _username = string.Empty; - private string _password = string.Empty; private string _hostUsername = UserNames.Host; private string _hostPassword = string.Empty; private string _confirmPassword = string.Empty; private string _hostEmail = string.Empty; private string _message = string.Empty; - private string _integratedSecurityDisplay = "display: none;"; private string _loadingDisplay = "display: none;"; protected override async Task OnAfterRenderAsync(bool firstRender) @@ -164,52 +153,21 @@ } } - private void SetIntegratedSecurity(ChangeEventArgs e) - { - _integratedSecurityDisplay = Convert.ToBoolean((string)e.Value) - ? "display: none;" - : string.Empty; - } - private async Task Install() { - if (((_serverName != "" && _databaseName != "") || _fileName !="") && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "") + var connectionString = _selectedDatabase.BuildConnectionString(); + + if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "") { _loadingDisplay = ""; StateHasChanged(); - var connectionstring = ""; - var fullyQualifiedType = ""; - switch (_databaseType) - { - case "LocalDB": - connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;"; - fullyQualifiedType = "Oqtane.Repository.Databases.LocalDbDatabase, Oqtane.Server"; - break; - case "SQLServer": - connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";"; - if (_integratedSecurityDisplay == "display: none;") - { - connectionstring += "Integrated Security=SSPI;"; - } - else - { - connectionstring += "User ID=" + _username + ";Password=" + _password; - } - fullyQualifiedType = "Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server"; - break; - case "Sqlite": - connectionstring = "Data Source=" + _fileName; - fullyQualifiedType = "Oqtane.Repository.Databases.SqliteDatabase, Oqtane.Server"; - break; - } - Uri uri = new Uri(NavigationManager.Uri); var config = new InstallConfig { - DatabaseType = fullyQualifiedType, - ConnectionString = connectionstring, + DatabaseType = _databaseType, + ConnectionString = connectionString, Aliases = uri.Authority, HostEmail = _hostEmail, HostPassword = _hostPassword, @@ -218,8 +176,6 @@ IsNewTenant = true, SiteName = Constants.DefaultSite }; - - var installation = await InstallationService.Install(config); if (installation.Success) diff --git a/Oqtane.Database.MySQL/MySQLDatabase.cs b/Oqtane.Database.MySQL/MySQLDatabase.cs new file mode 100644 index 00000000..5691e8c6 --- /dev/null +++ b/Oqtane.Database.MySQL/MySQLDatabase.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using MySql.EntityFrameworkCore.Metadata; +using Oqtane.Interfaces; +using Oqtane.Models; + +namespace Oqtane.Database.MySQL +{ + public class MySQLDatabase : IOqtaneDatabase + { + public MySQLDatabase() + { + ConnectionStringFields = new List() + { + new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1"}, + new() {Name = "Port", FriendlyName = "Port", Value = "3306"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, + new() {Name = "Pwd", FriendlyName = "Password", Value = ""} + }; + } + + public string FriendlyName => Name; + + public string Name => "MySQL"; + + public string Provider => "MySql.EntityFrameworkCore"; + + public List ConnectionStringFields { get; } + + public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + { + return table.Column(name: name, nullable: false).Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn); + } + + public string BuildConnectionString() + { + var connectionString = String.Empty; + + var server = ConnectionStringFields[0].Value; + var port = ConnectionStringFields[1].Value; + var database = ConnectionStringFields[2].Value; + var userId = ConnectionStringFields[3].Value; + var password = ConnectionStringFields[4].Value; + + if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password)) + { + connectionString = $"Server={server};Database={database};Uid={userId};Pwd={password};"; + } + + if (!String.IsNullOrEmpty(port)) + { + connectionString += $"Port={port};"; + } + return connectionString; + } + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseMySQL(connectionString); + } + } +} diff --git a/Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj b/Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj new file mode 100644 index 00000000..cc1cd306 --- /dev/null +++ b/Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj @@ -0,0 +1,16 @@ + + + + net5.0 + 9 + + + + + + + + + + + diff --git a/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj b/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj new file mode 100644 index 00000000..6f1c3507 --- /dev/null +++ b/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj @@ -0,0 +1,18 @@ + + + + 9 + net5.0 + + + + + + + + + + + + + diff --git a/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs new file mode 100644 index 00000000..9ba6ab63 --- /dev/null +++ b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; +using Oqtane.Models; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Oqtane.Database.PostgreSQL +{ + public class PostgreSQLDatabase : IOqtaneDatabase + { + + public PostgreSQLDatabase() + { + ConnectionStringFields = new List() + { + new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1"}, + new() {Name = "Port", FriendlyName = "Port", Value = "5432"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, + new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, + new() {Name = "Pwd", FriendlyName = "Password", Value = ""} + }; + } + + public string FriendlyName => Name; + + public string Name => "PostgreSQL"; + + public string Provider => "Npgsql.EntityFrameworkCore.PostgreSQL"; + + public List ConnectionStringFields { get; } + + public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + { + return table.Column(name: name, nullable: false).Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); + } + + public string BuildConnectionString() + { + var connectionString = String.Empty; + + var server = ConnectionStringFields[0].Value; + var port = ConnectionStringFields[1].Value; + var database = ConnectionStringFields[2].Value; + var integratedSecurity = Boolean.Parse(ConnectionStringFields[3].Value); + var userId = ConnectionStringFields[4].Value; + var password = ConnectionStringFields[5].Value; + + if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(port)) + { + connectionString = $"Server={server};Port={port};Database={database};"; + } + + if (integratedSecurity) + { + connectionString += "Integrated Security=true;"; + } + else + { + if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password)) + { + connectionString += $"User ID={userId};Password={password};"; + } + else + { + connectionString = String.Empty; + } + } + + return connectionString; + } + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseNpgsql(connectionString).UseSnakeCaseNamingConvention(); + } + } +} diff --git a/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj b/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj new file mode 100644 index 00000000..75f13dad --- /dev/null +++ b/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj @@ -0,0 +1,15 @@ + + + + net5.0 + + + + + + + + + + + diff --git a/Oqtane.Database.Sqlite/SqliteDatabase.cs b/Oqtane.Database.Sqlite/SqliteDatabase.cs new file mode 100644 index 00000000..62873409 --- /dev/null +++ b/Oqtane.Database.Sqlite/SqliteDatabase.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; +using Oqtane.Models; + +namespace Oqtane.Repository.Databases +{ + public class SqliteDatabase : IOqtaneDatabase + { + public SqliteDatabase() + { + ConnectionStringFields = new List() + { + new() {Name = "Server", FriendlyName = "File Name", Value = "Oqtane-{{Date}}.db"} + }; + } + + public string FriendlyName => Name; + + public string Name => "Sqlite"; + + public string Provider => "Microsoft.EntityFrameworkCore.Sqlite"; + + public List ConnectionStringFields { get; } + + public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + { + return table.Column(name: name, nullable: false).Annotation("Sqlite:Autoincrement", true); + } + + public string BuildConnectionString() + { + var connectionstring = String.Empty; + + var server = ConnectionStringFields[0].Value; + + if (!String.IsNullOrEmpty(server)) + { + connectionstring = $"Data Source={server};"; + } + + return connectionstring; + } + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseSqlite(connectionString); + } + } +} diff --git a/Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs b/Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs new file mode 100644 index 00000000..103cd76b --- /dev/null +++ b/Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Oqtane.Interfaces; + +namespace Oqtane.Repository.Databases.Interfaces +{ + public interface IMultiDatabase + { + public IEnumerable Databases { get; } + } +} diff --git a/Oqtane.Server/Databases/LocalDbDatabase.cs b/Oqtane.Server/Databases/LocalDbDatabase.cs index 0100c208..a0e0580d 100644 --- a/Oqtane.Server/Databases/LocalDbDatabase.cs +++ b/Oqtane.Server/Databases/LocalDbDatabase.cs @@ -1,16 +1,36 @@ -using Microsoft.EntityFrameworkCore; -using Oqtane.Interfaces; +using System; +using System.Collections.Generic; +using Oqtane.Models; +using Oqtane.Repository.Databases; -namespace Oqtane.Repository.Databases +namespace Oqtane.Databases { - public class LocalDbDatabase : IDatabase + public class LocalDbDatabase : SqlServerDatabaseBase { - public string FriendlyName => "Local Database"; - public string Name => "LocalDB"; + private static string _friendlyName => "Local Database"; + private static string _name => "LocalDB"; - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + private static readonly List _connectionStringFields = new() { - return optionsBuilder.UseSqlServer(connectionString); + new() {Name = "Server", FriendlyName = "Server", Value = "(LocalDb)\\MSSQLLocalDB"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"} + }; + + public LocalDbDatabase() :base(_name, _friendlyName, _connectionStringFields) { } + + public override string BuildConnectionString() + { + var connectionString = String.Empty; + + var server = ConnectionStringFields[0].Value; + var database = ConnectionStringFields[1].Value; + + if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database)) + { + connectionString = $"Data Source={server};AttachDbFilename=|DataDirectory|\\{database}.mdf;Initial Catalog={database};Integrated Security=SSPI;"; + } + + return connectionString; } } } diff --git a/Oqtane.Server/Databases/SqlServerDatabase.cs b/Oqtane.Server/Databases/SqlServerDatabase.cs index 5b33d3cd..d7d885c5 100644 --- a/Oqtane.Server/Databases/SqlServerDatabase.cs +++ b/Oqtane.Server/Databases/SqlServerDatabase.cs @@ -1,17 +1,61 @@ -using Microsoft.EntityFrameworkCore; -using Oqtane.Interfaces; +using System; +using System.Collections.Generic; +using Oqtane.Models; +using Oqtane.Repository.Databases; -namespace Oqtane.Repository.Databases +// ReSharper disable ArrangeObjectCreationWhenTypeNotEvident + +namespace Oqtane.Databases { - public class SqlServerDatabase : IDatabase + public class SqlServerDatabase : SqlServerDatabaseBase { - public string FriendlyName => "SQL Server"; + private static string _friendlyName => "SQL Server"; + private static string _name => "SqlServer"; - public string Name => "SqlServer"; - - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + private static readonly List _connectionStringFields = new() { - return optionsBuilder.UseSqlServer(connectionString); + new() {Name = "Server", FriendlyName = "Server", Value = "."}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, + new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, + new() {Name = "Pwd", FriendlyName = "Password", Value = ""} + }; + + public SqlServerDatabase() :base(_name, _friendlyName, _connectionStringFields) { } + + public override string BuildConnectionString() + { + var connectionString = String.Empty; + + var server = ConnectionStringFields[0].Value; + var database = ConnectionStringFields[1].Value; + var integratedSecurity = Boolean.Parse(ConnectionStringFields[2].Value); + var userId = ConnectionStringFields[3].Value; + var password = ConnectionStringFields[4].Value; + + if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database)) + { + connectionString = $"Data Source={server};Initial Catalog={database};"; + } + + if (integratedSecurity) + { + connectionString += "Integrated Security=SSPI;"; + } + else + { + if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password)) + { + connectionString += $"User ID={userId};Password={password};"; + } + else + { + connectionString = String.Empty; + } + } + + return connectionString; + } } } diff --git a/Oqtane.Server/Databases/SqlServerDatabaseBase.cs b/Oqtane.Server/Databases/SqlServerDatabaseBase.cs new file mode 100644 index 00000000..151f6837 --- /dev/null +++ b/Oqtane.Server/Databases/SqlServerDatabaseBase.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; +using Oqtane.Models; + +namespace Oqtane.Repository.Databases +{ + public abstract class SqlServerDatabaseBase : IOqtaneDatabase + { + protected SqlServerDatabaseBase(string name, string friendlyName, List connectionStringFields) + { + Name = name; + FriendlyName = friendlyName; + ConnectionStringFields = connectionStringFields; + } + + public string FriendlyName { get; } + + public string Name { get; } + + public string Provider => "Microsoft.EntityFrameworkCore.SqlServer"; + + public List ConnectionStringFields { get; } + + public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + { + return table.Column(name: name, nullable: false).Annotation("SqlServer:Identity", "1, 1"); + } + + public abstract string BuildConnectionString(); + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + { + return optionsBuilder.UseSqlServer(connectionString); + } + } +} diff --git a/Oqtane.Server/Databases/SqliteDatabase.cs b/Oqtane.Server/Databases/SqliteDatabase.cs deleted file mode 100644 index 4ac9a756..00000000 --- a/Oqtane.Server/Databases/SqliteDatabase.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Oqtane.Interfaces; - -namespace Oqtane.Repository.Databases -{ - public class SqliteDatabase : IDatabase - { - public string FriendlyName => Name; - - public string Name => "Sqlite"; - - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) - { - return optionsBuilder.UseSqlite(connectionString); - } - } -} diff --git a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs index e9c53a1b..41aa1de8 100644 --- a/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/DbContextOptionsBuilderExtensions.cs @@ -1,8 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.Linq; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; using Oqtane.Interfaces; // ReSharper disable ConvertToUsingDeclaration @@ -10,14 +8,22 @@ namespace Oqtane.Extensions { public static class DbContextOptionsBuilderExtensions { + public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, IOqtaneDatabase database, string connectionString) + { + database.UseDatabase(optionsBuilder, connectionString); + + return optionsBuilder; + } + public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString) { var type = Type.GetType(databaseType); - var database = Activator.CreateInstance(type) as IDatabase; + var database = Activator.CreateInstance(type) as IOqtaneDatabase; database.UseDatabase(optionsBuilder, connectionString); return optionsBuilder; } + } } diff --git a/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs b/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs index bf1064b3..68306de5 100644 --- a/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs +++ b/Oqtane.Server/Extensions/OqtaneServiceCollectionExtensions.cs @@ -48,12 +48,12 @@ namespace Microsoft.Extensions.DependencyInjection } // dynamically register database providers - var databaseTypes = assembly.GetInterfaces(); + var databaseTypes = assembly.GetInterfaces(); foreach (var databaseType in databaseTypes) { if (databaseType.AssemblyQualifiedName != null) { - var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, Oqtane.Shared"); + var serviceType = Type.GetType("Oqtane.Interfaces.IOqtaneDatabase, Oqtane.Shared"); services.AddScoped(serviceType ?? databaseType, databaseType); } } diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs index f91da21d..bad8c272 100644 --- a/Oqtane.Server/Infrastructure/DatabaseManager.cs +++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs @@ -13,6 +13,7 @@ using Oqtane.Models; using Oqtane.Repository; using Oqtane.Shared; using Oqtane.Enums; +using Oqtane.Interfaces; using File = System.IO.File; // ReSharper disable MemberCanBePrivate.Global @@ -172,11 +173,16 @@ namespace Oqtane.Infrastructure var connectionString = NormalizeConnectionString(install.ConnectionString); var databaseType = install.DatabaseType; - using (var dbc = new DbContext(new DbContextOptionsBuilder().UseOqtaneDatabase(databaseType, connectionString).Options)) + using (var scope = _serviceScopeFactory.CreateScope()) { - // create empty database if it does not exist - dbc.Database.EnsureCreated(); - result.Success = true; + var databases = scope.ServiceProvider.GetServices(); + + using (var dbc = new DbContext(new DbContextOptionsBuilder().UseOqtaneDatabase(databases.Single(d => d.Name == databaseType), connectionString).Options)) + { + // create empty database if it does not exist + dbc.Database.EnsureCreated(); + result.Success = true; + } } } catch (Exception ex) @@ -198,26 +204,31 @@ namespace Oqtane.Infrastructure if (install.TenantName == TenantNames.Master) { - try + using (var scope = _serviceScopeFactory.CreateScope()) { - var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; + var databases = scope.ServiceProvider.GetServices(); - using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) + try { - // Push latest model into database - masterDbContext.Database.Migrate(); - result.Success = true; - } - } - catch (Exception ex) - { - result.Message = ex.Message; - } + var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; - if (result.Success) - { - UpdateConnectionString(install.ConnectionString); - UpdateDatabaseType(install.DatabaseType); + using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) + { + // Push latest model into database + masterDbContext.Database.Migrate(); + result.Success = true; + } + } + catch (Exception ex) + { + result.Message = ex.Message; + } + + if (result.Success) + { + UpdateConnectionString(install.ConnectionString); + UpdateDatabaseType(install.DatabaseType); + } } } else @@ -234,38 +245,56 @@ namespace Oqtane.Infrastructure if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases)) { - using (var db = GetInstallationContext()) + using (var scope = _serviceScopeFactory.CreateScope()) { - Tenant tenant; - if (install.IsNewTenant) - { - tenant = new Tenant { Name = install.TenantName, - DBConnectionString = DenormalizeConnectionString(install.ConnectionString), - DBType = install.DatabaseType, - CreatedBy = "", - CreatedOn = DateTime.UtcNow, - ModifiedBy = "", - ModifiedOn = DateTime.UtcNow }; - db.Tenant.Add(tenant); - db.SaveChanges(); - _cache.Remove("tenants"); - } - else - { - tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName); - } + var databases = scope.ServiceProvider.GetServices(); - foreach (var aliasName in install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + using (var db = GetInstallationContext(databases)) { - if (tenant != null) + Tenant tenant; + if (install.IsNewTenant) { - var alias = new Alias { Name = aliasName, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; - db.Alias.Add(alias); + tenant = new Tenant + { + Name = install.TenantName, + DBConnectionString = DenormalizeConnectionString(install.ConnectionString), + DBType = install.DatabaseType, + CreatedBy = "", + CreatedOn = DateTime.UtcNow, + ModifiedBy = "", + ModifiedOn = DateTime.UtcNow + }; + db.Tenant.Add(tenant); + db.SaveChanges(); + _cache.Remove("tenants"); + } + else + { + tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName); } - db.SaveChanges(); + foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) + { + if (tenant != null) + { + var alias = new Alias + { + Name = aliasName, + TenantId = tenant.TenantId, + SiteId = -1, + CreatedBy = "", + CreatedOn = DateTime.UtcNow, + ModifiedBy = "", + ModifiedOn = DateTime.UtcNow + }; + db.Alias.Add(alias); + } + + db.SaveChanges(); + } + + _cache.Remove("aliases"); } - _cache.Remove("aliases"); } } @@ -274,12 +303,12 @@ namespace Oqtane.Infrastructure return result; } - private InstallationContext GetInstallationContext() + private InstallationContext GetInstallationContext(IEnumerable databases) { var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); - return new InstallationContext(databaseType, connectionString); + return new InstallationContext(databases.Single(d => d.Name == databaseType), connectionString); } private Installation MigrateTenants(InstallConfig install) @@ -291,14 +320,15 @@ namespace Oqtane.Infrastructure using (var scope = _serviceScopeFactory.CreateScope()) { var upgrades = scope.ServiceProvider.GetRequiredService(); + var databases = scope.ServiceProvider.GetServices(); - using (var db = GetInstallationContext()) + using (var db = GetInstallationContext(databases)) { foreach (var tenant in db.Tenant.ToList()) { try { - var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; + var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; using (var tenantDbContext = new TenantDBContext(dbConfig, null)) { // Push latest model into database @@ -345,6 +375,8 @@ namespace Oqtane.Infrastructure { var moduleDefinitions = scope.ServiceProvider.GetRequiredService(); var sql = scope.ServiceProvider.GetRequiredService(); + var databases = scope.ServiceProvider.GetServices(); + foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions()) { if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduleDefinition.ServerManagerType)) @@ -353,7 +385,7 @@ namespace Oqtane.Infrastructure if (moduleType != null) { var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - using (var db = GetInstallationContext()) + using (var db = GetInstallationContext(databases)) { foreach (var tenant in db.Tenant.ToList()) { diff --git a/Oqtane.Server/Migrations/01000000_InitializeMaster.cs b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs index 0465e058..064cda71 100644 --- a/Oqtane.Server/Migrations/01000000_InitializeMaster.cs +++ b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Migrations.Extensions; using Oqtane.Repository; @@ -9,52 +11,57 @@ namespace Oqtane.Migrations { [DbContext(typeof(MasterDBContext))] [Migration("Master.01.00.00.00")] - public class InitializeMaster : Migration + public class InitializeMaster : MultiDatabaseMigration { + public InitializeMaster(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Create Tenant table - var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase); tenantEntityBuilder.Create(); //Create Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.Create(); //Create ModuleDefinitions Table - var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase); moduleDefinitionsEntityBuilder.Create(); //Create Job Table - var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase); jobEntityBuilder.Create(); //Create JobLog Table - var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase); jobLogEntityBuilder.Create(); } protected override void Down(MigrationBuilder migrationBuilder) { //Drop Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.Drop(); //Drop JobLog Table - var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase); jobLogEntityBuilder.Drop(); //Drop Tenant table - var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase); tenantEntityBuilder.Drop(); //Drop ModuleDefinitions Table - var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase); moduleDefinitionsEntityBuilder.Drop(); //Drop Job Table - var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase); jobEntityBuilder.Drop(); } + } } diff --git a/Oqtane.Server/Migrations/01000000_InitializeTenant.cs b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs index fe1b8b1e..4d8817fa 100644 --- a/Oqtane.Server/Migrations/01000000_InitializeTenant.cs +++ b/Oqtane.Server/Migrations/01000000_InitializeTenant.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -8,86 +10,90 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.01.00.00.00")] - public class InitializeTenant : Migration + public class InitializeTenant : MultiDatabaseMigration { + public InitializeTenant(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Create Site table - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.Create(); //Create Page table - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.Create(); pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); //Add Column to Page table (for Sql Server only) we will drop it later for Sql Server only - if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer") + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { pageEntityBuilder.AddBooleanColumn("EditMode"); } //Create Module table - var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder); + var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder, ActiveDatabase); moduleEntityBuilder.Create(); //Create PageModule table - var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder); + var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase); pageModuleEntityBuilder.Create(); //Create User table - var userEntityBuilder = new UserEntityBuilder(migrationBuilder); + var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase); userEntityBuilder.Create(); userEntityBuilder.AddIndex("IX_User", "Username", true); //Create Role table - var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase); roleEntityBuilder.Create(); //Create UserRole table - var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder); + var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder, ActiveDatabase); userRoleEntityBuilder.Create(); userRoleEntityBuilder.AddIndex("IX_UserRole", new [] {"RoleId", "UserId"}, true); //Create Permission table - var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder); + var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder, ActiveDatabase); permissionEntityBuilder.Create(); permissionEntityBuilder.AddIndex("IX_Permission", new [] {"SiteId", "EntityName", "EntityId", "PermissionName", "RoleId", "UserId"}, true); //Create Setting table - var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder); + var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase); settingEntityBuilder.Create(); settingEntityBuilder.AddIndex("IX_Setting", new [] {"EntityName", "EntityId", "SettingName"}, true); //Create Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.Create(); //Create Log table - var logEntityBuilder = new LogEntityBuilder(migrationBuilder); + var logEntityBuilder = new LogEntityBuilder(migrationBuilder, ActiveDatabase); logEntityBuilder.Create(); //Create Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.Create(); //Create Folder table - var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder); + var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase); folderEntityBuilder.Create(); folderEntityBuilder.AddIndex("IX_Folder", new [] {"SiteId", "Path"}, true); //Create File table - var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase); fileEntityBuilder.Create(); //Create AspNetUsers table - var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder); + var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder, ActiveDatabase); aspNetUsersEntityBuilder.Create(); aspNetUsersEntityBuilder.AddIndex("EmailIndex", "NormalizedEmail", true); aspNetUsersEntityBuilder.AddIndex("UserNameIndex", "NormalizedUserName", true); //Create AspNetUserClaims table - var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder); + var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder, ActiveDatabase); aspNetUserClaimsEntityBuilder.Create(); aspNetUserClaimsEntityBuilder.AddIndex("IX_AspNetUserClaims_UserId", "UserId", true); @@ -96,67 +102,67 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Drop AspNetUserClaims table - var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder); + var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder, ActiveDatabase); aspNetUserClaimsEntityBuilder.Drop(); //Drop AspNetUsers table - var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder); + var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder, ActiveDatabase); aspNetUsersEntityBuilder.Drop(); //Drop File table - var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase); fileEntityBuilder.Drop(); //Drop Folder table - var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder); + var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase); folderEntityBuilder.Drop(); //Drop Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.Drop(); //Drop Log table - var logEntityBuilder = new LogEntityBuilder(migrationBuilder); + var logEntityBuilder = new LogEntityBuilder(migrationBuilder, ActiveDatabase); logEntityBuilder.Drop(); //Drop Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.Drop(); //Drop Setting table - var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder); + var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase); settingEntityBuilder.Drop(); //Drop Permission table - var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder); + var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder, ActiveDatabase); permissionEntityBuilder.Drop(); //Drop UserRole table - var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder); + var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder, ActiveDatabase); userRoleEntityBuilder.Drop(); //Drop Role table - var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase); roleEntityBuilder.Drop(); //Drop User table - var userEntityBuilder = new UserEntityBuilder(migrationBuilder); + var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase); userEntityBuilder.Drop(); //Drop PageModule table - var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder); + var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase); pageModuleEntityBuilder.Drop(); //Drop Module table - var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder); + var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder, ActiveDatabase); moduleEntityBuilder.Drop(); //Drop Page table - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.Drop(); //Drop Site table - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.Drop(); } } diff --git a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs index 7257bbb1..a1ab6525 100644 --- a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs +++ b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInMaster.cs @@ -1,5 +1,7 @@ -using Microsoft.EntityFrameworkCore.Infrastructure; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,43 +9,47 @@ namespace Oqtane.Migrations { [DbContext(typeof(MasterDBContext))] [Migration("Master.01.00.01.00")] - public class AddAdditionalIndexesInMaster : Migration + public class AddAdditionalIndexesInMaster : MultiDatabaseMigration { + public AddAdditionalIndexesInMaster(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Update Tenant table - var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase); tenantEntityBuilder.AddIndex("IX_Tenant", "Name"); //Update Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.AddIndex("IX_Alias", "Name"); //Update ModuleDefinitions Table - var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase); moduleDefinitionsEntityBuilder.AddIndex("IX_ModuleDefinition", "ModuleDefinitionName"); //Update Job Table - var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase); jobEntityBuilder.AddIndex("IX_Job", "JobType"); } protected override void Down(MigrationBuilder migrationBuilder) { //Update Tenant table - var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase); tenantEntityBuilder.DropIndex("IX_Tenant"); //Update Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.DropIndex("IX_Alias"); //Update ModuleDefinitions Table - var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder); + var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase); moduleDefinitionsEntityBuilder.DropIndex("IX_ModuleDefinition"); //Update Job Table - var jobEntityBuilder = new JobEntityBuilder(migrationBuilder); + var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase); jobEntityBuilder.DropIndex("IX_Job"); } } diff --git a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs index 158c8b0f..3801cc3e 100644 --- a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs +++ b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Migrations.Extensions; using Oqtane.Repository; @@ -8,28 +10,32 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.01.00.01.00")] - public class AddAdditionalIndexesInTenant : Migration + public class AddAdditionalIndexesInTenant : MultiDatabaseMigration { + public AddAdditionalIndexesInTenant(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Create Index on Site - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.AddIndex("IX_Site", new [] {"TenantId", "Name"}, true); //Create Index on Role table - var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase); roleEntityBuilder.AddIndex("IX_Role", new [] {"SiteId", "Name"}, true); //Create Index on Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.AddIndex("IX_Profile", new [] {"SiteId", "Name"}, true); //Create Index on File table - var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase); fileEntityBuilder.AddIndex("IX_File", new [] {"FolderId", "Name"}, true); //Add Columns to Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.AddStringColumn("FromDisplayName", 50, true); notificationEntityBuilder.AddStringColumn("FromEmail", 256, true); notificationEntityBuilder.AddStringColumn("ToDisplayName", 50, true); @@ -38,27 +44,26 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Drop Index on Site table - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.DropIndex("IX_Site"); //Drop Index on Role table - var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder); + var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase); roleEntityBuilder.DropIndex("IX_Role"); //Drop Index on Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.DropIndex("IX_Profile"); //Drop Index on File table - var fileEntityBuilder = new FileEntityBuilder(migrationBuilder); + var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase); fileEntityBuilder.DropIndex("IX_File"); //Drop Columns from Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.DropColumn("FromDisplayName"); notificationEntityBuilder.DropColumn("FromEmail"); notificationEntityBuilder.DropColumn("ToDisplayName"); } - } } diff --git a/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs index 7d01d0b0..1de51146 100644 --- a/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs +++ b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,12 +9,16 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.01.00.01.01")] - public class AddAdditionColumnToNotifications : Migration + public class AddAdditionColumnToNotifications : MultiDatabaseMigration { + public AddAdditionColumnToNotifications(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Add Column to Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.AddDateTimeColumn("SendOn", true); migrationBuilder.Sql( @@ -26,7 +32,7 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Drop Column from Notification table - var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder); + var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.DropColumn("SendOn"); } } diff --git a/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs index 9ee79ff7..5f5fee65 100644 --- a/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs +++ b/Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,14 +9,18 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.01.00.02.01")] - public class DropColumnFromPage : Migration + public class DropColumnFromPage : MultiDatabaseMigration { + public DropColumnFromPage(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Drop Column from Page table - if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer") + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.DropColumn("EditMode"); } } @@ -22,7 +28,7 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Add Column to Page table - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.AddBooleanColumn("EditMode"); } } diff --git a/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs index 79555898..6546e71a 100644 --- a/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs +++ b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,25 +9,28 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.02.00.00.01")] - public class AddColumnToProfileAndUpdatePage : Migration + public class AddColumnToProfileAndUpdatePage : MultiDatabaseMigration { + public AddColumnToProfileAndUpdatePage(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Add Column to Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.AddStringColumn("Options", 2000, true); - ///Update new field migrationBuilder.Sql( @" UPDATE Profile SET Options = '' "); - //Alter Column in Page table - if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + //Alter Column in Page table for Sql Server + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.DropIndex("IX_Page"); pageEntityBuilder.AlterStringColumn("Path", 256); pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); @@ -35,13 +40,13 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Drop Column from Profile table - var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder); + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.DropColumn("Options"); //Alter Column in Page table - if (migrationBuilder.ActiveProvider != "Microsoft.EntityFrameworkCore.Sqlite") + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { - var pageEntityBuilder = new PageEntityBuilder(migrationBuilder); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.DropIndex("IX_Page"); pageEntityBuilder.AlterStringColumn("Path", 50); pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true); diff --git a/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs index d62220ea..2b3a9e77 100644 --- a/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs +++ b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs @@ -1,20 +1,27 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Repository; namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.02.00.01.01")] - public class UpdateIconColumnInPage : Migration + public class UpdateIconColumnInPage : MultiDatabaseMigration { + public UpdateIconColumnInPage(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { ///Update Icon Field in Page migrationBuilder.Sql( @" - UPDATE [Page] - SET Icon = IIF(Icon <> '', 'oi oi-' + Icon, ''); + UPDATE Page + SET Icon = 'oi oi-' + Icon + WHERE Icon <> '' "); } } diff --git a/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs b/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs index 21514c31..0fa1b490 100644 --- a/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs +++ b/Oqtane.Server/Migrations/02000102_AddLanguageTable.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,19 +9,23 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.02.00.01.02")] - public class AddLanguageTable : Migration + public class AddLanguageTable : MultiDatabaseMigration { + public AddLanguageTable(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Create Language table - var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder); + var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder, ActiveDatabase); languageEntityBuilder.Create(); } protected override void Down(MigrationBuilder migrationBuilder) { //Drop Language table - var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder); + var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder, ActiveDatabase); languageEntityBuilder.Drop(); } } diff --git a/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs index 3b098e3a..041f407a 100644 --- a/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs +++ b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,12 +9,16 @@ namespace Oqtane.Migrations { [DbContext(typeof(TenantDBContext))] [Migration("Tenant.02.00.01.03")] - public class UpdatePageAndAddColumnToSite : Migration + public class UpdatePageAndAddColumnToSite : MultiDatabaseMigration { + public UpdatePageAndAddColumnToSite(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Add Column to Site table - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.AddStringColumn("AdminContainerType", 200, true); //Update new column @@ -25,8 +31,8 @@ namespace Oqtane.Migrations //Delete records from Page migrationBuilder.Sql( @" - DELETE FROM [Page] - WHERE Path = 'admin/tenants'; + DELETE FROM Page + WHERE Path = 'admin/tenants' "); } @@ -34,7 +40,7 @@ namespace Oqtane.Migrations protected override void Down(MigrationBuilder migrationBuilder) { //Drop Column from Site table - var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder); + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); siteEntityBuilder.DropColumn("AdminContainerType"); } } diff --git a/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs b/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs index bbbeb06c..5828f962 100644 --- a/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs +++ b/Oqtane.Server/Migrations/02010000_AddIndexesForForeignKeyInMaster.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,27 +9,31 @@ namespace Oqtane.Migrations { [DbContext(typeof(MasterDBContext))] [Migration("Master.02.01.00.00")] - public class AddIndexesForForeignKeyInMaster : Migration + public class AddIndexesForForeignKeyInMaster : MultiDatabaseMigration { + public AddIndexesForForeignKeyInMaster(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Update JobLog table - var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase); jobLogEntityBuilder.AddIndex("IX_JobLog_JobId", "JobId"); //Update Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.AddIndex("IX_Alias_TenantId", "TenantId"); } protected override void Down(MigrationBuilder migrationBuilder) { //Update JobLog table - var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder); + var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase); jobLogEntityBuilder.DropIndex("IX_JobLog_JobId"); //Update Alias table - var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder); + var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase); aliasEntityBuilder.DropIndex("IX_Alias_TenantId"); } } diff --git a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs index 9d76ada3..388e95d5 100644 --- a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs +++ b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; @@ -7,21 +9,28 @@ namespace Oqtane.Migrations { [DbContext(typeof(MasterDBContext))] [Migration("Master.02.01.00.01")] - public class AddDatabaseTypeColumnToTenant : Migration + public class AddDatabaseTypeColumnToTenant : MultiDatabaseMigration { + public AddDatabaseTypeColumnToTenant(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Add Column to Site table - var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder); + var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase); tenantEntityBuilder.AddStringColumn("DBType", 200, true); - //Update new column - migrationBuilder.Sql( - @" + //Update new column if SqlServer (Other Databases will not have any records yet) + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") + { + migrationBuilder.Sql(@" UPDATE Tenant - SET DBType = 'Oqtane.Repository.Databases.SqlServerDatabase, Oqtane.Server' + SET DBType = 'SqlServer' "); + } + } } } diff --git a/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs index fad6bd1a..d2d35188 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Alias", x => x.AliasId); private readonly ForeignKey _tenantForeignKey = new("FK_Alias_Tenant", x => x.TenantId, "Tenant", "TenantId", ReferentialAction.Cascade); - public AliasEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public AliasEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override AliasEntityBuilder BuildTable(ColumnsBuilder table) { - AliasId = table.AddAutoIncrementColumn("AliasId"); + AliasId = ActiveDatabase.AddAutoIncrementColumn(table,"AliasId"); Name = table.AddStringColumn("Name", 200); TenantId = table.AddIntegerColumn("TenantId"); SiteId = table.AddIntegerColumn("SiteId"); diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs index a99c9067..1a6fffce 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_AspNetUserClaims", x => x.Id); private readonly ForeignKey _aspNetUsersForeignKey = new("FK_AspNetUserClaims_AspNetUsers_UserId", x => x.UserId, "AspNetUsers", "Id", ReferentialAction.Cascade); - public AspNetUserClaimsEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public AspNetUserClaimsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override AspNetUserClaimsEntityBuilder BuildTable(ColumnsBuilder table) { - Id = table.AddAutoIncrementColumn("Id"); + Id = ActiveDatabase.AddAutoIncrementColumn(table,"Id"); UserId = table.AddStringColumn("UserId", 450); ClaimType = table.AddMaxStringColumn("ClaimType", true); ClaimValue = table.AddMaxStringColumn("ClaimValue", true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs index e6ac3b45..9a071297 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "AspNetUsers"; private readonly PrimaryKey _primaryKey = new("PK_AspNetUsers", x => x.Id); - public AspNetUsersEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public AspNetUsersEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; diff --git a/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs index 9f805d6e..f92bffcc 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -10,7 +11,7 @@ namespace Oqtane.Migrations.EntityBuilders { public abstract class AuditableBaseEntityBuilder : BaseEntityBuilder where TEntityBuilder : BaseEntityBuilder { - protected AuditableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base (migrationBuilder) + protected AuditableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base (migrationBuilder, database) { } diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs index d58a88a2..078c74a7 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; namespace Oqtane.Migrations.EntityBuilders @@ -10,9 +11,10 @@ namespace Oqtane.Migrations.EntityBuilders { private readonly MigrationBuilder _migrationBuilder; - protected BaseEntityBuilder(MigrationBuilder migrationBuilder) + protected BaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) { _migrationBuilder = migrationBuilder; + ActiveDatabase = database; ForeignKeys = new List>(); } @@ -23,9 +25,10 @@ namespace Oqtane.Migrations.EntityBuilders { table.AddForeignKey(foreignKey); } - } + protected IOqtaneDatabase ActiveDatabase { get; } + protected abstract TEntityBuilder BuildTable(ColumnsBuilder table); protected string EntityTableName { get; init; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs index 81cdd9e6..e5bfac03 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -10,7 +11,7 @@ namespace Oqtane.Migrations.EntityBuilders { public abstract class DeletableAuditableBaseEntityBuilder : AuditableBaseEntityBuilder where TEntityBuilder : BaseEntityBuilder { - protected DeletableAuditableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + protected DeletableAuditableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { } diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs index c9bba190..0fe98b66 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs @@ -2,6 +2,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global @@ -10,7 +11,7 @@ namespace Oqtane.Migrations.EntityBuilders { public abstract class DeletableBaseEntityBuilder : BaseEntityBuilder where TEntityBuilder : BaseEntityBuilder { - protected DeletableBaseEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + protected DeletableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { } diff --git a/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs index 695935a1..3eb95051 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_File", x => x.FileId); private readonly ForeignKey _folderForeignKey = new("FK_File_Folder", x => x.FolderId, "Folder", "FolderId", ReferentialAction.Cascade); - public FileEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public FileEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override FileEntityBuilder BuildTable(ColumnsBuilder table) { - FileId = table.AddAutoIncrementColumn("FileId"); + FileId = ActiveDatabase.AddAutoIncrementColumn(table,"FileId"); FolderId = table.AddIntegerColumn("FolderId"); Name = table.AddStringColumn("Name", 50); Extension = table.AddStringColumn("Extension", 50); diff --git a/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs index d7d5f63d..8da9514e 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Folder", x => x.FolderId); private readonly ForeignKey _siteForeignKey = new("FK_Folder_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public FolderEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public FolderEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override FolderEntityBuilder BuildTable(ColumnsBuilder table) { - FolderId = table.AddAutoIncrementColumn("FolderId"); + FolderId = ActiveDatabase.AddAutoIncrementColumn(table,"FolderId"); SiteId = table.AddIntegerColumn("SiteId"); ParentId = table.AddIntegerColumn("ParentId", true); Name = table.AddStringColumn("Name", 50); diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs index 1cdda817..066468ef 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "Job"; private readonly PrimaryKey _primaryKey = new("PK_Job", x => x.JobId); - public JobEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public JobEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override JobEntityBuilder BuildTable(ColumnsBuilder table) { - JobId = table.AddAutoIncrementColumn("JobId"); + JobId = ActiveDatabase.AddAutoIncrementColumn(table,"JobId"); Name = table.AddStringColumn("Name", 200); JobType = table.AddStringColumn("JobType", 200); Frequency = table.AddStringColumn("Frequency", 1); diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs index e26c1f44..d4082706 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_JobLog", x => x.JobLogId); private readonly ForeignKey _jobLogForeignKey = new("FK_JobLog_Job", x => x.JobId, "Job", "JobId", ReferentialAction.Cascade); - public JobLogEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public JobLogEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -22,7 +23,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override JobLogEntityBuilder BuildTable(ColumnsBuilder table) { - JobLogId = table.AddAutoIncrementColumn("JobLogId"); + JobLogId = ActiveDatabase.AddAutoIncrementColumn(table,"JobLogId"); JobId = table.AddIntegerColumn("JobId"); StartDate = table.AddDateTimeColumn("StartDate"); FinishDate = table.AddDateTimeColumn("FinishDate", true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs index b32e07ec..8cf622a3 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Language", x => x.LanguageId); private readonly ForeignKey _siteForeignKey = new("FK_Language_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public LanguageEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public LanguageEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override LanguageEntityBuilder BuildTable(ColumnsBuilder table) { - LanguageId = table.AddAutoIncrementColumn("LanguageId"); + LanguageId = ActiveDatabase.AddAutoIncrementColumn(table,"LanguageId"); SiteId = table.AddIntegerColumn("SiteId"); Name = table.AddStringColumn("Name", 100); Code = table.AddStringColumn("Code", 10); diff --git a/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs index 933e1256..e1a8ad33 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Log", x => x.LogId); private readonly ForeignKey _siteForeignKey = new("FK_Log_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public LogEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public LogEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override LogEntityBuilder BuildTable(ColumnsBuilder table) { - LogId = table.AddAutoIncrementColumn("LogId"); + LogId = ActiveDatabase.AddAutoIncrementColumn(table,"LogId"); SiteId = table.AddIntegerColumn("SiteId", true); LogDate = table.AddDateTimeColumn("LogDate"); PageId = table.AddIntegerColumn("PageId", true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs index 5e7d5b50..d4891453 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "ModuleDefinition"; private readonly PrimaryKey _primaryKey = new("PK_ModuleDefinition", x => x.ModuleDefinitionId); - public ModuleDefinitionsEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public ModuleDefinitionsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override ModuleDefinitionsEntityBuilder BuildTable(ColumnsBuilder table) { - ModuleDefinitionId = table.AddAutoIncrementColumn("ModuleDefinitionId"); + ModuleDefinitionId = ActiveDatabase.AddAutoIncrementColumn(table,"ModuleDefinitionId"); ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); Name = table.AddStringColumn("Name", 200, true); Description = table.AddStringColumn("Description", 2000, true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs index 96f8b270..2bda7316 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Module", x => x.ModuleId); private readonly ForeignKey _siteForeignKey = new("FK_Module_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public ModuleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public ModuleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override ModuleEntityBuilder BuildTable(ColumnsBuilder table) { - ModuleId = table.AddAutoIncrementColumn("ModuleId"); + ModuleId = ActiveDatabase.AddAutoIncrementColumn(table,"ModuleId"); SiteId = table.AddIntegerColumn("SiteId"); ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); AllPages = table.AddBooleanColumn("AllPages"); diff --git a/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs index 2ee3779b..f3866af9 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Notification", x => x.NotificationId); private readonly ForeignKey _siteForeignKey = new("FK_Notification_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public NotificationEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public NotificationEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override NotificationEntityBuilder BuildTable(ColumnsBuilder table) { - NotificationId = table.AddAutoIncrementColumn("NotificationId"); + NotificationId = ActiveDatabase.AddAutoIncrementColumn(table,"NotificationId"); SiteId = table.AddIntegerColumn("SiteId"); FromUserId = table.AddIntegerColumn("FromUserId", true); ToUserId = table.AddIntegerColumn("ToUserId", true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs index c259b945..ff1d57a3 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Page", x => x.PageId); private readonly ForeignKey _siteForeignKey = new("FK_Page_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public PageEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public PageEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,9 +24,16 @@ namespace Oqtane.Migrations.EntityBuilders protected override PageEntityBuilder BuildTable(ColumnsBuilder table) { - PageId = table.AddAutoIncrementColumn("PageId"); + PageId = ActiveDatabase.AddAutoIncrementColumn(table,"PageId"); SiteId = table.AddIntegerColumn("SiteId"); - Path = table.AddStringColumn("Path", 50); + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") + { + Path = table.AddStringColumn("Path", 50); + } + else + { + Path = table.AddStringColumn("Path", 256); + } Name = table.AddStringColumn("Name", 50); Title = table.AddStringColumn("Title", 200, true); ThemeType = table.AddStringColumn("ThemeType", 200, true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs index ff9d0594..66fdd39f 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -15,7 +16,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly ForeignKey _moduleForeignKey = new("FK_PageModule_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.NoAction); private readonly ForeignKey _pageForeignKey = new("FK_PageModule_Page", x => x.PageId, "Page", "PageId", ReferentialAction.Cascade); - public PageModuleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public PageModuleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -25,7 +26,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override PageModuleEntityBuilder BuildTable(ColumnsBuilder table) { - PageModuleId = table.AddAutoIncrementColumn("PageModuleId"); + PageModuleId = ActiveDatabase.AddAutoIncrementColumn(table,"PageModuleId"); PageId = table.AddIntegerColumn("PageId"); ModuleId = table.AddIntegerColumn("ModuleId"); Title = table.AddStringColumn("Title", 200); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs index af383609..5636062b 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -16,7 +17,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly ForeignKey _userForeignKey = new("FK_Permission_User", x => x.UserId, "User", "UserId", ReferentialAction.NoAction); private readonly ForeignKey _roleForeignKey = new("FK_Permission_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction); - public PermissionEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public PermissionEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -27,7 +28,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override PermissionEntityBuilder BuildTable(ColumnsBuilder table) { - PermissionId = table.AddAutoIncrementColumn("PermissionId"); + PermissionId = ActiveDatabase.AddAutoIncrementColumn(table,"PermissionId"); SiteId = table.AddIntegerColumn("SiteId"); EntityName = table.AddStringColumn("EntityName", 50); EntityId = table.AddIntegerColumn("EntityId"); diff --git a/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs index b5e27469..ca57a939 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Profile", x => x.ProfileId); private readonly ForeignKey _siteForeignKey = new("FK_Profile_Sites", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public ProfileEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public ProfileEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override ProfileEntityBuilder BuildTable(ColumnsBuilder table) { - ProfileId = table.AddAutoIncrementColumn("ProfileId"); + ProfileId = ActiveDatabase.AddAutoIncrementColumn(table,"ProfileId"); SiteId = table.AddIntegerColumn("SiteId", true); Name = table.AddStringColumn("Name", 50); Title = table.AddStringColumn("Title", 50); diff --git a/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs index 67deafa1..dd9956d6 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -14,7 +15,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_Role", x => x.RoleId); private readonly ForeignKey _siteForeignKey = new("FK_Role_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); - public RoleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public RoleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -23,7 +24,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override RoleEntityBuilder BuildTable(ColumnsBuilder table) { - RoleId = table.AddAutoIncrementColumn("RoleId"); + RoleId = ActiveDatabase.AddAutoIncrementColumn(table,"RoleId"); SiteId = table.AddIntegerColumn("SiteId", true); Name = table.AddStringColumn("Name", 256); Description = table.AddStringColumn("Description", 256); diff --git a/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs index 7f4bb07d..31d32806 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "Setting"; private readonly PrimaryKey _primaryKey = new("PK_Setting", x => x.SettingId); - public SettingEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public SettingEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override SettingEntityBuilder BuildTable(ColumnsBuilder table) { - SettingId = table.AddAutoIncrementColumn("SettingId"); + SettingId = ActiveDatabase.AddAutoIncrementColumn(table,"SettingId"); EntityName = table.AddStringColumn("EntityName", 50); EntityId = table.AddIntegerColumn("EntityId"); SettingName = table.AddStringColumn("SettingName", 50); diff --git a/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs index 172ff1df..c6773c4e 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "Site"; private readonly PrimaryKey _primaryKey = new("PK_Site", x => x.SiteId); - public SiteEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public SiteEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override SiteEntityBuilder BuildTable(ColumnsBuilder table) { - SiteId = table.AddAutoIncrementColumn("SiteId"); + SiteId = ActiveDatabase.AddAutoIncrementColumn(table,"SiteId"); TenantId = table.AddIntegerColumn("TenantId"); Name = table.AddStringColumn("Name", 200); LogoFileId = table.AddIntegerColumn("LogoFileId", true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs index 1cf04a30..794fc2ac 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "Tenant"; private readonly PrimaryKey _primaryKey = new("PK_Tenant", x => x.TenantId); - public TenantEntityBuilder(MigrationBuilder migrationBuilder): base(migrationBuilder) + public TenantEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database): base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override TenantEntityBuilder BuildTable(ColumnsBuilder table) { - TenantId = table.AddAutoIncrementColumn("TenantId"); + TenantId = ActiveDatabase.AddAutoIncrementColumn(table,"TenantId"); Name = table.AddStringColumn("Name", 100); DBConnectionString = table.AddStringColumn("DBConnectionString", 1024); Version = table.AddStringColumn("Version", 50, true); diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs index cfcf6acb..51a2b78e 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -13,7 +14,7 @@ namespace Oqtane.Migrations.EntityBuilders private const string _entityTableName = "User"; private readonly PrimaryKey _primaryKey = new("PK_User", x => x.UserId); - public UserEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public UserEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -21,7 +22,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override UserEntityBuilder BuildTable(ColumnsBuilder table) { - UserId = table.AddAutoIncrementColumn("UserId"); + UserId = ActiveDatabase.AddAutoIncrementColumn(table,"UserId"); Username = table.AddStringColumn("Username", 256); DisplayName = table.AddStringColumn("DisplayName", 50); Email = table.AddStringColumn("Email", 256); diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs index 46ee993e..88327191 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global @@ -15,7 +16,7 @@ namespace Oqtane.Migrations.EntityBuilders private readonly ForeignKey _userForeignKey = new("FK_UserRole_User", x => x.UserId, "User", "UserId", ReferentialAction.Cascade); private readonly ForeignKey _roleForeignKey = new("FK_UserRole_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction); - public UserRoleEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public UserRoleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -25,7 +26,7 @@ namespace Oqtane.Migrations.EntityBuilders protected override UserRoleEntityBuilder BuildTable(ColumnsBuilder table) { - UserRoleId = table.AddAutoIncrementColumn("UserRoleId"); + UserRoleId = ActiveDatabase.AddAutoIncrementColumn(table,"UserRoleId"); UserId = table.AddIntegerColumn("UserId"); RoleId = table.AddIntegerColumn("RoleId"); EffectiveDate = table.AddDateTimeColumn("EffectiveDate", true); diff --git a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs index ecd272db..068a54ef 100644 --- a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs +++ b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs @@ -6,14 +6,6 @@ namespace Oqtane.Migrations.Extensions { public static class ColumnsBuilderExtensions { - public static OperationBuilder AddAutoIncrementColumn(this ColumnsBuilder table, string name) - { - return table.Column(name: name, nullable: false) - .Annotation("SqlServer:Identity", "1, 1") - .Annotation("Sqlite:Autoincrement", true) - .Annotation("MySql:ValueGeneratedOnAdd", true); - } - public static OperationBuilder AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false) { return table.Column(name: name, nullable: nullable); @@ -36,12 +28,12 @@ namespace Oqtane.Migrations.Extensions public static OperationBuilder AddMaxStringColumn(this ColumnsBuilder table, string name, bool nullable = false) { - return table.Column(name: name, nullable: nullable); + return table.Column(name: name, nullable: nullable, unicode: true); } public static OperationBuilder AddStringColumn(this ColumnsBuilder table, string name, int length, bool nullable = false) { - return table.Column(name: name, maxLength: length, nullable: nullable); + return table.Column(name: name, maxLength: length, nullable: nullable, unicode: true); } } diff --git a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs new file mode 100644 index 00000000..2a0e6fce --- /dev/null +++ b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; + +namespace Oqtane.Migrations +{ + public abstract class MultiDatabaseMigration : Migration + { + private readonly IEnumerable _databases; + + protected MultiDatabaseMigration(IEnumerable databases) + { + _databases = databases; + } + + protected IOqtaneDatabase ActiveDatabase => _databases.FirstOrDefault(d => d.Provider == ActiveProvider); + } +} diff --git a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigrationsAssembly.cs b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigrationsAssembly.cs new file mode 100644 index 00000000..6373f351 --- /dev/null +++ b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigrationsAssembly.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Internal; +using Oqtane.Interfaces; +using Oqtane.Repository.Databases.Interfaces; + +namespace Oqtane.Migrations.Framework +{ + public class MultiDatabaseMigrationsAssembly: MigrationsAssembly + { + private readonly IEnumerable _databases; + + public MultiDatabaseMigrationsAssembly( + ICurrentDbContext currentContext, + IDbContextOptions options, + IMigrationsIdGenerator idGenerator, + IDiagnosticsLogger logger) + : base(currentContext, options, idGenerator, logger) + { + var multiDatabaseContext = currentContext.Context as IMultiDatabase; + if (multiDatabaseContext != null) _databases = multiDatabaseContext.Databases; + } + public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider) + { + var hasCtorWithCacheOptions = migrationClass.GetConstructor(new[] { typeof(IEnumerable) }) != null; + + if (hasCtorWithCacheOptions) + { + var migration = (Migration)Activator.CreateInstance(migrationClass.AsType(), _databases); + if (migration != null) + { + migration.ActiveProvider = activeProvider; + return migration; + } + } + + return base.CreateMigration(migrationClass, activeProvider); + } + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index 4329a4c7..96774c52 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Oqtane.Infrastructure; using Oqtane.Models; using Oqtane.Repository; @@ -8,6 +9,8 @@ using System.Net; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Oqtane.Enums; +using Oqtane.Interfaces; + // ReSharper disable ConvertToUsingDeclaration namespace Oqtane.Modules.HtmlText.Manager @@ -15,12 +18,12 @@ namespace Oqtane.Modules.HtmlText.Manager public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable { private readonly IHtmlTextRepository _htmlText; - private readonly ISqlRepository _sql; + private readonly IEnumerable _databases; - public HtmlTextManager(IHtmlTextRepository htmlText, ISqlRepository sql) + public HtmlTextManager(IHtmlTextRepository htmlText, IEnumerable databases) { _htmlText = htmlText; - _sql = sql; + _databases = databases; } public string ExportModule(Module module) @@ -54,13 +57,13 @@ namespace Oqtane.Modules.HtmlText.Manager public bool Install(Tenant tenant, string version) { - var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; + var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Up); } public bool Uninstall(Tenant tenant) { - var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; + var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Down); } } diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs index 2214df2c..5ed5242c 100644 --- a/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs +++ b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs @@ -1,5 +1,8 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; +using Oqtane.Migrations; using Oqtane.Modules.HtmlText.Migrations.EntityBuilders; using Oqtane.Modules.HtmlText.Repository; @@ -7,19 +10,23 @@ namespace Oqtane.Modules.HtmlText.Migrations { [DbContext(typeof(HtmlTextContext))] [Migration("HtmlText.01.00.00.00")] - public class InitializeModule : Migration + public class InitializeModule : MultiDatabaseMigration { + public InitializeModule(IEnumerable databases) : base(databases) + { + } + protected override void Up(MigrationBuilder migrationBuilder) { //Create HtmlText table - var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder, ActiveDatabase); entityBuilder.Create(); } protected override void Down(MigrationBuilder migrationBuilder) { //Drop HtmlText table - var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder, ActiveDatabase); entityBuilder.Drop(); } } diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs index 972c4c7d..8ed3e956 100644 --- a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs +++ b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; using Oqtane.Migrations; using Oqtane.Migrations.EntityBuilders; using Oqtane.Migrations.Extensions; @@ -16,7 +17,7 @@ namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders private readonly PrimaryKey _primaryKey = new("PK_HtmlText", x => x.HtmlTextId); private readonly ForeignKey _moduleForeignKey = new("FK_HtmlText_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); - public HtmlTextEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + public HtmlTextEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) { EntityTableName = _entityTableName; PrimaryKey = _primaryKey; @@ -25,7 +26,7 @@ namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders protected override HtmlTextEntityBuilder BuildTable(ColumnsBuilder table) { - HtmlTextId = table.AddAutoIncrementColumn("HtmlTextId"); + HtmlTextId = ActiveDatabase.AddAutoIncrementColumn(table,"HtmlTextId"); ModuleId = table.AddIntegerColumn("ModuleId"); Content = table.AddMaxStringColumn("Content"); diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index f4aaf48c..168667fd 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -1,18 +1,21 @@ -using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; using Oqtane.Modules.HtmlText.Models; using Oqtane.Repository; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; +using Oqtane.Interfaces; +using Oqtane.Repository.Databases.Interfaces; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global namespace Oqtane.Modules.HtmlText.Repository { - public class HtmlTextContext : DBContextBase, IService + public class HtmlTextContext : DBContextBase, IService, IMultiDatabase { - public virtual DbSet HtmlText { get; set; } - public HtmlTextContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { - // ContextBase handles multi-tenant database connections } + + public virtual DbSet HtmlText { get; set; } } } diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index a87d0533..8898841a 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -50,7 +50,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive
- @@ -58,6 +57,9 @@
+ + + diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index 5ee8b6c1..0e7b0289 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -1,10 +1,16 @@ using System; +using System.Collections.Generic; +using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; +using Oqtane.Interfaces; +using Oqtane.Migrations.Framework; +using Oqtane.Repository.Databases.Interfaces; using Oqtane.Shared; // ReSharper disable BuiltInTypeReferenceStyleForMemberAccess @@ -32,11 +38,16 @@ namespace Oqtane.Repository _configuration = dbConfig.Configuration; _connectionString = dbConfig.ConnectionString; _databaseType = dbConfig.DatabaseType; + Databases = dbConfig.Databases; _tenantResolver = tenantResolver; } + public IEnumerable Databases { get; } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + optionsBuilder.ReplaceService(); + if (string.IsNullOrEmpty(_connectionString) && _tenantResolver != null) { var tenant = _tenantResolver.GetTenant(); @@ -60,7 +71,14 @@ namespace Oqtane.Repository if (!string.IsNullOrEmpty(_connectionString) && !string.IsNullOrEmpty(_databaseType)) { - optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); + if (Databases != null) + { + optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.Name == _databaseType), _connectionString); + } + else + { + optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); + } } base.OnConfiguring(optionsBuilder); diff --git a/Oqtane.Server/Repository/Context/DbConfig.cs b/Oqtane.Server/Repository/Context/DbConfig.cs index 7cc636ef..97e60f8f 100644 --- a/Oqtane.Server/Repository/Context/DbConfig.cs +++ b/Oqtane.Server/Repository/Context/DbConfig.cs @@ -1,20 +1,25 @@ +using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; +using Oqtane.Interfaces; namespace Oqtane.Repository { public class DbConfig : IDbConfig { - public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration) + public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration, IEnumerable databases) { Accessor = accessor; Configuration = configuration; + Databases = databases; } public IHttpContextAccessor Accessor { get; } public IConfiguration Configuration { get; } + public IEnumerable Databases { get; set; } + public string ConnectionString { get; set; } public string DatabaseType { get; set; } diff --git a/Oqtane.Server/Repository/Context/InstallationContext.cs b/Oqtane.Server/Repository/Context/InstallationContext.cs index 061aecbb..d64bd5f0 100644 --- a/Oqtane.Server/Repository/Context/InstallationContext.cs +++ b/Oqtane.Server/Repository/Context/InstallationContext.cs @@ -1,24 +1,29 @@ -using System.Diagnostics.CodeAnalysis; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; using Oqtane.Extensions; +using Oqtane.Interfaces; using Oqtane.Models; +// ReSharper disable CheckNamespace +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + namespace Oqtane.Repository { public class InstallationContext : DbContext { private readonly string _connectionString; - private readonly string _databaseType; + private readonly IOqtaneDatabase _database; - public InstallationContext(string databaseType, string connectionString) + public InstallationContext(IOqtaneDatabase database, string connectionString) { _connectionString = connectionString; - _databaseType = databaseType; + _database = database; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - => optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString); + => optionsBuilder.UseOqtaneDatabase(_database, _connectionString); public virtual DbSet Alias { get; set; } public virtual DbSet Tenant { get; set; } diff --git a/Oqtane.Server/Repository/Context/MasterDBContext.cs b/Oqtane.Server/Repository/Context/MasterDBContext.cs index 04f61176..a5040c33 100644 --- a/Oqtane.Server/Repository/Context/MasterDBContext.cs +++ b/Oqtane.Server/Repository/Context/MasterDBContext.cs @@ -1,9 +1,14 @@ using System; -using Microsoft.AspNetCore.Http; +using System.Collections.Generic; +using System.Linq; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations; using Oqtane.Models; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; +using Oqtane.Interfaces; +using Oqtane.Migrations.Framework; +using Oqtane.Repository.Databases.Interfaces; using Oqtane.Shared; // ReSharper disable BuiltInTypeReferenceStyleForMemberAccess @@ -12,17 +17,22 @@ using Oqtane.Shared; namespace Oqtane.Repository { - public class MasterDBContext : DbContext + public class MasterDBContext : DbContext, IMultiDatabase { private readonly IDbConfig _dbConfig; public MasterDBContext(DbContextOptions options, IDbConfig dbConfig) : base(options) { _dbConfig = dbConfig; + Databases = dbConfig.Databases; } + public IEnumerable Databases { get; } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + optionsBuilder.ReplaceService(); + var connectionString = _dbConfig.ConnectionString; var configuration = _dbConfig.Configuration; var databaseType = _dbConfig.DatabaseType; @@ -38,10 +48,18 @@ namespace Oqtane.Repository databaseType = configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; } - if (!string.IsNullOrEmpty(connectionString)) + if (!string.IsNullOrEmpty(connectionString) && !string.IsNullOrEmpty(databaseType)) { - optionsBuilder.UseOqtaneDatabase(databaseType, connectionString); + if (Databases != null) + { + optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.Name == databaseType), connectionString); + } + else + { + optionsBuilder.UseOqtaneDatabase(databaseType, connectionString); + } } + base.OnConfiguring(optionsBuilder); } diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index 3e2f5d3d..8aa6ccc2 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -1,12 +1,19 @@ -using Microsoft.AspNetCore.Http; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; +using Oqtane.Interfaces; using Oqtane.Models; +using Oqtane.Repository.Databases.Interfaces; + +// ReSharper disable CheckNamespace +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global namespace Oqtane.Repository { - public class TenantDBContext : DBContextBase + public class TenantDBContext : DBContextBase, IMultiDatabase { + public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { } + public virtual DbSet Site { get; set; } public virtual DbSet Page { get; set; } public virtual DbSet PageModule { get; set; } @@ -21,13 +28,6 @@ namespace Oqtane.Repository public virtual DbSet Notification { get; set; } public virtual DbSet Folder { get; set; } public virtual DbSet File { get; set; } - public virtual DbSet Language { get; set; } - - public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) - { - // DBContextBase handles multi-tenant database connections - } - } } diff --git a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs index cde50726..2d364505 100644 --- a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs +++ b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; +using Oqtane.Interfaces; namespace Oqtane.Repository { @@ -9,7 +11,10 @@ namespace Oqtane.Repository public IConfiguration Configuration { get; } + public IEnumerable Databases { get; set; } + public string ConnectionString { get; set; } + public string DatabaseType { get; set; } } } diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 5ba2ff1b..60ae50b8 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -130,10 +130,6 @@ namespace Oqtane services.AddSingleton(); - services.AddScoped(); - services.AddDbContext(options => { }); - services.AddDbContext(options => { }); - services.AddIdentityCore(options => { }) .AddEntityFrameworkStores() .AddSignInManager() @@ -214,6 +210,10 @@ namespace Oqtane // load the external assemblies into the app domain, install services services.AddOqtane(_runtime, _supportedCultures); + services.AddScoped(); + services.AddDbContext(options => { }); + services.AddDbContext(options => { }); + services.AddMvc() .AddNewtonsoftJson() diff --git a/Oqtane.Shared/Interfaces/IDatabase.cs b/Oqtane.Shared/Interfaces/IDatabase.cs deleted file mode 100644 index 8a03d74b..00000000 --- a/Oqtane.Shared/Interfaces/IDatabase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -namespace Oqtane.Interfaces -{ - public interface IDatabase - { - public string FriendlyName { get; } - - public string Name { get; } - - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); - } -} diff --git a/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs b/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs new file mode 100644 index 00000000..7f214a40 --- /dev/null +++ b/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Models; + +namespace Oqtane.Interfaces +{ + public interface IOqtaneDatabase + { + public string FriendlyName { get; } + + public string Name { get; } + + public string Provider { get; } + + public List ConnectionStringFields { get; } + + public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name); + + public string BuildConnectionString(); + + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); + } +} diff --git a/Oqtane.Shared/Models/ConnectionStringField.cs b/Oqtane.Shared/Models/ConnectionStringField.cs new file mode 100644 index 00000000..a014168c --- /dev/null +++ b/Oqtane.Shared/Models/ConnectionStringField.cs @@ -0,0 +1,11 @@ +namespace Oqtane.Models +{ + public class ConnectionStringField + { + public string FriendlyName { get; set; } + + public string Name { get; set; } + + public string Value { get; set; } + } +} diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 44aaab47..7760da33 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -19,9 +19,16 @@ + + + + C:\Users\charl\.nuget\packages\microsoft.entityframeworkcore.relational\5.0.2\lib\netstandard2.1\Microsoft.EntityFrameworkCore.Relational.dll + + + diff --git a/Oqtane.sln b/Oqtane.sln index 70e85123..9548b9c6 100644 --- a/Oqtane.sln +++ b/Oqtane.sln @@ -20,6 +20,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oqtane.Database.MySQL", "Oqtane.Database.MySQL\Oqtane.Database.MySQL.csproj", "{A996FD2D-DAC8-4DFA-92B2-51DF32C6E014}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oqtane.Database.PostgreSQL", "Oqtane.Database.PostgreSQL\Oqtane.Database.PostgreSQL.csproj", "{3B29B35F-65E7-4819-9AED-EAC7FCFA309B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Oqtane.Database.Sqlite", "Oqtane.Database.Sqlite\Oqtane.Database.Sqlite.csproj", "{E4F50CA9-19A6-465A-9469-C033748AD95B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,6 +52,18 @@ Global {823B556D-8D4E-4BB8-A65A-C4EB5E7E7424}.Debug|Any CPU.Build.0 = Debug|Any CPU {823B556D-8D4E-4BB8-A65A-C4EB5E7E7424}.Release|Any CPU.ActiveCfg = Release|Any CPU {823B556D-8D4E-4BB8-A65A-C4EB5E7E7424}.Release|Any CPU.Build.0 = Release|Any CPU + {A996FD2D-DAC8-4DFA-92B2-51DF32C6E014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A996FD2D-DAC8-4DFA-92B2-51DF32C6E014}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A996FD2D-DAC8-4DFA-92B2-51DF32C6E014}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A996FD2D-DAC8-4DFA-92B2-51DF32C6E014}.Release|Any CPU.Build.0 = Release|Any CPU + {3B29B35F-65E7-4819-9AED-EAC7FCFA309B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B29B35F-65E7-4819-9AED-EAC7FCFA309B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B29B35F-65E7-4819-9AED-EAC7FCFA309B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B29B35F-65E7-4819-9AED-EAC7FCFA309B}.Release|Any CPU.Build.0 = Release|Any CPU + {E4F50CA9-19A6-465A-9469-C033748AD95B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4F50CA9-19A6-465A-9469-C033748AD95B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4F50CA9-19A6-465A-9469-C033748AD95B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4F50CA9-19A6-465A-9469-C033748AD95B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From e6530ee127dddbceafcc1458fcd06150a1c4dfb4 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Fri, 2 Apr 2021 10:55:00 -0700 Subject: [PATCH 06/23] Added support for MySQL and ProgreSQL and AddSite/Tenant --- Oqtane.Client/Modules/Admin/Sites/Add.razor | 171 ++++++-------- Oqtane.Client/Modules/HtmlText/Edit.razor | 2 +- .../HtmlText/Services/HtmlTextService.cs | 8 +- .../HtmlText/Services/IHtmlTextService.cs | 6 +- Oqtane.Database.MySQL/MySQLDatabase.cs | 57 +++-- .../PostgreSQLDatabase.cs | 97 ++++++-- Oqtane.Database.Sqlite/SqliteDatabase.cs | 47 ++-- Oqtane.Server/Databases/LocalDbDatabase.cs | 4 +- Oqtane.Server/Databases/SqlServerDatabase.cs | 11 +- .../Databases/SqlServerDatabaseBase.cs | 23 +- .../Migrations/01000000_InitializeMaster.cs | 4 +- .../01000100_AddAdditionalIndexesInTenant.cs | 1 - ...000101_AddAdditionColumnToNotifications.cs | 8 +- ...2000001_AddColumnToProfileAndUpdatePage.cs | 7 +- .../02000101_UpdateIconColumnInPage.cs | 10 +- .../02000103_UpdatePageAndAddColumnToSite.cs | 15 +- .../02010001_AddDatabaseTypeColumnToTenant.cs | 7 +- .../EntityBuilders/AliasEntityBuilder.cs | 9 +- .../AspNetUserClaimsEntityBuilder.cs | 9 +- .../AspNetUsersEntityBuilder.cs | 31 ++- .../AuditableBaseEntityBuilder.cs | 9 +- .../EntityBuilders/BaseEntityBuilder.cs | 223 ++++++++++++++---- .../DeletableAuditableBaseEntityBuilder.cs | 7 +- .../DeletableBaseEntityBuilder.cs | 9 +- .../EntityBuilders/FileEntityBuilder.cs | 15 +- .../EntityBuilders/FolderEntityBuilder.cs | 15 +- .../EntityBuilders/JobEntityBuilder.cs | 25 +- .../EntityBuilders/JobLogEntityBuilder.cs | 14 +- .../EntityBuilders/LanguageEntityBuilder.cs | 11 +- .../EntityBuilders/LogEntityBuilder.cs | 33 ++- .../ModuleDefinitionsEntityBuilder.cs | 13 +- .../EntityBuilders/ModuleEntityBuilder.cs | 9 +- .../NotificationEntityBuilder.cs | 23 +- .../EntityBuilders/PageEntityBuilder.cs | 33 ++- .../EntityBuilders/PageModuleEntityBuilder.cs | 15 +- .../EntityBuilders/PermissionEntityBuilder.cs | 17 +- .../EntityBuilders/ProfileEntityBuilder.cs | 23 +- .../EntityBuilders/RoleEntityBuilder.cs | 13 +- .../EntityBuilders/SettingEntityBuilder.cs | 11 +- .../EntityBuilders/SiteEntityBuilder.cs | 25 +- .../EntityBuilders/TenantEntityBuilder.cs | 9 +- .../EntityBuilders/UserEntityBuilder.cs | 15 +- .../EntityBuilders/UserRoleEntityBuilder.cs | 11 +- .../Extensions/ColumnsBuilderExtensions.cs | 40 ---- .../CreateTableBuilderExtensions.cs | 24 -- .../Migrations/Framework/ForeignKey.cs | 2 - .../Controllers/HtmlTextController.cs | 10 +- .../HtmlText/Manager/HtmlTextManager.cs | 2 +- .../EntityBuilders/HtmlTextEntityBuilder.cs | 7 +- .../HtmlText/Repository/HtmlTextContext.cs | 2 +- .../HtmlText/Repository/HtmlTextRepository.cs | 8 +- .../Repository/IHtmlTextRepository.cs | 6 +- .../Repository/Context/DBContextBase.cs | 13 + Oqtane.Shared/Interfaces/IOqtaneDatabase.cs | 6 + Oqtane.Shared/Models/ConnectionStringField.cs | 2 + .../Models/{HtmlTextInfo.cs => HtmlText.cs} | 3 +- Oqtane.Shared/Shared/OqtaneDatabaseBase.cs | 59 +++++ 57 files changed, 708 insertions(+), 581 deletions(-) delete mode 100644 Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs delete mode 100644 Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs rename Oqtane.Shared/Modules/HtmlText/Models/{HtmlTextInfo.cs => HtmlText.cs} (88%) create mode 100644 Oqtane.Shared/Shared/OqtaneDatabaseBase.cs diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index a4b430e9..ac89d1dd 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -1,4 +1,5 @@ @namespace Oqtane.Modules.Admin.Sites +@using Oqtane.Interfaces @inherits ModuleBase @inject NavigationManager NavigationManager @inject ITenantService TenantService @@ -9,6 +10,7 @@ @inject IUserService UserService @inject IInstallationService InstallationService @inject IStringLocalizer Localizer +@inject IEnumerable Databases @if (_tenants == null) { @@ -122,7 +124,7 @@ else - @if (_tenantid == "+") + @if (_tenantId == "+") { @@ -134,7 +136,7 @@ else - + @@ -142,64 +144,67 @@ else - + @{ + foreach (var database in Databases) + { + + } + } - - - - - - - - - - - - - - - - - - - - - - - - - @if (!_integratedsecurity) { - - - - - - - - - - - - - - - - + _selectedDatabase = Databases.Single(d => d.Name == _databaseType); + foreach (var field in _selectedDatabase.ConnectionStringFields) + { + var fieldId = field.Name.ToLowerInvariant(); + if (field.Name != "IntegratedSecurity") + { + var isVisible = ""; + var fieldType = (field.Name == "Pwd") ? "password" : "text"; + if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" ) + { + var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity"); + if (intSecurityField != null) + { + isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : ""; + } + } + + field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm")); + + + + + + + + + + } + else + { + + + + + + + + + } + } } - + @@ -223,16 +228,13 @@ else private List _containers = new List(); private List _siteTemplates; private List _tenants; - private string _tenantid = "-"; + private string _tenantId = "-"; - private string _tenantname = string.Empty; - private string _databasetype = "LocalDB"; - private string _server = "(LocalDb)\\MSSQLLocalDB"; - private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm"); - private string _username = string.Empty; - private string _password = string.Empty; - private bool _integratedsecurity = true; - private string _hostusername = UserNames.Host; + private string _tenantName = string.Empty; + private IOqtaneDatabase _selectedDatabase; + private string _databaseType = "LocalDB"; + + private string _hostUserName = UserNames.Host; private string _hostpassword = string.Empty; private string _name = string.Empty; @@ -256,23 +258,10 @@ else private void TenantChanged(ChangeEventArgs e) { - _tenantid = (string)e.Value; - if (string.IsNullOrEmpty(_tenantname)) + _tenantId = (string)e.Value; + if (string.IsNullOrEmpty(_tenantName)) { - _tenantname = _name; - } - StateHasChanged(); - } - - private void SetIntegratedSecurity(ChangeEventArgs e) - { - if (Convert.ToBoolean((string)e.Value)) - { - _integratedsecurity = true; - } - else - { - _integratedsecurity = false; + _tenantName = _name; } StateHasChanged(); } @@ -306,7 +295,7 @@ else private async Task SaveSite() { - if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-" && _sitetemplatetype != "-") + if (_tenantId != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-" && _sitetemplatetype != "-") { var duplicates = new List(); var aliases = await AliasService.GetAliasesAsync(); @@ -322,9 +311,9 @@ else { InstallConfig config = new InstallConfig(); - if (_tenantid == "+") + if (_tenantId == "+") { - if (!string.IsNullOrEmpty(_tenantname) && _tenants.FirstOrDefault(item => item.Name == _tenantname) == null) + if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null) { // validate host credentials var user = new User(); @@ -334,32 +323,14 @@ else user = await UserService.LoginUserAsync(user, false, false); if (user.IsAuthenticated) { - if (!string.IsNullOrEmpty(_server) && !string.IsNullOrEmpty(_database)) + var connectionString = _selectedDatabase.BuildConnectionString(); + if (connectionString != "") { - var connectionString = string.Empty; - if (_databasetype == "LocalDB") - { - connectionString = "Data Source=" + _server + ";AttachDbFilename=|DataDirectory|\\" + _database + ".mdf;Initial Catalog=" + _database + ";Integrated Security=SSPI;"; - } - else - { - connectionString = "Data Source=" + _server + ";Initial Catalog=" + _database + ";"; - - if (_integratedsecurity) - { - connectionString += "Integrated Security=SSPI;"; - } - else - { - connectionString += "User ID=" + _username + ";Password=" + _password; - } - } - config.ConnectionString = connectionString; config.HostPassword = _hostpassword; config.HostEmail = user.Email; config.HostName = user.DisplayName; - config.TenantName = _tenantname; + config.TenantName = _tenantName; config.IsNewTenant = true; } else @@ -379,7 +350,7 @@ else } else { - var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); + var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantId)); if (tenant != null) { config.TenantName = tenant.Name; diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 311c4cd7..3cd06d9c 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -80,7 +80,7 @@ } else { - htmltext = new HtmlTextInfo(); + htmltext = new HtmlText(); htmltext.ModuleId = ModuleState.ModuleId; htmltext.Content = content; await HtmlTextService.AddHtmlTextAsync(htmltext); diff --git a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs index 1e9d42ab..af0063bb 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs @@ -19,18 +19,18 @@ namespace Oqtane.Modules.HtmlText.Services private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText"); - public async Task GetHtmlTextAsync(int moduleId) + public async Task GetHtmlTextAsync(int moduleId) { - var htmltext = await GetJsonAsync>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId)); + var htmltext = await GetJsonAsync>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId)); return htmltext.FirstOrDefault(); } - public async Task AddHtmlTextAsync(HtmlTextInfo htmlText) + public async Task AddHtmlTextAsync(Models.HtmlText htmlText) { await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText); } - public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText) + public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText) { await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText); } diff --git a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs index 6ce1d646..c663882a 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs @@ -6,11 +6,11 @@ namespace Oqtane.Modules.HtmlText.Services { public interface IHtmlTextService { - Task GetHtmlTextAsync(int ModuleId); + Task GetHtmlTextAsync(int ModuleId); - Task AddHtmlTextAsync(HtmlTextInfo htmltext); + Task AddHtmlTextAsync(Models.HtmlText htmltext); - Task UpdateHtmlTextAsync(HtmlTextInfo htmltext); + Task UpdateHtmlTextAsync(Models.HtmlText htmltext); Task DeleteHtmlTextAsync(int ModuleId); } diff --git a/Oqtane.Database.MySQL/MySQLDatabase.cs b/Oqtane.Database.MySQL/MySQLDatabase.cs index 5691e8c6..3e988aab 100644 --- a/Oqtane.Database.MySQL/MySQLDatabase.cs +++ b/Oqtane.Database.MySQL/MySQLDatabase.cs @@ -4,39 +4,36 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using MySql.EntityFrameworkCore.Metadata; -using Oqtane.Interfaces; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Database.MySQL { - public class MySQLDatabase : IOqtaneDatabase + public class MySQLDatabase : OqtaneDatabaseBase { - public MySQLDatabase() + private static string _friendlyName => "MySQL"; + + private static string _name => "MySQL"; + + private static readonly List _connectionStringFields = new() { - ConnectionStringFields = new List() - { - new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1"}, - new() {Name = "Port", FriendlyName = "Port", Value = "3306"}, - new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, - new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, - new() {Name = "Pwd", FriendlyName = "Password", Value = ""} - }; - } + new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"}, + new() {Name = "Port", FriendlyName = "Port", Value = "3306", HelpText="Enter the port used to connect to the server"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"}, + new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"} + }; - public string FriendlyName => Name; + public MySQLDatabase() :base(_name, _friendlyName, _connectionStringFields) { } - public string Name => "MySQL"; + public override string Provider => "MySql.EntityFrameworkCore"; - public string Provider => "MySql.EntityFrameworkCore"; - - public List ConnectionStringFields { get; } - - public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + public override OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) { return table.Column(name: name, nullable: false).Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn); } - public string BuildConnectionString() + public override string BuildConnectionString() { var connectionString = String.Empty; @@ -58,7 +55,25 @@ namespace Oqtane.Database.MySQL return connectionString; } - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + public override string ConcatenateSql(params string[] values) + { + var returnValue = "CONCAT("; + for (var i = 0; i < values.Length; i++) + { + if (i > 0) + { + returnValue += ","; + } + returnValue += values[i]; + } + + returnValue += ")"; + + return returnValue; + } + + + public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) { return optionsBuilder.UseMySQL(connectionString); } diff --git a/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs index 9ba6ab63..8d50debd 100644 --- a/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs +++ b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs @@ -1,44 +1,48 @@ using System; using System.Collections.Generic; +using System.Globalization; +using EFCore.NamingConventions.Internal; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; -using Oqtane.Interfaces; using Oqtane.Models; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Oqtane.Shared; namespace Oqtane.Database.PostgreSQL { - public class PostgreSQLDatabase : IOqtaneDatabase + public class PostgreSQLDatabase : OqtaneDatabaseBase { + private static string _friendlyName => "PostgreSQL"; - public PostgreSQLDatabase() + private static string _name => "PostgreSQL"; + + private readonly INameRewriter _rewriter; + + private static readonly List _connectionStringFields = new() { - ConnectionStringFields = new List() - { - new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1"}, - new() {Name = "Port", FriendlyName = "Port", Value = "5432"}, - new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, - new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true"}, - new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, - new() {Name = "Pwd", FriendlyName = "Password", Value = ""} - }; + new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"}, + new() {Name = "Port", FriendlyName = "Port", Value = "5432", HelpText="Enter the port used to connect to the server"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"}, + new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"}, + new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"} + }; + + public PostgreSQLDatabase() : base(_name, _friendlyName, _connectionStringFields) + { + _rewriter = new SnakeCaseNameRewriter(CultureInfo.InvariantCulture); } - public string FriendlyName => Name; + public override string Provider => "Npgsql.EntityFrameworkCore.PostgreSQL"; - public string Name => "PostgreSQL"; - - public string Provider => "Npgsql.EntityFrameworkCore.PostgreSQL"; - - public List ConnectionStringFields { get; } - - public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + public override OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) { return table.Column(name: name, nullable: false).Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn); } - public string BuildConnectionString() + public override string BuildConnectionString() { var connectionString = String.Empty; @@ -73,7 +77,56 @@ namespace Oqtane.Database.PostgreSQL return connectionString; } - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + public override string ConcatenateSql(params string[] values) + { + var returnValue = String.Empty; + for (var i = 0; i < values.Length; i++) + { + if (i > 0) + { + returnValue += " || "; + } + returnValue += values[i]; + } + + return returnValue; + } + + public override string RewriteName(string name) + { + return _rewriter.RewriteName(name); + } + + public override void UpdateIdentityStoreTableNames(ModelBuilder builder) + { + foreach(var entity in builder.Model.GetEntityTypes()) + { + var tableName = entity.GetTableName(); + if (tableName.StartsWith("AspNetUser")) + { + // Replace table names + entity.SetTableName(RewriteName(entity.GetTableName())); + + // Replace column names + foreach(var property in entity.GetProperties()) + { + property.SetColumnName(RewriteName(property.GetColumnName())); + } + + foreach(var key in entity.GetKeys()) + { + key.SetName(RewriteName(key.GetName())); + } + + foreach(var index in entity.GetIndexes()) + { + index.SetName(RewriteName(index.GetName())); + } + } + } + } + + public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) { return optionsBuilder.UseNpgsql(connectionString).UseSnakeCaseNamingConvention(); } diff --git a/Oqtane.Database.Sqlite/SqliteDatabase.cs b/Oqtane.Database.Sqlite/SqliteDatabase.cs index 62873409..50b901d0 100644 --- a/Oqtane.Database.Sqlite/SqliteDatabase.cs +++ b/Oqtane.Database.Sqlite/SqliteDatabase.cs @@ -1,38 +1,34 @@ using System; using System.Collections.Generic; -using System.Linq; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; -using Oqtane.Interfaces; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Repository.Databases { - public class SqliteDatabase : IOqtaneDatabase + public class SqliteDatabase : OqtaneDatabaseBase { - public SqliteDatabase() + private static string _friendlyName => "Sqlite"; + + private static string _name => "Sqlite"; + + private static readonly List _connectionStringFields = new() { - ConnectionStringFields = new List() - { - new() {Name = "Server", FriendlyName = "File Name", Value = "Oqtane-{{Date}}.db"} - }; - } + new() {Name = "Server", FriendlyName = "File Name", Value = "Oqtane-{{Date}}.db", HelpText="Enter the file name to use for the database"} + }; - public string FriendlyName => Name; + public SqliteDatabase() :base(_name, _friendlyName, _connectionStringFields) { } - public string Name => "Sqlite"; + public override string Provider => "Microsoft.EntityFrameworkCore.Sqlite"; - public string Provider => "Microsoft.EntityFrameworkCore.Sqlite"; - - public List ConnectionStringFields { get; } - - public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + public override OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) { return table.Column(name: name, nullable: false).Annotation("Sqlite:Autoincrement", true); } - public string BuildConnectionString() + public override string BuildConnectionString() { var connectionstring = String.Empty; @@ -46,7 +42,22 @@ namespace Oqtane.Repository.Databases return connectionstring; } - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + public override string ConcatenateSql(params string[] values) + { + var returnValue = String.Empty; + for (var i = 0; i < values.Length; i++) + { + if (i > 0) + { + returnValue += " || "; + } + returnValue += values[i]; + } + + return returnValue; + } + + public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) { return optionsBuilder.UseSqlite(connectionString); } diff --git a/Oqtane.Server/Databases/LocalDbDatabase.cs b/Oqtane.Server/Databases/LocalDbDatabase.cs index a0e0580d..77be3035 100644 --- a/Oqtane.Server/Databases/LocalDbDatabase.cs +++ b/Oqtane.Server/Databases/LocalDbDatabase.cs @@ -12,8 +12,8 @@ namespace Oqtane.Databases private static readonly List _connectionStringFields = new() { - new() {Name = "Server", FriendlyName = "Server", Value = "(LocalDb)\\MSSQLLocalDB"}, - new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"} + new() {Name = "Server", FriendlyName = "Server", Value = "(LocalDb)\\MSSQLLocalDB", HelpText="Enter the database server"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"} }; public LocalDbDatabase() :base(_name, _friendlyName, _connectionStringFields) { } diff --git a/Oqtane.Server/Databases/SqlServerDatabase.cs b/Oqtane.Server/Databases/SqlServerDatabase.cs index d7d885c5..cfb852c3 100644 --- a/Oqtane.Server/Databases/SqlServerDatabase.cs +++ b/Oqtane.Server/Databases/SqlServerDatabase.cs @@ -10,15 +10,16 @@ namespace Oqtane.Databases public class SqlServerDatabase : SqlServerDatabaseBase { private static string _friendlyName => "SQL Server"; + private static string _name => "SqlServer"; private static readonly List _connectionStringFields = new() { - new() {Name = "Server", FriendlyName = "Server", Value = "."}, - new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}"}, - new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true"}, - new() {Name = "Uid", FriendlyName = "User Id", Value = ""}, - new() {Name = "Pwd", FriendlyName = "Password", Value = ""} + new() {Name = "Server", FriendlyName = "Server", Value = ".", HelpText="Enter the database server"}, + new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"}, + new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"}, + new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"}, + new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"} }; public SqlServerDatabase() :base(_name, _friendlyName, _connectionStringFields) { } diff --git a/Oqtane.Server/Databases/SqlServerDatabaseBase.cs b/Oqtane.Server/Databases/SqlServerDatabaseBase.cs index 151f6837..70d3de3a 100644 --- a/Oqtane.Server/Databases/SqlServerDatabaseBase.cs +++ b/Oqtane.Server/Databases/SqlServerDatabaseBase.cs @@ -2,36 +2,27 @@ using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Databases; using Oqtane.Interfaces; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Repository.Databases { - public abstract class SqlServerDatabaseBase : IOqtaneDatabase + public abstract class SqlServerDatabaseBase : OqtaneDatabaseBase { - protected SqlServerDatabaseBase(string name, string friendlyName, List connectionStringFields) + protected SqlServerDatabaseBase(string name, string friendlyName, List connectionStringFields) : base(name, friendlyName, connectionStringFields) { - Name = name; - FriendlyName = friendlyName; - ConnectionStringFields = connectionStringFields; } - public string FriendlyName { get; } + public override string Provider => "Microsoft.EntityFrameworkCore.SqlServer"; - public string Name { get; } - - public string Provider => "Microsoft.EntityFrameworkCore.SqlServer"; - - public List ConnectionStringFields { get; } - - public OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + public override OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) { return table.Column(name: name, nullable: false).Annotation("SqlServer:Identity", "1, 1"); } - public abstract string BuildConnectionString(); - - public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) + public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString) { return optionsBuilder.UseSqlServer(connectionString); } diff --git a/Oqtane.Server/Migrations/01000000_InitializeMaster.cs b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs index 064cda71..1338686a 100644 --- a/Oqtane.Server/Migrations/01000000_InitializeMaster.cs +++ b/Oqtane.Server/Migrations/01000000_InitializeMaster.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; -using Oqtane.Migrations.Extensions; using Oqtane.Repository; namespace Oqtane.Migrations diff --git a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs index 3801cc3e..6afdf29f 100644 --- a/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs +++ b/Oqtane.Server/Migrations/01000100_AddAdditionalIndexesInTenant.cs @@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Oqtane.Interfaces; using Oqtane.Migrations.EntityBuilders; -using Oqtane.Migrations.Extensions; using Oqtane.Repository; namespace Oqtane.Migrations diff --git a/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs index 1de51146..f41cb26e 100644 --- a/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs +++ b/Oqtane.Server/Migrations/01000101_AddAdditionColumnToNotifications.cs @@ -21,12 +21,8 @@ namespace Oqtane.Migrations var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase); notificationEntityBuilder.AddDateTimeColumn("SendOn", true); - migrationBuilder.Sql( - @" - UPDATE Notification - SET SendOn = CreatedOn - WHERE SendOn IS NULL; - "); + //Update new Column + notificationEntityBuilder.UpdateColumn("SendOn", $"{ActiveDatabase.RewriteName("CreatedOn")}", $"{ActiveDatabase.RewriteName("SendOn")} IS NULL"); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs index 6546e71a..d7a13fb2 100644 --- a/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs +++ b/Oqtane.Server/Migrations/02000001_AddColumnToProfileAndUpdatePage.cs @@ -21,11 +21,8 @@ namespace Oqtane.Migrations var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); profileEntityBuilder.AddStringColumn("Options", 2000, true); - migrationBuilder.Sql( - @" - UPDATE Profile - SET Options = '' - "); + //Update new column + profileEntityBuilder.UpdateColumn("Options", "''"); //Alter Column in Page table for Sql Server if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") diff --git a/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs index 2b3a9e77..f0dfd972 100644 --- a/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs +++ b/Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Oqtane.Interfaces; +using Oqtane.Migrations.EntityBuilders; using Oqtane.Repository; namespace Oqtane.Migrations @@ -17,12 +18,9 @@ namespace Oqtane.Migrations protected override void Up(MigrationBuilder migrationBuilder) { ///Update Icon Field in Page - migrationBuilder.Sql( - @" - UPDATE Page - SET Icon = 'oi oi-' + Icon - WHERE Icon <> '' - "); + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); + var updateSql = ActiveDatabase.ConcatenateSql("'oi oi-'", $"{ActiveDatabase.RewriteName("Icon")}"); + pageEntityBuilder.UpdateColumn("Icon", updateSql, $"{ActiveDatabase.RewriteName("Icon")} <> ''" ); } } } diff --git a/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs index 041f407a..740b671a 100644 --- a/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs +++ b/Oqtane.Server/Migrations/02000103_UpdatePageAndAddColumnToSite.cs @@ -22,19 +22,12 @@ namespace Oqtane.Migrations siteEntityBuilder.AddStringColumn("AdminContainerType", 200, true); //Update new column - migrationBuilder.Sql( - @" - UPDATE Site - SET AdminContainerType = '' - "); + siteEntityBuilder.UpdateColumn("AdminContainerType", "''"); + //Delete records from Page - migrationBuilder.Sql( - @" - DELETE FROM Page - WHERE Path = 'admin/tenants' - "); - + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); + pageEntityBuilder.DeleteFromTable($"{ActiveDatabase.RewriteName("Path")} = 'admin/tenants'"); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs index 388e95d5..f57b302f 100644 --- a/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs +++ b/Oqtane.Server/Migrations/02010001_AddDatabaseTypeColumnToTenant.cs @@ -24,13 +24,8 @@ namespace Oqtane.Migrations //Update new column if SqlServer (Other Databases will not have any records yet) if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { - migrationBuilder.Sql(@" - UPDATE Tenant - SET DBType = 'SqlServer' - "); - + tenantEntityBuilder.UpdateColumn("DBType", "'SqlServer'"); } - } } } diff --git a/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs index d2d35188..2e05d58a 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AliasEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,10 +23,10 @@ namespace Oqtane.Migrations.EntityBuilders protected override AliasEntityBuilder BuildTable(ColumnsBuilder table) { - AliasId = ActiveDatabase.AddAutoIncrementColumn(table,"AliasId"); - Name = table.AddStringColumn("Name", 200); - TenantId = table.AddIntegerColumn("TenantId"); - SiteId = table.AddIntegerColumn("SiteId"); + AliasId = AddAutoIncrementColumn(table,"AliasId"); + Name = AddStringColumn(table, "Name", 200); + TenantId = AddIntegerColumn(table, "TenantId"); + SiteId = AddIntegerColumn(table, "SiteId"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs index 1a6fffce..bf53614c 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUserClaimsEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,10 +23,10 @@ namespace Oqtane.Migrations.EntityBuilders protected override AspNetUserClaimsEntityBuilder BuildTable(ColumnsBuilder table) { - Id = ActiveDatabase.AddAutoIncrementColumn(table,"Id"); - UserId = table.AddStringColumn("UserId", 450); - ClaimType = table.AddMaxStringColumn("ClaimType", true); - ClaimValue = table.AddMaxStringColumn("ClaimValue", true); + Id = AddAutoIncrementColumn(table,"Id"); + UserId = AddStringColumn(table,"UserId", 450); + ClaimType = AddMaxStringColumn(table,"ClaimType", true); + ClaimValue = AddMaxStringColumn(table,"ClaimValue", true); return this; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs index 9a071297..dec56d2d 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AspNetUsersEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,21 +21,21 @@ namespace Oqtane.Migrations.EntityBuilders protected override AspNetUsersEntityBuilder BuildTable(ColumnsBuilder table) { - Id = table.AddStringColumn("Id", 450); - UserName = table.AddStringColumn("Username", 256, true); - NormalizedUserName = table.AddStringColumn("NormalizedUserName", 256, true); - Email = table.AddStringColumn("Email", 256, true); - NormalizedEmail = table.AddStringColumn("NormalizedEmail", 256, true); - EmailConfirmed = table.AddBooleanColumn("EmailConfirmed"); - PasswordHash = table.AddMaxStringColumn("PasswordHash", true); - SecurityStamp = table.AddMaxStringColumn("SecurityStamp", true); - ConcurrencyStamp = table.AddMaxStringColumn("ConcurrencyStamp", true); - PhoneNumber = table.AddMaxStringColumn("PhoneNumber", true); - PhoneNumberConfirmed = table.AddBooleanColumn("PhoneNumberConfirmed"); - TwoFactorEnabled = table.AddBooleanColumn("TwoFactorEnabled"); - LockoutEnd = table.AddDateTimeOffsetColumn("LockoutEnd", true); - LockoutEnabled = table.AddBooleanColumn("LockoutEnabled"); - AccessFailedCount = table.AddIntegerColumn("AccessFailedCount"); + Id = AddStringColumn(table,"Id", 450); + UserName = AddStringColumn(table,"UserName", 256, true); + NormalizedUserName = AddStringColumn(table,"NormalizedUserName", 256, true); + Email = AddStringColumn(table,"Email", 256, true); + NormalizedEmail = AddStringColumn(table,"NormalizedEmail", 256, true); + EmailConfirmed = AddBooleanColumn(table,"EmailConfirmed"); + PasswordHash = AddMaxStringColumn(table,"PasswordHash", true); + SecurityStamp = AddMaxStringColumn(table,"SecurityStamp", true); + ConcurrencyStamp = AddMaxStringColumn(table,"ConcurrencyStamp", true); + PhoneNumber = AddMaxStringColumn(table,"PhoneNumber", true); + PhoneNumberConfirmed = AddBooleanColumn(table,"PhoneNumberConfirmed"); + TwoFactorEnabled = AddBooleanColumn(table,"TwoFactorEnabled"); + LockoutEnd = AddDateTimeOffsetColumn(table,"LockoutEnd", true); + LockoutEnabled = AddBooleanColumn(table,"LockoutEnabled"); + AccessFailedCount = AddIntegerColumn(table,"AccessFailedCount"); return this; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs index f92bffcc..cad1a993 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/AuditableBaseEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global @@ -17,10 +16,10 @@ namespace Oqtane.Migrations.EntityBuilders protected void AddAuditableColumns(ColumnsBuilder table) { - CreatedBy = table.AddStringColumn("CreatedBy", 256); - CreatedOn = table.AddDateTimeColumn("CreatedOn"); - ModifiedBy = table.AddStringColumn("ModifiedBy", 256); - ModifiedOn = table.AddDateTimeColumn("ModifiedOn"); + CreatedBy = AddStringColumn(table,"CreatedBy", 256); + CreatedOn = AddDateTimeColumn(table,"CreatedOn"); + ModifiedBy = AddStringColumn(table,"ModifiedBy", 256); + ModifiedOn = AddDateTimeColumn(table,"ModifiedOn"); } diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs index 078c74a7..42264996 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess namespace Oqtane.Migrations.EntityBuilders { @@ -18,15 +20,6 @@ namespace Oqtane.Migrations.EntityBuilders ForeignKeys = new List>(); } - private void AddKeys(CreateTableBuilder table) - { - table.AddPrimaryKey(PrimaryKey); - foreach (var foreignKey in ForeignKeys) - { - table.AddForeignKey(foreignKey); - } - } - protected IOqtaneDatabase ActiveDatabase { get; } protected abstract TEntityBuilder BuildTable(ColumnsBuilder table); @@ -37,16 +30,92 @@ namespace Oqtane.Migrations.EntityBuilders protected List> ForeignKeys { get; } + private string RewriteName(string name) + { + return ActiveDatabase.RewriteName(name); + } + + + // Column Operations + + protected OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name) + { + return ActiveDatabase.AddAutoIncrementColumn(table, RewriteName(name)); + } + public void AddBooleanColumn(string name) { - _migrationBuilder.AddColumn(name, EntityTableName); + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName)); + } + + protected OperationBuilder AddBooleanColumn(ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: RewriteName(name), nullable: nullable); } public void AddDateTimeColumn(string name, bool nullable = false) { - _migrationBuilder.AddColumn(name, EntityTableName, nullable: nullable); + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable); } + protected OperationBuilder AddDateTimeColumn(ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: RewriteName(name), nullable: nullable); + } + + public void AddDateTimeOffsetColumn(string name, bool nullable = false) + { + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable); + } + + protected OperationBuilder AddDateTimeOffsetColumn(ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: RewriteName(name), nullable: nullable); + } + + public void AddIntegerColumn(string name, bool nullable = false) + { + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable); + } + + protected OperationBuilder AddIntegerColumn(ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: RewriteName(name), nullable: nullable); + } + + public void AddMaxStringColumn(string name, int length, bool nullable = false) + { + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: true); + } + + protected OperationBuilder AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false) + { + return table.Column(name: RewriteName(name), nullable: nullable, unicode: true); + } + + public void AddStringColumn(string name, int length, bool nullable = false) + { + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: true); + } + + protected OperationBuilder AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false) + { + return table.Column(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: true); + } + + public void AlterStringColumn(string name, int length, bool nullable = false) + { + _migrationBuilder.AlterColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable); + } + + public void DropColumn(string name) + { + _migrationBuilder.DropColumn(RewriteName(name), RewriteName(EntityTableName)); + } + + + //Index Operations + /// /// Creates a Migration to add an Index to the Entity (table) /// @@ -56,9 +125,9 @@ namespace Oqtane.Migrations.EntityBuilders public virtual void AddIndex(string indexName, string columnName, bool isUnique = false) { _migrationBuilder.CreateIndex( - name: indexName, - table: EntityTableName, - column: columnName, + name: RewriteName(indexName), + table: RewriteName(EntityTableName), + column: RewriteName(columnName), unique: isUnique); } @@ -66,55 +135,107 @@ namespace Oqtane.Migrations.EntityBuilders /// Creates a Migration to add an Index to the Entity (table) /// /// The name of the Index to create - /// The names of the columns to add to the index + /// The names of the columns to add to the index /// A flag that determines if the Index should be Unique public virtual void AddIndex(string indexName, string[] columnNames, bool isUnique = false) { _migrationBuilder.CreateIndex( - name: indexName, - table: EntityTableName, - columns: columnNames, + name: RewriteName(indexName), + table: RewriteName(EntityTableName), + columns: columnNames.Select(RewriteName).ToArray(), unique: isUnique); } - public void AddStringColumn(string name, int length, bool nullable = false) - { - _migrationBuilder.AddColumn(name, EntityTableName, maxLength: length, nullable: nullable); - } - - public void AlterStringColumn(string name, int length, bool nullable = false) - { - _migrationBuilder.AlterColumn(name, EntityTableName, maxLength: length, nullable: nullable); - } - - /// - /// Creates a Migration to Create the Entity (table) - /// - public void Create() - { - _migrationBuilder.CreateTable(EntityTableName, BuildTable, null, AddKeys); - } - - /// - /// Creates a Migration to Drop the Entity (table) - /// - public void Drop() - { - _migrationBuilder.DropTable(EntityTableName); - } - - public void DropColumn(string name) - { - _migrationBuilder.DropColumn(name, EntityTableName); - } - /// /// Creates a Migration to drop an Index from the Entity (table) /// /// The name of the Index to drop public virtual void DropIndex(string indexName) { - _migrationBuilder.DropIndex(indexName, EntityTableName); + _migrationBuilder.DropIndex(RewriteName(indexName), RewriteName(EntityTableName)); + } + + + // Key Operations + + private void AddKeys(CreateTableBuilder table) + { + AddPrimaryKey(table, PrimaryKey); + foreach (var foreignKey in ForeignKeys) + { + AddForeignKey(table, foreignKey); + } + } + + public void AddPrimaryKey(CreateTableBuilder table, PrimaryKey primaryKey) + { + table.PrimaryKey(RewriteName(primaryKey.Name), primaryKey.Columns); + } + + public void AddForeignKey(CreateTableBuilder table, ForeignKey foreignKey) + { + table.ForeignKey( + name: RewriteName(foreignKey.Name), + column: foreignKey.Column, + principalTable: RewriteName(foreignKey.PrincipalTable), + principalColumn: RewriteName(foreignKey.PrincipalColumn), + onDelete: foreignKey.OnDeleteAction); + } + + public void DropForeignKey(ForeignKey foreignKey) + { + DropForeignKey(RewriteName(foreignKey.Name)); + } + + public void DropForeignKey(string keyName) + { + _migrationBuilder.DropForeignKey(RewriteName(keyName), RewriteName(EntityTableName)); + } + + + // Table Operations + + /// + /// Creates a Migration to Create the Entity (table) + /// + public void Create() + { + _migrationBuilder.CreateTable(RewriteName(EntityTableName), BuildTable, null, AddKeys); + } + + /// + /// Creates a Migration to Drop the Entity (table) + /// + public void Drop() + { + _migrationBuilder.DropTable(RewriteName(EntityTableName)); + } + + + //Sql Operations + + public void DeleteFromTable(string condition = "") + { + var deleteSql = $"DELETE FROM {RewriteName(EntityTableName)} "; + + if(!string.IsNullOrEmpty(condition)) + { + deleteSql += $"WHERE {condition}"; + } + _migrationBuilder.Sql(deleteSql); + } + + public void UpdateColumn(string columnName, string value, string condition = "") + { + var updateValue = value; + + var updateSql = $"UPDATE {RewriteName(EntityTableName)} SET {RewriteName(columnName)} = {value} "; + + if(!string.IsNullOrEmpty(condition)) + { + updateSql += $"WHERE {condition}"; + } + _migrationBuilder.Sql(updateSql); } } } diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs index e5bfac03..afe9627e 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableAuditableBaseEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global @@ -17,9 +16,9 @@ namespace Oqtane.Migrations.EntityBuilders protected void AddDeletableColumns(ColumnsBuilder table) { - DeletedBy = table.AddStringColumn("DeletedBy", 256, true); - DeletedOn = table.AddDateTimeColumn("DeletedOn", true); - IsDeleted = table.AddBooleanColumn("IsDeleted"); + DeletedBy = AddStringColumn(table,"DeletedBy", 256, true); + DeletedOn = AddDateTimeColumn(table,"DeletedOn", true); + IsDeleted = AddBooleanColumn(table,"IsDeleted"); } public OperationBuilder DeletedBy { get; private set; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs index 0fe98b66..3ff98429 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/DeletableBaseEntityBuilder.cs @@ -1,9 +1,8 @@ -using System; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; + // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global @@ -17,9 +16,9 @@ namespace Oqtane.Migrations.EntityBuilders protected void AddDeletableColumns(ColumnsBuilder table) { - DeletedBy = table.AddStringColumn("DeletedBy", 256, true); - DeletedOn = table.AddDateTimeColumn("DeletedOn", true); - IsDeleted = table.AddBooleanColumn("IsDeleted"); + DeletedBy = AddStringColumn(table,"DeletedBy", 256, true); + DeletedOn = AddDateTimeColumn(table,"DeletedOn", true); + IsDeleted = AddBooleanColumn(table,"IsDeleted"); } public OperationBuilder DeletedBy { get; private set; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs index 3eb95051..f875fb0b 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,13 +23,13 @@ namespace Oqtane.Migrations.EntityBuilders protected override FileEntityBuilder BuildTable(ColumnsBuilder table) { - FileId = ActiveDatabase.AddAutoIncrementColumn(table,"FileId"); - FolderId = table.AddIntegerColumn("FolderId"); - Name = table.AddStringColumn("Name", 50); - Extension = table.AddStringColumn("Extension", 50); - Size = table.AddIntegerColumn("Size"); - ImageHeight = table.AddIntegerColumn("ImageHeight"); - ImageWidth = table.AddIntegerColumn("ImageWidth"); + FileId = AddAutoIncrementColumn(table,"FileId"); + FolderId = AddIntegerColumn(table,"FolderId"); + Name = AddStringColumn(table,"Name", 50); + Extension = AddStringColumn(table,"Extension", 50); + Size = AddIntegerColumn(table,"Size"); + ImageHeight = AddIntegerColumn(table,"ImageHeight"); + ImageWidth = AddIntegerColumn(table,"ImageWidth"); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs index 8da9514e..e8da5831 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/FolderEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,13 +23,13 @@ namespace Oqtane.Migrations.EntityBuilders protected override FolderEntityBuilder BuildTable(ColumnsBuilder table) { - FolderId = ActiveDatabase.AddAutoIncrementColumn(table,"FolderId"); - SiteId = table.AddIntegerColumn("SiteId"); - ParentId = table.AddIntegerColumn("ParentId", true); - Name = table.AddStringColumn("Name", 50); - Path = table.AddStringColumn("Path", 50); - Order = table.AddIntegerColumn("Order"); - IsSystem = table.AddBooleanColumn("IsSystem"); + FolderId = AddAutoIncrementColumn(table,"FolderId"); + SiteId = AddIntegerColumn(table,"SiteId"); + ParentId = AddIntegerColumn(table,"ParentId", true); + Name = AddStringColumn(table,"Name", 50); + Path = AddStringColumn(table,"Path", 50); + Order = AddIntegerColumn(table,"Order"); + IsSystem = AddBooleanColumn(table,"IsSystem"); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs index 066468ef..34cffd74 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,18 +21,18 @@ namespace Oqtane.Migrations.EntityBuilders protected override JobEntityBuilder BuildTable(ColumnsBuilder table) { - JobId = ActiveDatabase.AddAutoIncrementColumn(table,"JobId"); - Name = table.AddStringColumn("Name", 200); - JobType = table.AddStringColumn("JobType", 200); - Frequency = table.AddStringColumn("Frequency", 1); - Interval = table.AddIntegerColumn("Interval"); - StartDate = table.AddDateTimeColumn("StartDate", true); - EndDate = table.AddDateTimeColumn("EndDate", true); - IsEnabled = table.AddBooleanColumn("IsEnabled"); - IsStarted = table.AddBooleanColumn("IsStarted"); - IsExecuting = table.AddBooleanColumn("IsExecuting"); - NextExecution = table.AddDateTimeColumn("NextExecution", true); - RetentionHistory = table.AddIntegerColumn("RetentionHistory"); + JobId = AddAutoIncrementColumn(table,"JobId"); + Name = AddStringColumn(table,"Name", 200); + JobType = AddStringColumn(table,"JobType", 200); + Frequency = AddStringColumn(table,"Frequency", 1); + Interval = AddIntegerColumn(table,"Interval"); + StartDate = AddDateTimeColumn(table,"StartDate", true); + EndDate = AddDateTimeColumn(table,"EndDate", true); + IsEnabled = AddBooleanColumn(table,"IsEnabled"); + IsStarted = AddBooleanColumn(table,"IsStarted"); + IsExecuting = AddBooleanColumn(table,"IsExecuting"); + NextExecution = AddDateTimeColumn(table,"NextExecution", true); + RetentionHistory = AddIntegerColumn(table,"RetentionHistory"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs index d4082706..f73f8aa0 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/JobLogEntityBuilder.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; + // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -23,12 +23,12 @@ namespace Oqtane.Migrations.EntityBuilders protected override JobLogEntityBuilder BuildTable(ColumnsBuilder table) { - JobLogId = ActiveDatabase.AddAutoIncrementColumn(table,"JobLogId"); - JobId = table.AddIntegerColumn("JobId"); - StartDate = table.AddDateTimeColumn("StartDate"); - FinishDate = table.AddDateTimeColumn("FinishDate", true); - Succeeded = table.AddBooleanColumn("Succeeded", true); - Notes = table.AddMaxStringColumn("Notes", true); + JobLogId = AddAutoIncrementColumn(table,"JobLogId"); + JobId = AddIntegerColumn(table,"JobId"); + StartDate = AddDateTimeColumn(table,"StartDate"); + FinishDate = AddDateTimeColumn(table,"FinishDate", true); + Succeeded = AddBooleanColumn(table,"Succeeded", true); + Notes = AddMaxStringColumn(table,"Notes", true); return this; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs index 8cf622a3..44342abd 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/LanguageEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,11 +23,11 @@ namespace Oqtane.Migrations.EntityBuilders protected override LanguageEntityBuilder BuildTable(ColumnsBuilder table) { - LanguageId = ActiveDatabase.AddAutoIncrementColumn(table,"LanguageId"); - SiteId = table.AddIntegerColumn("SiteId"); - Name = table.AddStringColumn("Name", 100); - Code = table.AddStringColumn("Code", 10); - IsDefault = table.AddBooleanColumn("IsDefault"); + LanguageId = AddAutoIncrementColumn(table,"LanguageId"); + SiteId = AddIntegerColumn(table,"SiteId"); + Name = AddStringColumn(table,"Name", 100); + Code = AddStringColumn(table,"Code", 10); + IsDefault = AddBooleanColumn(table,"IsDefault"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs index e1a8ad33..f06feace 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,22 +23,22 @@ namespace Oqtane.Migrations.EntityBuilders protected override LogEntityBuilder BuildTable(ColumnsBuilder table) { - LogId = ActiveDatabase.AddAutoIncrementColumn(table,"LogId"); - SiteId = table.AddIntegerColumn("SiteId", true); - LogDate = table.AddDateTimeColumn("LogDate"); - PageId = table.AddIntegerColumn("PageId", true); - ModuleId = table.AddIntegerColumn("ModuleId", true); - UserId = table.AddIntegerColumn("UserId", true); - Url = table.AddStringColumn("Url", 2048); - Server = table.AddStringColumn("Server", 200); - Category = table.AddStringColumn("Category", 200); - Feature = table.AddStringColumn("Feature", 200); - Function = table.AddStringColumn("Function", 20); - Level = table.AddStringColumn("Level", 20); - Message = table.AddMaxStringColumn("Message"); - MessageTemplate = table.AddMaxStringColumn("MessageTemplate"); - Exception = table.AddMaxStringColumn("Exception", true); - Properties = table.AddMaxStringColumn("Properties", true); + LogId = AddAutoIncrementColumn(table,"LogId"); + SiteId = AddIntegerColumn(table,"SiteId", true); + LogDate = AddDateTimeColumn(table,"LogDate"); + PageId = AddIntegerColumn(table,"PageId", true); + ModuleId = AddIntegerColumn(table,"ModuleId", true); + UserId = AddIntegerColumn(table,"UserId", true); + Url = AddStringColumn(table,"Url", 2048); + Server = AddStringColumn(table,"Server", 200); + Category = AddStringColumn(table,"Category", 200); + Feature = AddStringColumn(table,"Feature", 200); + Function = AddStringColumn(table,"Function", 20); + Level = AddStringColumn(table,"Level", 20); + Message = AddMaxStringColumn(table,"Message"); + MessageTemplate = AddMaxStringColumn(table,"MessageTemplate"); + Exception = AddMaxStringColumn(table,"Exception", true); + Properties = AddMaxStringColumn(table,"Properties", true); return this; } diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs index d4891453..7dad6645 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleDefinitionsEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,12 +21,12 @@ namespace Oqtane.Migrations.EntityBuilders protected override ModuleDefinitionsEntityBuilder BuildTable(ColumnsBuilder table) { - ModuleDefinitionId = ActiveDatabase.AddAutoIncrementColumn(table,"ModuleDefinitionId"); - ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); - Name = table.AddStringColumn("Name", 200, true); - Description = table.AddStringColumn("Description", 2000, true); - Categories = table.AddStringColumn("Categories", 200, true); - Version = table.AddStringColumn("Version", 50, true); + ModuleDefinitionId = AddAutoIncrementColumn(table,"ModuleDefinitionId"); + ModuleDefinitionName = AddStringColumn(table,"ModuleDefinitionName", 200); + Name = AddStringColumn(table,"Name", 200, true); + Description = AddStringColumn(table,"Description", 2000, true); + Categories = AddStringColumn(table,"Categories", 200, true); + Version = AddStringColumn(table,"Version", 50, true); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs index 2bda7316..98ac7577 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ModuleEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,10 +23,10 @@ namespace Oqtane.Migrations.EntityBuilders protected override ModuleEntityBuilder BuildTable(ColumnsBuilder table) { - ModuleId = ActiveDatabase.AddAutoIncrementColumn(table,"ModuleId"); - SiteId = table.AddIntegerColumn("SiteId"); - ModuleDefinitionName = table.AddStringColumn("ModuleDefinitionName", 200); - AllPages = table.AddBooleanColumn("AllPages"); + ModuleId = AddAutoIncrementColumn(table,"ModuleId"); + SiteId = AddIntegerColumn(table,"SiteId"); + ModuleDefinitionName = AddStringColumn(table,"ModuleDefinitionName", 200); + AllPages = AddBooleanColumn(table,"AllPages"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs index f3866af9..1a38a07c 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/NotificationEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,17 +23,17 @@ namespace Oqtane.Migrations.EntityBuilders protected override NotificationEntityBuilder BuildTable(ColumnsBuilder table) { - NotificationId = ActiveDatabase.AddAutoIncrementColumn(table,"NotificationId"); - SiteId = table.AddIntegerColumn("SiteId"); - FromUserId = table.AddIntegerColumn("FromUserId", true); - ToUserId = table.AddIntegerColumn("ToUserId", true); - ToEmail = table.AddStringColumn("ToEmail", 256); - ParentId = table.AddIntegerColumn("ParentId", true); - Subject = table.AddStringColumn("Subject", 256); - Body = table.AddMaxStringColumn("Body"); - CreatedOn = table.AddDateTimeColumn("CreatedOn"); - IsDelivered = table.AddBooleanColumn("IsDelivered"); - DeliveredOn = table.AddDateTimeColumn("DeliveredOn", true); + NotificationId = AddAutoIncrementColumn(table,"NotificationId"); + SiteId = AddIntegerColumn(table,"SiteId"); + FromUserId = AddIntegerColumn(table,"FromUserId", true); + ToUserId = AddIntegerColumn(table,"ToUserId", true); + ToEmail = AddStringColumn(table,"ToEmail", 256); + ParentId = AddIntegerColumn(table,"ParentId", true); + Subject = AddStringColumn(table,"Subject", 256); + Body = AddMaxStringColumn(table,"Body"); + CreatedOn = AddDateTimeColumn(table,"CreatedOn"); + IsDelivered = AddBooleanColumn(table,"IsDelivered"); + DeliveredOn = AddDateTimeColumn(table,"DeliveredOn", true); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs index ff1d57a3..b1cee2e9 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,28 +23,28 @@ namespace Oqtane.Migrations.EntityBuilders protected override PageEntityBuilder BuildTable(ColumnsBuilder table) { - PageId = ActiveDatabase.AddAutoIncrementColumn(table,"PageId"); - SiteId = table.AddIntegerColumn("SiteId"); + PageId = AddAutoIncrementColumn(table,"PageId"); + SiteId = AddIntegerColumn(table,"SiteId"); if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") { - Path = table.AddStringColumn("Path", 50); + Path = AddStringColumn(table,"Path", 50); } else { - Path = table.AddStringColumn("Path", 256); + Path = AddStringColumn(table,"Path", 256); } - Name = table.AddStringColumn("Name", 50); - Title = table.AddStringColumn("Title", 200, true); - ThemeType = table.AddStringColumn("ThemeType", 200, true); - Icon = table.AddStringColumn("Icon", 50); - ParentId = table.AddIntegerColumn("ParentId", true); - Order = table.AddIntegerColumn("Order"); - IsNavigation = table.AddBooleanColumn("IsNavigation"); - Url = table.AddStringColumn("Url", 500, true); - LayoutType = table.AddStringColumn("LayoutType", 200); - UserId = table.AddIntegerColumn("UserId", true); - IsPersonalizable = table.AddBooleanColumn("IsPersonalizable"); - DefaultContainerType = table.AddStringColumn("DefaultContainerType", 200, true); + Name = AddStringColumn(table,"Name", 50); + Title = AddStringColumn(table,"Title", 200, true); + ThemeType = AddStringColumn(table,"ThemeType", 200, true); + Icon = AddStringColumn(table,"Icon", 50); + ParentId = AddIntegerColumn(table,"ParentId", true); + Order = AddIntegerColumn(table,"Order"); + IsNavigation = AddBooleanColumn(table,"IsNavigation"); + Url = AddStringColumn(table,"Url", 500, true); + LayoutType = AddStringColumn(table,"LayoutType", 200); + UserId = AddIntegerColumn(table,"UserId", true); + IsPersonalizable = AddBooleanColumn(table,"IsPersonalizable"); + DefaultContainerType = AddStringColumn(table,"DefaultContainerType", 200, true); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs index 66fdd39f..16ea23fb 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PageModuleEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -26,13 +25,13 @@ namespace Oqtane.Migrations.EntityBuilders protected override PageModuleEntityBuilder BuildTable(ColumnsBuilder table) { - PageModuleId = ActiveDatabase.AddAutoIncrementColumn(table,"PageModuleId"); - PageId = table.AddIntegerColumn("PageId"); - ModuleId = table.AddIntegerColumn("ModuleId"); - Title = table.AddStringColumn("Title", 200); - Pane = table.AddStringColumn("Pane", 50); - Order = table.AddIntegerColumn("Order"); - ContainerType = table.AddStringColumn("ContainerType", 200); + PageModuleId = AddAutoIncrementColumn(table,"PageModuleId"); + PageId = AddIntegerColumn(table,"PageId"); + ModuleId = AddIntegerColumn(table,"ModuleId"); + Title = AddStringColumn(table,"Title", 200); + Pane = AddStringColumn(table,"Pane", 50); + Order = AddIntegerColumn(table,"Order"); + ContainerType = AddStringColumn(table,"ContainerType", 200); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs index 5636062b..f5f21473 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/PermissionEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -28,14 +27,14 @@ namespace Oqtane.Migrations.EntityBuilders protected override PermissionEntityBuilder BuildTable(ColumnsBuilder table) { - PermissionId = ActiveDatabase.AddAutoIncrementColumn(table,"PermissionId"); - SiteId = table.AddIntegerColumn("SiteId"); - EntityName = table.AddStringColumn("EntityName", 50); - EntityId = table.AddIntegerColumn("EntityId"); - PermissionName = table.AddStringColumn("PermissionName", 50); - RoleId = table.AddIntegerColumn("RoleId", true); - UserId = table.AddIntegerColumn("UserId", true); - IsAuthorized = table.AddBooleanColumn("IsAuthorized"); + PermissionId = AddAutoIncrementColumn(table,"PermissionId"); + SiteId = AddIntegerColumn(table,"SiteId"); + EntityName = AddStringColumn(table,"EntityName", 50); + EntityId = AddIntegerColumn(table,"EntityId"); + PermissionName = AddStringColumn(table,"PermissionName", 50); + RoleId = AddIntegerColumn(table,"RoleId", true); + UserId = AddIntegerColumn(table,"UserId", true); + IsAuthorized = AddBooleanColumn(table,"IsAuthorized"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs index ca57a939..593242a7 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/ProfileEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,17 +23,17 @@ namespace Oqtane.Migrations.EntityBuilders protected override ProfileEntityBuilder BuildTable(ColumnsBuilder table) { - ProfileId = ActiveDatabase.AddAutoIncrementColumn(table,"ProfileId"); - SiteId = table.AddIntegerColumn("SiteId", true); - Name = table.AddStringColumn("Name", 50); - Title = table.AddStringColumn("Title", 50); - Description = table.AddStringColumn("Description", 256, true); - Category = table.AddStringColumn("Category", 50); - ViewOrder = table.AddIntegerColumn("ViewOrder"); - MaxLength = table.AddIntegerColumn("MaxLength"); - DefaultValue = table.AddStringColumn("DefaultValue", 2000, true); - IsRequired = table.AddBooleanColumn("IsRequired"); - IsPrivate = table.AddBooleanColumn("IsPrivate"); + ProfileId = AddAutoIncrementColumn(table,"ProfileId"); + SiteId = AddIntegerColumn(table,"SiteId", true); + Name = AddStringColumn(table,"Name", 50); + Title = AddStringColumn(table,"Title", 50); + Description = AddStringColumn(table,"Description", 256, true); + Category = AddStringColumn(table,"Category", 50); + ViewOrder = AddIntegerColumn(table,"ViewOrder"); + MaxLength = AddIntegerColumn(table,"MaxLength"); + DefaultValue = AddStringColumn(table,"DefaultValue", 2000, true); + IsRequired = AddBooleanColumn(table,"IsRequired"); + IsPrivate = AddBooleanColumn(table,"IsPrivate"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs index dd9956d6..52feffa8 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,12 +23,12 @@ namespace Oqtane.Migrations.EntityBuilders protected override RoleEntityBuilder BuildTable(ColumnsBuilder table) { - RoleId = ActiveDatabase.AddAutoIncrementColumn(table,"RoleId"); - SiteId = table.AddIntegerColumn("SiteId", true); - Name = table.AddStringColumn("Name", 256); - Description = table.AddStringColumn("Description", 256); - IsAutoAssigned = table.AddBooleanColumn("IsAutoAssigned"); - IsSystem = table.AddBooleanColumn("IsSystem"); + RoleId = AddAutoIncrementColumn(table,"RoleId"); + SiteId = AddIntegerColumn(table,"SiteId", true); + Name = AddStringColumn(table,"Name", 256); + Description = AddStringColumn(table,"Description", 256); + IsAutoAssigned = AddBooleanColumn(table,"IsAutoAssigned"); + IsSystem = AddBooleanColumn(table,"IsSystem"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs index 31d32806..4956203f 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SettingEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,11 +21,11 @@ namespace Oqtane.Migrations.EntityBuilders protected override SettingEntityBuilder BuildTable(ColumnsBuilder table) { - SettingId = ActiveDatabase.AddAutoIncrementColumn(table,"SettingId"); - EntityName = table.AddStringColumn("EntityName", 50); - EntityId = table.AddIntegerColumn("EntityId"); - SettingName = table.AddStringColumn("SettingName", 50); - SettingValue = table.AddMaxStringColumn("SettingValue"); + SettingId = AddAutoIncrementColumn(table,"SettingId"); + EntityName = AddStringColumn(table,"EntityName", 50); + EntityId = AddIntegerColumn(table,"EntityId"); + SettingName = AddStringColumn(table,"SettingName", 50); + SettingValue = AddMaxStringColumn(table,"SettingValue"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs index c6773c4e..cce461e7 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,18 +21,18 @@ namespace Oqtane.Migrations.EntityBuilders protected override SiteEntityBuilder BuildTable(ColumnsBuilder table) { - SiteId = ActiveDatabase.AddAutoIncrementColumn(table,"SiteId"); - TenantId = table.AddIntegerColumn("TenantId"); - Name = table.AddStringColumn("Name", 200); - LogoFileId = table.AddIntegerColumn("LogoFileId", true); - FaviconFileId = table.AddIntegerColumn("FaviconFileId", true); - DefaultThemeType = table.AddStringColumn("DefaultThemeType", 200); - DefaultLayoutType = table.AddStringColumn("DefaultLayoutType", 200); - DefaultContainerType = table.AddStringColumn("DefaultContainerType", 200); - PwaIsEnabled = table.AddBooleanColumn("PwaIsEnabled"); - PwaAppIconFileId = table.AddIntegerColumn("PwaAppIconFileId", true); - PwaSplashIconFileId = table.AddIntegerColumn("PwaSplashIconFileId", true); - AllowRegistration = table.AddBooleanColumn("AllowRegistration"); + SiteId = AddAutoIncrementColumn(table,"SiteId"); + TenantId = AddIntegerColumn(table,"TenantId"); + Name = AddStringColumn(table,"Name", 200); + LogoFileId = AddIntegerColumn(table,"LogoFileId", true); + FaviconFileId = AddIntegerColumn(table,"FaviconFileId", true); + DefaultThemeType = AddStringColumn(table,"DefaultThemeType", 200); + DefaultLayoutType = AddStringColumn(table,"DefaultLayoutType", 200); + DefaultContainerType = AddStringColumn(table,"DefaultContainerType", 200); + PwaIsEnabled = AddBooleanColumn(table,"PwaIsEnabled"); + PwaAppIconFileId = AddIntegerColumn(table,"PwaAppIconFileId", true); + PwaSplashIconFileId = AddIntegerColumn(table,"PwaSplashIconFileId", true); + AllowRegistration = AddBooleanColumn(table,"AllowRegistration"); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs index 794fc2ac..98201072 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/TenantEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,10 +21,10 @@ namespace Oqtane.Migrations.EntityBuilders protected override TenantEntityBuilder BuildTable(ColumnsBuilder table) { - TenantId = ActiveDatabase.AddAutoIncrementColumn(table,"TenantId"); - Name = table.AddStringColumn("Name", 100); - DBConnectionString = table.AddStringColumn("DBConnectionString", 1024); - Version = table.AddStringColumn("Version", 50, true); + TenantId = AddAutoIncrementColumn(table,"TenantId"); + Name = AddStringColumn(table,"Name", 100); + DBConnectionString = AddStringColumn(table,"DBConnectionString", 1024); + Version = AddStringColumn(table,"Version", 50, true); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs index 51a2b78e..d070f027 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -22,13 +21,13 @@ namespace Oqtane.Migrations.EntityBuilders protected override UserEntityBuilder BuildTable(ColumnsBuilder table) { - UserId = ActiveDatabase.AddAutoIncrementColumn(table,"UserId"); - Username = table.AddStringColumn("Username", 256); - DisplayName = table.AddStringColumn("DisplayName", 50); - Email = table.AddStringColumn("Email", 256); - PhotoFileId = table.AddIntegerColumn("PhotoFileId", true); - LastLoginOn = table.AddDateTimeColumn("LastLoginOn", true); - LastIPAddress = table.AddStringColumn("LastIpAddress", 50); + UserId = AddAutoIncrementColumn(table,"UserId"); + Username = AddStringColumn(table,"Username", 256); + DisplayName = AddStringColumn(table,"DisplayName", 50); + Email = AddStringColumn(table,"Email", 256); + PhotoFileId = AddIntegerColumn(table,"PhotoFileId", true); + LastLoginOn = AddDateTimeColumn(table,"LastLoginOn", true); + LastIPAddress = AddStringColumn(table,"LastIpAddress", 50); AddAuditableColumns(table); AddDeletableColumns(table); diff --git a/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs index 88327191..9b112151 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/UserRoleEntityBuilder.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -26,11 +25,11 @@ namespace Oqtane.Migrations.EntityBuilders protected override UserRoleEntityBuilder BuildTable(ColumnsBuilder table) { - UserRoleId = ActiveDatabase.AddAutoIncrementColumn(table,"UserRoleId"); - UserId = table.AddIntegerColumn("UserId"); - RoleId = table.AddIntegerColumn("RoleId"); - EffectiveDate = table.AddDateTimeColumn("EffectiveDate", true); - ExpiryDate = table.AddDateTimeColumn("ExpiryDate", true); + UserRoleId = AddAutoIncrementColumn(table,"UserRoleId"); + UserId = AddIntegerColumn(table,"UserId"); + RoleId = AddIntegerColumn(table,"RoleId"); + EffectiveDate = AddDateTimeColumn(table,"EffectiveDate", true); + ExpiryDate = AddDateTimeColumn(table,"ExpiryDate", true); AddAuditableColumns(table); diff --git a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs deleted file mode 100644 index 068a54ef..00000000 --- a/Oqtane.Server/Migrations/Extensions/ColumnsBuilderExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations.Operations; -using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; - -namespace Oqtane.Migrations.Extensions -{ - public static class ColumnsBuilderExtensions - { - public static OperationBuilder AddBooleanColumn(this ColumnsBuilder table, string name, bool nullable = false) - { - return table.Column(name: name, nullable: nullable); - } - - public static OperationBuilder AddDateTimeColumn(this ColumnsBuilder table, string name, bool nullable = false) - { - return table.Column(name: name, nullable: nullable); - } - - public static OperationBuilder AddDateTimeOffsetColumn(this ColumnsBuilder table, string name, bool nullable = false) - { - return table.Column(name: name, nullable: nullable); - } - - public static OperationBuilder AddIntegerColumn(this ColumnsBuilder table, string name, bool nullable = false) - { - return table.Column(name: name, nullable: nullable); - } - - public static OperationBuilder AddMaxStringColumn(this ColumnsBuilder table, string name, bool nullable = false) - { - return table.Column(name: name, nullable: nullable, unicode: true); - } - - public static OperationBuilder AddStringColumn(this ColumnsBuilder table, string name, int length, bool nullable = false) - { - return table.Column(name: name, maxLength: length, nullable: nullable, unicode: true); - } - - } -} diff --git a/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs b/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs deleted file mode 100644 index 76a1b454..00000000 --- a/Oqtane.Server/Migrations/Extensions/CreateTableBuilderExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; -using Oqtane.Migrations.EntityBuilders; - -namespace Oqtane.Migrations.Extensions -{ - public static class CreateTableBuilderExtensions - { - public static void AddForeignKey(this CreateTableBuilder table, ForeignKey foreignKey) where TEntityBuilder : BaseEntityBuilder - { - table.ForeignKey( - name: foreignKey.Name, - column: foreignKey.Column, - principalTable: foreignKey.PrincipalTable, - principalColumn: foreignKey.PrincipalColumn, - onDelete: foreignKey.OnDeleteAction); - } - - public static void AddPrimaryKey(this CreateTableBuilder table, PrimaryKey primaryKey) where TEntityBuilder : BaseEntityBuilder - { - table.PrimaryKey(primaryKey.Name, primaryKey.Columns); - } - } -} diff --git a/Oqtane.Server/Migrations/Framework/ForeignKey.cs b/Oqtane.Server/Migrations/Framework/ForeignKey.cs index d2a2260d..09f219e6 100644 --- a/Oqtane.Server/Migrations/Framework/ForeignKey.cs +++ b/Oqtane.Server/Migrations/Framework/ForeignKey.cs @@ -1,8 +1,6 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Migrations.Operations; -using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Migrations.EntityBuilders; namespace Oqtane.Migrations diff --git a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs index 74bf8564..eeabff6d 100644 --- a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs +++ b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs @@ -25,12 +25,12 @@ namespace Oqtane.Modules.HtmlText.Controllers // GET api//5 [HttpGet("{id}")] [Authorize(Policy = PolicyNames.ViewModule)] - public List Get(int id) + public List Get(int id) { - var list = new List(); + var list = new List(); try { - HtmlTextInfo htmlText = null; + Models.HtmlText htmlText = null; if (_entityId == id) { htmlText = _htmlText.GetHtmlText(id); @@ -48,7 +48,7 @@ namespace Oqtane.Modules.HtmlText.Controllers // POST api/ [HttpPost] [Authorize(Policy = PolicyNames.EditModule)] - public HtmlTextInfo Post([FromBody] HtmlTextInfo htmlText) + public Models.HtmlText Post([FromBody] Models.HtmlText htmlText) { try { @@ -69,7 +69,7 @@ namespace Oqtane.Modules.HtmlText.Controllers // PUT api//5 [HttpPut("{id}")] [Authorize(Policy = PolicyNames.EditModule)] - public HtmlTextInfo Put(int id, [FromBody] HtmlTextInfo htmlText) + public Models.HtmlText Put(int id, [FromBody] Models.HtmlText htmlText) { try { diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index 96774c52..40f7bde4 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -48,7 +48,7 @@ namespace Oqtane.Modules.HtmlText.Manager } else { - htmlText = new HtmlTextInfo(); + htmlText = new Models.HtmlText(); htmlText.ModuleId = module.ModuleId; htmlText.Content = content; _htmlText.AddHtmlText(htmlText); diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs index 8ed3e956..0f912485 100644 --- a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs +++ b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs @@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; using Oqtane.Interfaces; using Oqtane.Migrations; using Oqtane.Migrations.EntityBuilders; -using Oqtane.Migrations.Extensions; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -26,9 +25,9 @@ namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders protected override HtmlTextEntityBuilder BuildTable(ColumnsBuilder table) { - HtmlTextId = ActiveDatabase.AddAutoIncrementColumn(table,"HtmlTextId"); - ModuleId = table.AddIntegerColumn("ModuleId"); - Content = table.AddMaxStringColumn("Content"); + HtmlTextId = AddAutoIncrementColumn(table,"HtmlTextId"); + ModuleId = AddIntegerColumn(table,"ModuleId"); + Content = AddMaxStringColumn(table,"Content"); AddAuditableColumns(table); diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index 168667fd..cd62722f 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -16,6 +16,6 @@ namespace Oqtane.Modules.HtmlText.Repository { } - public virtual DbSet HtmlText { get; set; } + public virtual DbSet HtmlText { get; set; } } } diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs index c97b0de7..633a5b25 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs @@ -13,20 +13,20 @@ namespace Oqtane.Modules.HtmlText.Repository _db = context; } - public HtmlTextInfo GetHtmlText(int moduleId) + public Models.HtmlText GetHtmlText(int moduleId) { return _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId); } - public HtmlTextInfo AddHtmlText(HtmlTextInfo htmlText) + public Models.HtmlText AddHtmlText(Models.HtmlText htmlText) { _db.HtmlText.Add(htmlText); _db.SaveChanges(); return htmlText; } - public HtmlTextInfo UpdateHtmlText(HtmlTextInfo htmlText) + public Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText) { _db.Entry(htmlText).State = EntityState.Modified; _db.SaveChanges(); @@ -35,7 +35,7 @@ namespace Oqtane.Modules.HtmlText.Repository public void DeleteHtmlText(int moduleId) { - HtmlTextInfo htmlText = _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId); + Models.HtmlText htmlText = _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId); if (htmlText != null) _db.HtmlText.Remove(htmlText); _db.SaveChanges(); } diff --git a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs index cbe5d0e4..75daf276 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs @@ -4,9 +4,9 @@ namespace Oqtane.Modules.HtmlText.Repository { public interface IHtmlTextRepository { - HtmlTextInfo GetHtmlText(int moduleId); - HtmlTextInfo AddHtmlText(HtmlTextInfo htmlText); - HtmlTextInfo UpdateHtmlText(HtmlTextInfo htmlText); + Models.HtmlText GetHtmlText(int moduleId); + Models.HtmlText AddHtmlText(Models.HtmlText htmlText); + Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText); void DeleteHtmlText(int moduleId); } } diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index 0e7b0289..d3066502 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -84,6 +84,19 @@ namespace Oqtane.Repository base.OnConfiguring(optionsBuilder); } + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + if (Databases != null) + { + var database = Databases.Single(d => d.Name == _databaseType); + + database.UpdateIdentityStoreTableNames(builder); + } + + } + public override int SaveChanges() { DbContextUtils.SaveChanges(this, _accessor); diff --git a/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs b/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs index 7f214a40..225ccffd 100644 --- a/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs +++ b/Oqtane.Shared/Interfaces/IOqtaneDatabase.cs @@ -20,6 +20,12 @@ namespace Oqtane.Interfaces public string BuildConnectionString(); + public string ConcatenateSql(params string[] values); + + public string RewriteName(string name); + + public void UpdateIdentityStoreTableNames(ModelBuilder builder); + public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); } } diff --git a/Oqtane.Shared/Models/ConnectionStringField.cs b/Oqtane.Shared/Models/ConnectionStringField.cs index a014168c..f3f216a8 100644 --- a/Oqtane.Shared/Models/ConnectionStringField.cs +++ b/Oqtane.Shared/Models/ConnectionStringField.cs @@ -4,6 +4,8 @@ namespace Oqtane.Models { public string FriendlyName { get; set; } + public string HelpText { get; set; } + public string Name { get; set; } public string Value { get; set; } diff --git a/Oqtane.Shared/Modules/HtmlText/Models/HtmlTextInfo.cs b/Oqtane.Shared/Modules/HtmlText/Models/HtmlText.cs similarity index 88% rename from Oqtane.Shared/Modules/HtmlText/Models/HtmlTextInfo.cs rename to Oqtane.Shared/Modules/HtmlText/Models/HtmlText.cs index e51a41fd..25efbb23 100644 --- a/Oqtane.Shared/Modules/HtmlText/Models/HtmlTextInfo.cs +++ b/Oqtane.Shared/Modules/HtmlText/Models/HtmlText.cs @@ -5,8 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Oqtane.Modules.HtmlText.Models { - [Table("HtmlText")] - public class HtmlTextInfo : IAuditable + public class HtmlText : IAuditable { [Key] public int HtmlTextId { get; set; } diff --git a/Oqtane.Shared/Shared/OqtaneDatabaseBase.cs b/Oqtane.Shared/Shared/OqtaneDatabaseBase.cs new file mode 100644 index 00000000..ff107ff5 --- /dev/null +++ b/Oqtane.Shared/Shared/OqtaneDatabaseBase.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; +using Oqtane.Models; + +namespace Oqtane.Shared +{ + public abstract class OqtaneDatabaseBase : IOqtaneDatabase + { + protected OqtaneDatabaseBase(string name, string friendlyName, List connectionStringFields) + { + Name = name; + FriendlyName = friendlyName; + ConnectionStringFields = connectionStringFields; + } + + public string FriendlyName { get; } + + public string Name { get; } + + public abstract string Provider { get; } + + public List ConnectionStringFields { get; } + + public abstract OperationBuilder AddAutoIncrementColumn(ColumnsBuilder table, string name); + + public abstract string BuildConnectionString(); + + public virtual string ConcatenateSql(params string[] values) + { + var returnValue = String.Empty; + for (var i = 0; i < values.Length; i++) + { + if (i > 0) + { + returnValue += " + "; + } + returnValue += values[i]; + } + + return returnValue; + } + + public virtual string RewriteName(string name) + { + return name; + } + + public virtual void UpdateIdentityStoreTableNames(ModelBuilder builder) + { + + } + + public abstract DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); + } +} From 985987d8f4917a2bdf5e576feb5c3856a078b08f Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Fri, 2 Apr 2021 11:28:34 -0700 Subject: [PATCH 07/23] Updated initial appsettings.json --- Oqtane.Server/appsettings.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Oqtane.Server/appsettings.json b/Oqtane.Server/appsettings.json index 33858f9e..68bd1906 100644 --- a/Oqtane.Server/appsettings.json +++ b/Oqtane.Server/appsettings.json @@ -1,10 +1,9 @@ { "Database": { - "DatabaseType": "Sqlite", - "DatabaseEngineVersion": "" + "DatabaseType": "" }, "ConnectionStrings": { - "DefaultConnection": "Data Source=Oqtane.db" + "DefaultConnection": "" }, "Runtime": "Server", "Installation": { From d12b18350f7c6243806dcdcfada396fb4b2387f1 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Fri, 2 Apr 2021 11:49:38 -0700 Subject: [PATCH 08/23] Fixed bug in AddSite due to missing assignment of database type --- Oqtane.Client/Modules/Admin/Sites/Add.razor | 1 + 1 file changed, 1 insertion(+) diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index ac89d1dd..9627ade2 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -326,6 +326,7 @@ else var connectionString = _selectedDatabase.BuildConnectionString(); if (connectionString != "") { + config.DatabaseType = _databaseType; config.ConnectionString = connectionString; config.HostPassword = _hostpassword; config.HostEmail = user.Email; From 8c45b7e42ffba1642c26264e8c01b9af160514a4 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Thu, 8 Apr 2021 12:20:21 -0700 Subject: [PATCH 09/23] Added support for migrating existing Oqtane installations from DbUp to Migrations. Also added a Migration for version 2.0.2, and set current version to 2.1.0 --- .../Infrastructure/DatabaseManager.cs | 115 +++++++++++------- .../Migrations/02000201_AddSiteGuidToSite.cs | 34 ++++++ .../02010000_AddAppVersionsTableInTenant.cs | 75 ++++++++++++ .../AppVersionsEntityBuilder.cs | 35 ++++++ .../EntityBuilders/BaseEntityBuilder.cs | 20 +-- Oqtane.Server/Oqtane.Server.csproj | 2 + .../Repository/Interfaces/ISqlRepository.cs | 5 + Oqtane.Server/Repository/SqlRepository.cs | 84 +++++++++---- Oqtane.Server/Scripts/MigrateMaster.sql | 17 +++ Oqtane.Server/Scripts/MigrateTenant.sql | 20 +++ Oqtane.Shared/Shared/Constants.cs | 4 +- 11 files changed, 331 insertions(+), 80 deletions(-) create mode 100644 Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs create mode 100644 Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs create mode 100644 Oqtane.Server/Migrations/EntityBuilders/AppVersionsEntityBuilder.cs create mode 100644 Oqtane.Server/Scripts/MigrateMaster.sql create mode 100644 Oqtane.Server/Scripts/MigrateTenant.sql diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs index bad8c272..18dc820f 100644 --- a/Oqtane.Server/Infrastructure/DatabaseManager.cs +++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; @@ -75,7 +76,13 @@ namespace Oqtane.Infrastructure if (install == null) { // startup or silent installation - install = new InstallConfig { ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), TenantName = TenantNames.Master, IsNewTenant = false }; + install = new InstallConfig + { + ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), + TenantName = TenantNames.Master, + DatabaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey], + IsNewTenant = false + }; if (!IsInstalled()) { @@ -207,6 +214,7 @@ namespace Oqtane.Infrastructure using (var scope = _serviceScopeFactory.CreateScope()) { var databases = scope.ServiceProvider.GetServices(); + var sql = scope.ServiceProvider.GetRequiredService(); try { @@ -214,6 +222,10 @@ namespace Oqtane.Infrastructure using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) { + if (IsInstalled() && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")) + { + UpgradeSqlServer(sql, install.ConnectionString, true); + } // Push latest model into database masterDbContext.Database.Migrate(); result.Success = true; @@ -303,14 +315,6 @@ namespace Oqtane.Infrastructure return result; } - private InstallationContext GetInstallationContext(IEnumerable databases) - { - var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; - var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); - - return new InstallationContext(databases.Single(d => d.Name == databaseType), connectionString); - } - private Installation MigrateTenants(InstallConfig install) { var result = new Installation { Success = false, Message = string.Empty }; @@ -321,6 +325,7 @@ namespace Oqtane.Infrastructure { var upgrades = scope.ServiceProvider.GetRequiredService(); var databases = scope.ServiceProvider.GetServices(); + var sql = scope.ServiceProvider.GetRequiredService(); using (var db = GetInstallationContext(databases)) { @@ -328,9 +333,14 @@ namespace Oqtane.Infrastructure { try { - var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType}; + var dbConfig = new DbConfig(null, null, databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType}; using (var tenantDbContext = new TenantDBContext(dbConfig, null)) { + if (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB") + { + UpgradeSqlServer(sql, tenant.DBConnectionString, false); + } + // Push latest model into database tenantDbContext.Database.Migrate(); result.Success = true; @@ -551,36 +561,6 @@ namespace Oqtane.Infrastructure return result; } - private string NormalizeConnectionString(string connectionString) - { - var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); - connectionString = connectionString.Replace("|DataDirectory|", dataDirectory); - return connectionString; - } - - private string DenormalizeConnectionString(string connectionString) - { - var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); - connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|"); - return connectionString; - } - - public void UpdateConnectionString(string connectionString) - { - connectionString = DenormalizeConnectionString(connectionString); - if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString) - { - AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString); - _config.Reload(); - } - } - - public void UpdateDatabaseType(string databaseType) - { - AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType); - _config.Reload(); - } - public void AddOrUpdateAppSetting(string sectionPathKey, T value) { try @@ -600,6 +580,36 @@ namespace Oqtane.Infrastructure } } + private string DenormalizeConnectionString(string connectionString) + { + var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); + connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|"); + return connectionString; + } + + private InstallationContext GetInstallationContext(IEnumerable databases) + { + var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey]; + var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)); + + return new InstallationContext(databases.Single(d => d.Name == databaseType), connectionString); + } + + private string GetInstallationConfig(string key, string defaultValue) + { + var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue); + // double fallback to default value - allow hold sample keys in config + if (string.IsNullOrEmpty(value)) value = defaultValue; + return value; + } + + private string NormalizeConnectionString(string connectionString) + { + var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); + connectionString = connectionString.Replace("|DataDirectory|", dataDirectory); + return connectionString; + } + private void SetValueRecursively(string sectionPathKey, dynamic jsonObj, T value) { // split the string at the first ':' character @@ -619,12 +629,27 @@ namespace Oqtane.Infrastructure } } - private string GetInstallationConfig(string key, string defaultValue) + public void UpdateConnectionString(string connectionString) { - var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue); - // double fallback to default value - allow hold sample keys in config - if (string.IsNullOrEmpty(value)) value = defaultValue; - return value; + connectionString = DenormalizeConnectionString(connectionString); + if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString) + { + AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString); + _config.Reload(); + } + } + + public void UpdateDatabaseType(string databaseType) + { + AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType); + _config.Reload(); + } + + public void UpgradeSqlServer(ISqlRepository sql, string connectionString, bool isMaster) + { + var script = (isMaster) ? "MigrateMaster.sql" : "MigrateTenant.sql"; + + sql.ExecuteScript(connectionString, Assembly.GetExecutingAssembly(), script); } } } diff --git a/Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs b/Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs new file mode 100644 index 00000000..45484d92 --- /dev/null +++ b/Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.00.02.01")] + + public class AddSiteGuidToSite : MultiDatabaseMigration + { + public AddSiteGuidToSite(IEnumerable databases) : base(databases) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + //Add Column to Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); + siteEntityBuilder.AddStringColumn("SiteGuid", 36, true, false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop Column from Site table + var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); + siteEntityBuilder.DropColumn("SiteGuid"); + } + + } +} diff --git a/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs b/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs new file mode 100644 index 00000000..f2a65ab7 --- /dev/null +++ b/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Interfaces; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.01.00.00")] + + public class AddAppVersionsTable : MultiDatabaseMigration + { + public AddAppVersionsTable(IEnumerable databases) : base(databases) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create AppVersions table + var appVersionsEntityBuilder = new AppVersionsEntityBuilder(migrationBuilder, ActiveDatabase); + appVersionsEntityBuilder.Create(); + + //Finish SqlServer Migration from DbUp + if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB") + { + //Version 1.0.0 + InsertVersion(migrationBuilder, "01.00.00", "Oqtane.Scripts.Master.00.09.00.00.sql"); + + //Version 1.0.1 + InsertVersion(migrationBuilder, "01.00.01", "Oqtane.Scripts.Master.01.00.01.00.sql"); + + //Version 1.0.2 + InsertVersion(migrationBuilder, "01.00.02", "Oqtane.Scripts.Tenant.01.00.02.01.sql"); + + //Version 2.0.0 + InsertVersion(migrationBuilder, "02.00.00", "Oqtane.Scripts.Tenant.02.00.00.01.sql"); + + //Version 2.0.1 + InsertVersion(migrationBuilder, "02.00.01", "Oqtane.Scripts.Tenant.02.00.01.03.sql"); + + //Version 2.0.2 + InsertVersion(migrationBuilder, "02.00.02", "Oqtane.Scripts.Tenant.02.00.02.01.sql"); + + //Drop SchemaVersions + migrationBuilder.Sql(@" + IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + DROP TABLE SchemaVersions + END"); + } + + //Version 2.1.0 + migrationBuilder.Sql($@" + INSERT INTO AppVersions(Version, AppliedDate) + VALUES('02.01.00', '{DateTime.UtcNow:u}') + "); + } + + private void InsertVersion(MigrationBuilder migrationBuilder, string version, string scriptName) + { + migrationBuilder.Sql($@" + IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + INSERT INTO AppVersions(Version, AppliedDate) + SELECT Version = '{version}', Applied As AppliedDate + FROM SchemaVersions + WHERE ScriptName = '{scriptName}' + END + "); + } + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/AppVersionsEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/AppVersionsEntityBuilder.cs new file mode 100644 index 00000000..7c5581ff --- /dev/null +++ b/Oqtane.Server/Migrations/EntityBuilders/AppVersionsEntityBuilder.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Interfaces; + +namespace Oqtane.Migrations.EntityBuilders +{ + public class AppVersionsEntityBuilder : BaseEntityBuilder + { + private const string _entityTableName = "AppVersions"; + private readonly PrimaryKey _primaryKey = new("PK_AppVersions", x => x.Id); + + public AppVersionsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + } + + protected override AppVersionsEntityBuilder BuildTable(ColumnsBuilder table) + { + Id = AddAutoIncrementColumn(table,"Id"); + Version = AddStringColumn(table,"Version", 10); + AppliedDate = AddDateTimeColumn(table,"AppliedDate"); + + return this; + } + + public OperationBuilder Id { get; set; } + + public OperationBuilder Version { get; set; } + + public OperationBuilder AppliedDate { get; set; } + + } +} diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs index 42264996..77022a9f 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs @@ -83,29 +83,29 @@ namespace Oqtane.Migrations.EntityBuilders return table.Column(name: RewriteName(name), nullable: nullable); } - public void AddMaxStringColumn(string name, int length, bool nullable = false) + public void AddMaxStringColumn(string name, int length, bool nullable = false, bool unicode = true) { - _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: true); + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: unicode); } - protected OperationBuilder AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false) + protected OperationBuilder AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false, bool unicode = true) { - return table.Column(name: RewriteName(name), nullable: nullable, unicode: true); + return table.Column(name: RewriteName(name), nullable: nullable, unicode: unicode); } - public void AddStringColumn(string name, int length, bool nullable = false) + public void AddStringColumn(string name, int length, bool nullable = false, bool unicode = true) { - _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: true); + _migrationBuilder.AddColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode); } - protected OperationBuilder AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false) + protected OperationBuilder AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false, bool unicode = true) { - return table.Column(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: true); + return table.Column(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: unicode); } - public void AlterStringColumn(string name, int length, bool nullable = false) + public void AlterStringColumn(string name, int length, bool nullable = false, bool unicode = true) { - _migrationBuilder.AlterColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable); + _migrationBuilder.AlterColumn(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode); } public void DropColumn(string name) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 8898841a..af44052f 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -39,6 +39,8 @@ + + diff --git a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs index 76a6f701..4d53fce6 100644 --- a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs @@ -7,8 +7,13 @@ namespace Oqtane.Repository public interface ISqlRepository { void ExecuteScript(Tenant tenant, string script); + + bool ExecuteScript(string connectionString, Assembly assembly, string filename); + bool ExecuteScript(Tenant tenant, Assembly assembly, string filename); + int ExecuteNonQuery(Tenant tenant, string query); + SqlDataReader ExecuteReader(Tenant tenant, string query); } } diff --git a/Oqtane.Server/Repository/SqlRepository.cs b/Oqtane.Server/Repository/SqlRepository.cs index 037a9e42..6a35876a 100644 --- a/Oqtane.Server/Repository/SqlRepository.cs +++ b/Oqtane.Server/Repository/SqlRepository.cs @@ -5,6 +5,9 @@ using System.Linq; using System.Reflection; using Microsoft.Data.SqlClient; using Oqtane.Models; +// ReSharper disable ConvertToUsingDeclaration +// ReSharper disable InvertIf +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess namespace Oqtane.Repository { @@ -13,35 +16,41 @@ namespace Oqtane.Repository public void ExecuteScript(Tenant tenant, string script) { - // execute script in curent tenant - foreach (string query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries)) + // execute script in current tenant + foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries)) { ExecuteNonQuery(tenant, query); } } - public bool ExecuteScript(Tenant tenant, Assembly assembly, string filename) + public bool ExecuteScript(string connectionString, Assembly assembly, string fileName) { - // script must be included as an Embedded Resource within an assembly - bool success = true; - string script = ""; + var success = true; + var script = GetScriptFromAssembly(assembly, fileName); - if (assembly != null) + if (!string.IsNullOrEmpty(script)) { - string name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + filename)); - if (name != null) + try { - Stream resourceStream = assembly.GetManifestResourceStream(name); - if (resourceStream != null) + foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries)) { - using (var reader = new StreamReader(resourceStream)) - { - script = reader.ReadToEnd(); - } + ExecuteNonQuery(connectionString, query); } } + catch + { + success = false; + } } + return success; + } + + public bool ExecuteScript(Tenant tenant, Assembly assembly, string fileName) + { + var success = true; + var script = GetScriptFromAssembly(assembly, fileName); + if (!string.IsNullOrEmpty(script)) { try @@ -59,12 +68,26 @@ namespace Oqtane.Repository public int ExecuteNonQuery(Tenant tenant, string query) { - var conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); + return ExecuteNonQuery(tenant.DBConnectionString, query); + } + + public SqlDataReader ExecuteReader(Tenant tenant, string query) + { + SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); + SqlCommand cmd = conn.CreateCommand(); + PrepareCommand(conn, cmd, query); + var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); + return dr; + } + + private int ExecuteNonQuery(string connectionString, string query) + { + var conn = new SqlConnection(FormatConnectionString(connectionString)); var cmd = conn.CreateCommand(); using (conn) { PrepareCommand(conn, cmd, query); - int val = -1; + var val = -1; try { val = cmd.ExecuteNonQuery(); @@ -77,13 +100,28 @@ namespace Oqtane.Repository } } - public SqlDataReader ExecuteReader(Tenant tenant, string query) + private string GetScriptFromAssembly(Assembly assembly, string fileName) { - SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); - SqlCommand cmd = conn.CreateCommand(); - PrepareCommand(conn, cmd, query); - var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); - return dr; + // script must be included as an Embedded Resource within an assembly + var script = ""; + + if (assembly != null) + { + var name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + fileName)); + if (name != null) + { + var resourceStream = assembly.GetManifestResourceStream(name); + if (resourceStream != null) + { + using (var reader = new StreamReader(resourceStream)) + { + script = reader.ReadToEnd(); + } + } + } + } + + return script; } private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query) diff --git a/Oqtane.Server/Scripts/MigrateMaster.sql b/Oqtane.Server/Scripts/MigrateMaster.sql new file mode 100644 index 00000000..3da59696 --- /dev/null +++ b/Oqtane.Server/Scripts/MigrateMaster.sql @@ -0,0 +1,17 @@ +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + CREATE TABLE __EFMigrationsHistory + ( + MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY, + ProductVersion nvarchar(32) NOT NULL + ) + END + INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion) + VALUES ('Master.01.00.00.00', '5.0.0') + INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion) + SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0' + FROM SchemaVersions + WHERE ScriptName LIKE 'Oqtane.Scripts.Master.01%' + END \ No newline at end of file diff --git a/Oqtane.Server/Scripts/MigrateTenant.sql b/Oqtane.Server/Scripts/MigrateTenant.sql new file mode 100644 index 00000000..ca4ae38e --- /dev/null +++ b/Oqtane.Server/Scripts/MigrateTenant.sql @@ -0,0 +1,20 @@ +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1) + BEGIN + CREATE TABLE __EFMigrationsHistory + ( + MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY, + ProductVersion nvarchar(32) NOT NULL + ) + END + INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion) + VALUES ('Tenant.01.00.00.00', '5.0.0') + INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion) + SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0' + FROM SchemaVersions + WHERE ScriptName LIKE 'Oqtane.Scripts.Tenant.01%' + OR ScriptName LIKE 'Oqtane.Scripts.Tenant.02%' + INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion) + VALUES ('HtmlText.01.00.00.00', '5.0.0') + END \ No newline at end of file diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs index 1b05a7e7..e7636ed0 100644 --- a/Oqtane.Shared/Shared/Constants.cs +++ b/Oqtane.Shared/Shared/Constants.cs @@ -5,8 +5,8 @@ namespace Oqtane.Shared { public class Constants { public const string PackageId = "Oqtane.Framework"; - public const string Version = "2.0.1"; - public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1"; + public const string Version = "2.1.0"; + public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0"; public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client"; public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client"; From a0329b1b6cd4ad82a832557a448998acf7b2fa63 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Thu, 8 Apr 2021 14:58:02 -0700 Subject: [PATCH 10/23] Fix bug in new Migration to support PostgreSQL --- .../Migrations/02010000_AddAppVersionsTableInTenant.cs | 6 +++++- .../Migrations/Framework/MultiDatabaseMigration.cs | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs b/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs index f2a65ab7..73a15750 100644 --- a/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs +++ b/Oqtane.Server/Migrations/02010000_AddAppVersionsTableInTenant.cs @@ -53,8 +53,12 @@ namespace Oqtane.Migrations } //Version 2.1.0 + var appVersions = RewriteName("AppVersions"); + var version = RewriteName("Version"); + var appledDate = RewriteName("AppliedDate"); + migrationBuilder.Sql($@" - INSERT INTO AppVersions(Version, AppliedDate) + INSERT INTO {appVersions}({version}, {appledDate}) VALUES('02.01.00', '{DateTime.UtcNow:u}') "); } diff --git a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs index 2a0e6fce..ca9a0217 100644 --- a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs +++ b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs @@ -15,5 +15,10 @@ namespace Oqtane.Migrations } protected IOqtaneDatabase ActiveDatabase => _databases.FirstOrDefault(d => d.Provider == ActiveProvider); + + protected string RewriteName(string name) + { + return ActiveDatabase.RewriteName(name); + } } } From 0222bbdeae363204e395138adf03820b8ba1f691 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 15:48:54 -0700 Subject: [PATCH 11/23] Resolve conflict with main Oqtane repo --- Oqtane.Server/Oqtane.Server.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index af44052f..bfe0caec 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -39,6 +39,10 @@ + + + + From f8b607911d2fcc9c24252e3abcefca2054f96ef8 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 15:53:07 -0700 Subject: [PATCH 12/23] Resolve conflict in project file --- Oqtane.Server/Oqtane.Server.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index bfe0caec..8ed5e8da 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -20,9 +20,9 @@ - - - + + + From 713b19e0e908fa07ab25a679b8a3bef31c80579c Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 15:57:07 -0700 Subject: [PATCH 13/23] Remove Html Module Script files --- Oqtane.Server/Oqtane.Server.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 8ed5e8da..1eb93de8 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -41,8 +41,6 @@ - - From 23bab67bd34eb584439f6a7d748352727343a71a Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 15:59:31 -0700 Subject: [PATCH 14/23] Resolve new conflict --- Oqtane.Server/Oqtane.Server.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 1eb93de8..b1e6a820 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -41,6 +41,8 @@ + + From e11a65c6cae8e7408474ed7b9d47099a75d740fa Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 16:03:00 -0700 Subject: [PATCH 15/23] Rollback removal of script files for Html Module to resolve conflict --- .../HtmlText/Scripts/HtmlText.1.0.0.sql | 19 +++++++++++++++++++ .../HtmlText/Scripts/HtmlText.Uninstall.sql | 2 ++ Oqtane.Server/Oqtane.Server.csproj | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql create mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql new file mode 100644 index 00000000..fa3b0fd2 --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql @@ -0,0 +1,19 @@ +CREATE TABLE [dbo].[HtmlText]( + [HtmlTextId] [int] IDENTITY(1,1) NOT NULL, + [ModuleId] [int] NOT NULL, + [Content] [nvarchar](max) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_HtmlText] PRIMARY KEY CLUSTERED + ( + [HtmlTextId] ASC + ) +) +GO + +ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId]) +REFERENCES [dbo].[Module] ([ModuleId]) +ON DELETE CASCADE +GO diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql new file mode 100644 index 00000000..34011c03 --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql @@ -0,0 +1,2 @@ +DROP TABLE [dbo].[HtmlText] +GO diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index b1e6a820..8ed5e8da 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -41,8 +41,8 @@ - - + + From 096f8249c320e001857b047a9407983b4101ea57 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Wed, 14 Apr 2021 16:05:59 -0700 Subject: [PATCH 16/23] Resolve conflict in Constants --- Oqtane.Shared/Shared/Constants.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs index e7636ed0..60106dd2 100644 --- a/Oqtane.Shared/Shared/Constants.cs +++ b/Oqtane.Shared/Shared/Constants.cs @@ -5,8 +5,8 @@ namespace Oqtane.Shared { public class Constants { public const string PackageId = "Oqtane.Framework"; - public const string Version = "2.1.0"; - public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0"; + public const string Version = "2.0.2"; + public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2"; public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client"; public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client"; From 7516be41d989e4da583dcaf076f74311d582d8b0 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 19 Apr 2021 14:10:13 -0400 Subject: [PATCH 17/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc4d7909..19073205 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ There is a separate [Documentation repository](https://github.com/oqtane/oqtane. # Roadmap This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist. -V.2.1.0 ( Q1 2021 ) +V.2.1.0 ( May 2021 ) - [ ] Cross Platform Database Support ( ie. SQLite ) - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964) - [ ] EF Core Migrations for Database Installation/Upgrade - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964) From 4598d0d6ba70acf58f0505932529dc33b49f717d Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:13:10 -0700 Subject: [PATCH 18/23] Resolve conflict in AddSite --- Oqtane.Client/Modules/Admin/Sites/Add.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 9627ade2..7abd3ab2 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -295,7 +295,7 @@ else private async Task SaveSite() { - if (_tenantId != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-" && _sitetemplatetype != "-") + if (_tenantId != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-") { var duplicates = new List(); var aliases = await AliasService.GetAliasesAsync(); From 20b5a10882e943dbac9532dc2ddbdee20e6f4a7a Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:15:53 -0700 Subject: [PATCH 19/23] Resolve name of variable in AddSite --- Oqtane.Client/Modules/Admin/Sites/Add.razor | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 7abd3ab2..3c9d945b 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -124,7 +124,7 @@ else - @if (_tenantId == "+") + @if (_tenantid == "+") { @@ -228,7 +228,7 @@ else private List _containers = new List(); private List _siteTemplates; private List _tenants; - private string _tenantId = "-"; + private string _tenantid = "-"; private string _tenantName = string.Empty; private IOqtaneDatabase _selectedDatabase; @@ -258,7 +258,7 @@ else private void TenantChanged(ChangeEventArgs e) { - _tenantId = (string)e.Value; + _tenantid = (string)e.Value; if (string.IsNullOrEmpty(_tenantName)) { _tenantName = _name; @@ -295,7 +295,7 @@ else private async Task SaveSite() { - if (_tenantId != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-") + if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-") { var duplicates = new List(); var aliases = await AliasService.GetAliasesAsync(); @@ -311,7 +311,7 @@ else { InstallConfig config = new InstallConfig(); - if (_tenantId == "+") + if (_tenantid == "+") { if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null) { @@ -351,7 +351,7 @@ else } else { - var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantId)); + var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); if (tenant != null) { config.TenantName = tenant.Name; From 2402cab3f3c4dac735657110e34856847c3d3705 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:50:25 -0700 Subject: [PATCH 20/23] Attempt to resolve conflict in DatabaseManager --- .../Infrastructure/DatabaseManager.cs | 124 +++++++++--------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs index 99e67e57..4e3a4dcd 100644 --- a/Oqtane.Server/Infrastructure/DatabaseManager.cs +++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs @@ -234,7 +234,8 @@ namespace Oqtane.Infrastructure using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) { - if (IsInstalled() && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")) + var installation = IsInstalled(); + if (installation.Success && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")) { UpgradeSqlServer(sql, install.ConnectionString, true); } @@ -489,80 +490,77 @@ namespace Oqtane.Infrastructure var tenant = tenants.GetTenants().FirstOrDefault(item => item.Name == install.TenantName); - if (tenant != null) + site = new Site { - site = new Site - { - TenantId = tenant.TenantId, - Name = install.SiteName, - LogoFileId = null, - DefaultThemeType = install.DefaultTheme, - DefaultLayoutType = install.DefaultLayout, - DefaultContainerType = install.DefaultContainer, - SiteTemplateType = install.SiteTemplate - }; - site = sites.AddSite(site); + TenantId = tenant.TenantId, + Name = install.SiteName, + LogoFileId = null, + DefaultThemeType = install.DefaultTheme, + DefaultLayoutType = install.DefaultLayout, + DefaultContainerType = install.DefaultContainer, + SiteTemplateType = install.SiteTemplate + }; + site = sites.AddSite(site); - var identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); - if (identityUser == null) + var identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); + if (identityUser == null) + { + identityUser = new IdentityUser {UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true}; + var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); + if (create.Succeeded) { - identityUser = new IdentityUser {UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true}; - var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); - if (create.Succeeded) + var user = new User { - var user = new User - { - SiteId = site.SiteId, - Username = UserNames.Host, - Password = install.HostPassword, - Email = install.HostEmail, - DisplayName = install.HostName, - LastIPAddress = "", - LastLoginOn = null - }; + SiteId = site.SiteId, + Username = UserNames.Host, + Password = install.HostPassword, + Email = install.HostEmail, + DisplayName = install.HostName, + LastIPAddress = "", + LastLoginOn = null + }; - user = users.AddUser(user); - var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; - var userRole = new UserRole {UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null}; - userRoles.AddUserRole(userRole); + user = users.AddUser(user); + var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; + var userRole = new UserRole {UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null}; + userRoles.AddUserRole(userRole); - // add user folder - var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); - if (folder != null) + // add user folder + var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); + if (folder != null) + { + folders.AddFolder(new Folder { - folders.AddFolder(new Folder + SiteId = folder.SiteId, + ParentId = folder.FolderId, + Name = "My Folder", + Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), + Order = 1, + IsSystem = true, + Permissions = new List { - SiteId = folder.SiteId, - ParentId = folder.FolderId, - Name = "My Folder", - Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), - Order = 1, - IsSystem = true, - Permissions = new List - { - new Permission(PermissionNames.Browse, user.UserId, true), - new Permission(PermissionNames.View, RoleNames.Everyone, true), - new Permission(PermissionNames.Edit, user.UserId, true), - }.EncodePermissions(), - }); - } + new Permission(PermissionNames.Browse, user.UserId, true), + new Permission(PermissionNames.View, RoleNames.Everyone, true), + new Permission(PermissionNames.Edit, user.UserId, true), + }.EncodePermissions(), + }); } } - - foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) - { - alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName); - if (alias != null) - { - alias.SiteId = site.SiteId; - aliases.UpdateAlias(alias); - } - } - - tenant.Version = Constants.Version; - tenants.UpdateTenant(tenant); } + foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) + { + alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName); + if (alias != null) + { + alias.SiteId = site.SiteId; + aliases.UpdateAlias(alias); + } + } + + tenant.Version = Constants.Version; + tenants.UpdateTenant(tenant); + if (site != null) log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); } } From a11d30b1e40ac0c294b921d729fed47bf150e130 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:53:45 -0700 Subject: [PATCH 21/23] Attempt to resolve conflict in Server project file --- Oqtane.Server/Oqtane.Server.csproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 8ed5e8da..4c9a358b 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -74,13 +74,15 @@ - + + - + + From 6b204cc9885ef4072459b7937368feb02fdc9df6 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:56:51 -0700 Subject: [PATCH 22/23] Second attempt to resolve conflcit in Server project --- Oqtane.Server/Oqtane.Server.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 4c9a358b..d0cddc73 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -77,9 +77,6 @@ - - - From 13f7db7b1995b82644ba840f24930947dcef6464 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Mon, 19 Apr 2021 11:57:45 -0700 Subject: [PATCH 23/23] Resolve conflict --- Oqtane.Server/Oqtane.Server.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index d0cddc73..f7b08fd6 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -81,5 +81,4 @@ - - +