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 @@ - +