From 54a639d1d52049d08490ed3590051f264d56bc77 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 28 May 2021 17:01:25 -0400 Subject: [PATCH] Module Creator external template changes for 2.1 - supporting mutliple databases, EF Core migrations, and other multi-tenancy improvements --- .../Client/Services/[Module]Service.cs | 2 +- .../Client/[Owner].[Module].Client.csproj | 8 ++--- .../Templates/External/Package/release.cmd | 3 +- .../Server/Controllers/[Module]Controller.cs | 25 +++++++------ .../Server/Manager/[Module]Manager.cs | 20 ++++++----- .../Migrations/01000000_InitializeModule.cs | 30 ++++++++++++++++ .../EntityBuilders/[Module]EntityBuilder.cs | 36 +++++++++++++++++++ .../Server/Repository/[Module]Context.cs | 7 ++-- .../Server/Scripts/[Owner].[Module].1.0.0.sql | 26 -------------- .../Scripts/[Owner].[Module].Uninstall.sql | 6 ---- .../Server/[Owner].[Module].Server.csproj | 17 ++++----- .../External/Shared/Models/[Module].cs | 2 ++ 12 files changed, 109 insertions(+), 73 deletions(-) create mode 100644 Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/01000000_InitializeModule.cs create mode 100644 Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/EntityBuilders/[Module]EntityBuilder.cs delete mode 100644 Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql delete mode 100644 Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].Uninstall.sql diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Services/[Module]Service.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Services/[Module]Service.cs index 05a85ac7..344554e5 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Services/[Module]Service.cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Services/[Module]Service.cs @@ -18,7 +18,7 @@ namespace [Owner].[Module].Services _siteState = siteState; } - private string Apiurl => CreateApiUrl(_siteState.Alias, "[Module]"); + private string Apiurl => CreateApiUrl("[Module]", _siteState.Alias); public async Task> Get[Module]sAsync(int ModuleId) { diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].[Module].Client.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].[Module].Client.csproj index 61e2f739..6c2ee9e7 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].[Module].Client.csproj +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].[Module].Client.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Package/release.cmd b/Oqtane.Server/wwwroot/Modules/Templates/External/Package/release.cmd index aaa25f5d..db29e036 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Package/release.cmd +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Package/release.cmd @@ -1,2 +1,3 @@ "..\..\[RootFolder]\oqtane.package\nuget.exe" pack [Owner].[Module].nuspec -XCOPY "*.nupkg" "..\..\[RootFolder]\Oqtane.Server\wwwroot\Modules\" /Y +XCOPY "*.nupkg" "..\..\oqtane.framework\Oqtane.Server\Packages\" /Y + diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs index 3e2fe7b8..bc769b59 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs @@ -5,27 +5,19 @@ using Microsoft.AspNetCore.Http; using Oqtane.Shared; using Oqtane.Enums; using Oqtane.Infrastructure; -using [Owner].[Module].Models; using [Owner].[Module].Repository; +using Oqtane.Controllers; namespace [Owner].[Module].Controllers { - [Route(ControllerRoutes.Default)] - public class [Module]Controller : Controller + [Route(ControllerRoutes.ApiRoute)] + public class [Module]Controller : ModuleControllerBase { private readonly I[Module]Repository _[Module]Repository; - private readonly ILogManager _logger; - protected int _entityId = -1; - public [Module]Controller(I[Module]Repository [Module]Repository, ILogManager logger, IHttpContextAccessor accessor) + public [Module]Controller(I[Module]Repository [Module]Repository, ILogManager logger, IHttpContextAccessor accessor) : base(logger, accessor) { _[Module]Repository = [Module]Repository; - _logger = logger; - - if (accessor.HttpContext.Request.Query.ContainsKey("entityid")) - { - _entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]); - } } // GET: api/?moduleid=x @@ -33,7 +25,14 @@ namespace [Owner].[Module].Controllers [Authorize(Policy = PolicyNames.ViewModule)] public IEnumerable Get(string moduleid) { - return _[Module]Repository.Get[Module]s(int.Parse(moduleid)); + if (int.Parse(moduleid) == _entityId) + { + return _[Module]Repository.Get[Module]s(int.Parse(moduleid)); + } + else + { + return null; + } } // GET api//5 diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Manager/[Module]Manager.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Manager/[Module]Manager.cs index 486c8ddf..24fa1a91 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Manager/[Module]Manager.cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Manager/[Module]Manager.cs @@ -1,34 +1,38 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; +using Microsoft.AspNetCore.Http; using Oqtane.Modules; using Oqtane.Models; using Oqtane.Infrastructure; -using Oqtane.Repository; -using [Owner].[Module].Models; +using Oqtane.Enums; using [Owner].[Module].Repository; namespace [Owner].[Module].Manager { - public class [Module]Manager : IInstallable, IPortable + public class [Module]Manager : MigratableModuleBase, IInstallable, IPortable { private I[Module]Repository _[Module]Repository; - private ISqlRepository _sql; + private readonly ITenantManager _tenantManager; + private readonly IHttpContextAccessor _accessor; - public [Module]Manager(I[Module]Repository [Module]Repository, ISqlRepository sql) + public [Module]Manager(I[Module]Repository [Module]Repository, ITenantManager tenantManager, IHttpContextAccessor accessor) { _[Module]Repository = [Module]Repository; - _sql = sql; + _tenantManager = tenantManager; + _accessor = accessor; } public bool Install(Tenant tenant, string version) { - return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql"); + _tenantManager.SetTenant(tenant.TenantId); + return Migrate(new [Module]Context(_tenantManager, _accessor), tenant, MigrationType.Up); } public bool Uninstall(Tenant tenant) { - return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql"); + _tenantManager.SetTenant(tenant.TenantId); + return Migrate(new [Module]Context(_tenantManager, _accessor), tenant, MigrationType.Down); } public string ExportModule(Module module) diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/01000000_InitializeModule.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/01000000_InitializeModule.cs new file mode 100644 index 00000000..1b5cf26d --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/01000000_InitializeModule.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Databases.Interfaces; +using Oqtane.Migrations; +using [Owner].[Module].Migrations.EntityBuilders; +using [Owner].[Module].Repository; + +namespace [Owner].[Module].Migrations +{ + [DbContext(typeof([Module]Context))] + [Migration("[Module].01.00.00.00")] + public class InitializeModule : MultiDatabaseMigration + { + public InitializeModule(IDatabase database) : base(database) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + var entityBuilder = new [Module]EntityBuilder(migrationBuilder, ActiveDatabase); + entityBuilder.Create(); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + var entityBuilder = new [Module]EntityBuilder(migrationBuilder, ActiveDatabase); + entityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/EntityBuilders/[Module]EntityBuilder.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/EntityBuilders/[Module]EntityBuilder.cs new file mode 100644 index 00000000..c249b1d4 --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Migrations/EntityBuilders/[Module]EntityBuilder.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Databases.Interfaces; +using Oqtane.Migrations; +using Oqtane.Migrations.EntityBuilders; + +namespace [Owner].[Module].Migrations.EntityBuilders +{ + public class [Module]EntityBuilder : AuditableBaseEntityBuilder<[Module]EntityBuilder> + { + private const string _entityTableName = "[Owner][Module]"; + private readonly PrimaryKey<[Module]EntityBuilder> _primaryKey = new("PK_[Owner][Module]", x => x.[Module]Id); + private readonly ForeignKey<[Module]EntityBuilder> _moduleForeignKey = new("FK_[Owner][Module]_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); + + public [Module]EntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_moduleForeignKey); + } + + protected override [Module]EntityBuilder BuildTable(ColumnsBuilder table) + { + [Module]Id = AddAutoIncrementColumn(table,"[Module]Id"); + ModuleId = AddIntegerColumn(table,"ModuleId"); + Name = AddMaxStringColumn(table,"Name"); + AddAuditableColumns(table); + return this; + } + + public OperationBuilder [Module]Id { get; set; } + public OperationBuilder ModuleId { get; set; } + public OperationBuilder Name { get; set; } + } +} diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs index a10d7219..9e0fb3d9 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs @@ -2,15 +2,16 @@ using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Http; using Oqtane.Modules; using Oqtane.Repository; -using [Owner].[Module].Models; +using Oqtane.Infrastructure; +using Oqtane.Repository.Databases.Interfaces; namespace [Owner].[Module].Repository { - public class [Module]Context : DBContextBase, IService + public class [Module]Context : DBContextBase, IService, IMultiDatabase { public virtual DbSet [Module] { get; set; } - public [Module]Context(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) + public [Module]Context(ITenantManager tenantManager, IHttpContextAccessor accessor) : base(tenantManager, accessor) { // ContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql deleted file mode 100644 index ca9ba39d..00000000 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql +++ /dev/null @@ -1,26 +0,0 @@ -/* -Create [Owner][Module] table -*/ - -CREATE TABLE [dbo].[[Owner][Module]]( - [[Module]Id] [int] IDENTITY(1,1) NOT NULL, - [ModuleId] [int] NOT NULL, - [Name] [nvarchar](256) NOT NULL, - [CreatedBy] [nvarchar](256) NOT NULL, - [CreatedOn] [datetime] NOT NULL, - [ModifiedBy] [nvarchar](256) NOT NULL, - [ModifiedOn] [datetime] NOT NULL, - CONSTRAINT [PK_[Owner][Module]] PRIMARY KEY CLUSTERED - ( - [[Module]Id] ASC - ) -) -GO - -/* -Create foreign key relationships -*/ -ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId]) -REFERENCES [dbo].Module ([ModuleId]) -ON DELETE CASCADE -GO \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].Uninstall.sql b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].Uninstall.sql deleted file mode 100644 index 47baecc9..00000000 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].Uninstall.sql +++ /dev/null @@ -1,6 +0,0 @@ -/* -Remove [Owner][Module] table -*/ - -DROP TABLE [dbo].[[Owner][Module]] -GO diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].[Module].Server.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].[Module].Server.csproj index ec0e8e4a..aeb60008 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].[Module].Server.csproj +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].[Module].Server.csproj @@ -13,23 +13,18 @@ true - - - - - - - - - - - + + + + + + diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/Models/[Module].cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/Models/[Module].cs index 94f73ffa..45b0f2f2 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/Models/[Module].cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/Models/[Module].cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Oqtane.Models; @@ -7,6 +8,7 @@ namespace [Owner].[Module].Models [Table("[Owner][Module]")] public class [Module] : IAuditable { + [Key] public int [Module]Id { get; set; } public int ModuleId { get; set; } public string Name { get; set; }