From db85e088bf6eb8ac8f026aca90b2e0b47e94dc76 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 17 Sep 2021 13:56:19 -0400 Subject: [PATCH] fix #1659 installation issue on PostgreSQL by ntroducing a new RewriteValue method which can be overridden in a database provider to provide custom behavior. Updated PostgreSQL provide to utilize new method. Also added an Oqtane.Server project reference to the module and theme external templates to streamline the development experience (credit @leighpointer). --- .../PostgreSQLDatabase.cs | 9 +++ Oqtane.Server/Databases/DatabaseBase.cs | 5 ++ .../Databases/Interfaces/IDatabase.cs | 2 + .../Infrastructure/DatabaseManager.cs | 57 +++++++++---------- .../EntityBuilders/BaseEntityBuilder.cs | 18 +++++- .../Tenant/02020001_AddPageIsClickable.cs | 2 +- .../Templates/External/[Owner].[Module].sln | 17 +++--- .../Templates/External/[Owner].[Theme].sln | 13 +++-- 8 files changed, 73 insertions(+), 50 deletions(-) diff --git a/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs index 064e6f34..e482e8a3 100644 --- a/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs +++ b/Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs @@ -88,6 +88,15 @@ namespace Oqtane.Database.PostgreSQL return _rewriter.RewriteName(name); } + public override string RewriteValue(string value, string type) + { + if (type == "bool") + { + value = (value == "1") ? "true" : "false"; + } + return value; + } + public override void UpdateIdentityStoreTableNames(ModelBuilder builder) { foreach(var entity in builder.Model.GetEntityTypes()) diff --git a/Oqtane.Server/Databases/DatabaseBase.cs b/Oqtane.Server/Databases/DatabaseBase.cs index 42dc5505..bad8ad6c 100644 --- a/Oqtane.Server/Databases/DatabaseBase.cs +++ b/Oqtane.Server/Databases/DatabaseBase.cs @@ -65,6 +65,11 @@ namespace Oqtane.Databases return name; } + public virtual string RewriteValue(string value, string type) + { + return value; + } + public virtual void UpdateIdentityStoreTableNames(ModelBuilder builder) { diff --git a/Oqtane.Server/Databases/Interfaces/IDatabase.cs b/Oqtane.Server/Databases/Interfaces/IDatabase.cs index 93ec5433..2a6c0999 100644 --- a/Oqtane.Server/Databases/Interfaces/IDatabase.cs +++ b/Oqtane.Server/Databases/Interfaces/IDatabase.cs @@ -27,6 +27,8 @@ namespace Oqtane.Databases.Interfaces public string RewriteName(string name); + public string RewriteValue(string value, string type); + public void UpdateIdentityStoreTableNames(ModelBuilder builder); public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString); diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs index b553573a..c81f63a9 100644 --- a/Oqtane.Server/Infrastructure/DatabaseManager.cs +++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs @@ -107,7 +107,7 @@ namespace Oqtane.Infrastructure }; // on upgrade install the associated Nuget package - if (!string.IsNullOrEmpty(install.ConnectionString) && Type.GetType(install.DatabaseType) == null) + if (!string.IsNullOrEmpty(install.ConnectionString)) { InstallDatabase(install); } @@ -206,46 +206,41 @@ namespace Oqtane.Infrastructure try { - var databaseType = install.DatabaseType; + bool installPackages = false; - //Get database Type - var type = Type.GetType(databaseType); - - //Deploy the database components (if necessary) - if (type == null) + // iterate database packages in installation folder + var packagesFolder = new DirectoryInfo(Path.Combine(_environment.ContentRootPath, "Packages")); + foreach (var package in packagesFolder.GetFiles("*.nupkg.bak")) { - //Rename bak extension - var packageFolderName = "Packages"; - var path = _environment.ContentRootPath; - var packagesFolder = new DirectoryInfo(Path.Combine(path, packageFolderName)); - - // iterate through Nuget packages in source folder - foreach (var package in packagesFolder.GetFiles("*.nupkg.bak")) + // determine if package needs to be upgraded or installed + bool upgrade = System.IO.File.Exists(package.FullName.Replace(".nupkg.bak",".log")); + if (upgrade || package.Name.StartsWith(Utilities.GetAssemblyName(install.DatabaseType))) { - if (package.Name.StartsWith(Utilities.GetAssemblyName(install.DatabaseType))) - { - //rename file - var packageName = Path.Combine(package.DirectoryName, package.Name); - packageName = packageName.Substring(0, packageName.IndexOf(".bak")); - package.MoveTo(packageName, true); - } + var packageName = Path.Combine(package.DirectoryName, package.Name); + packageName = packageName.Substring(0, packageName.IndexOf(".bak")); + package.MoveTo(packageName, true); + installPackages = true; } - - //Call InstallationManager to install Database Package + } + if (installPackages) + { using (var scope = _serviceScopeFactory.CreateScope()) { var installationManager = scope.ServiceProvider.GetRequiredService(); installationManager.InstallPackages(); - - var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); - var assembliesFolder = new DirectoryInfo(assemblyPath); - var assemblyFile = new FileInfo($"{assembliesFolder}/{Utilities.GetAssemblyName(install.DatabaseType)}.dll"); - - AssemblyLoadContext.Default.LoadOqtaneAssembly(assemblyFile); - - result.Success = true; } } + + // load the installation database type (if necessary) + if (Type.GetType(install.DatabaseType) == null) + { + var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + var assembliesFolder = new DirectoryInfo(assemblyPath); + var assemblyFile = new FileInfo($"{assembliesFolder}/{Utilities.GetAssemblyName(install.DatabaseType)}.dll"); + AssemblyLoadContext.Default.LoadOqtaneAssembly(assemblyFile); + } + + result.Success = true; } catch (Exception ex) { diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs index e60aaade..07c68631 100644 --- a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs +++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs @@ -37,6 +37,10 @@ namespace Oqtane.Migrations.EntityBuilders return ActiveDatabase.RewriteName(name); } + private string RewriteValue(string value, string type) + { + return ActiveDatabase.RewriteValue(value, type); + } // Column Operations @@ -260,9 +264,19 @@ namespace Oqtane.Migrations.EntityBuilders _migrationBuilder.Sql(deleteSql); } - public void UpdateColumn(string columnName, string value, string condition = "") + public void UpdateColumn(string columnName, string value) { - var updateSql = $"UPDATE {RewriteName(EntityTableName)} SET {RewriteName(columnName)} = {value} "; + UpdateColumn(columnName, value, "", ""); + } + + public void UpdateColumn(string columnName, string value, string condition) + { + UpdateColumn(columnName, value, "", condition); + } + + public void UpdateColumn(string columnName, string value, string type, string condition) + { + var updateSql = $"UPDATE {RewriteName(EntityTableName)} SET {RewriteName(columnName)} = {RewriteValue(value, type)} "; if (!string.IsNullOrEmpty(condition)) { updateSql += $"WHERE {condition}"; diff --git a/Oqtane.Server/Migrations/Tenant/02020001_AddPageIsClickable.cs b/Oqtane.Server/Migrations/Tenant/02020001_AddPageIsClickable.cs index 89f458c1..54b86aaf 100644 --- a/Oqtane.Server/Migrations/Tenant/02020001_AddPageIsClickable.cs +++ b/Oqtane.Server/Migrations/Tenant/02020001_AddPageIsClickable.cs @@ -19,7 +19,7 @@ namespace Oqtane.Migrations.Tenant var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); pageEntityBuilder.AddBooleanColumn("IsClickable", true); - pageEntityBuilder.UpdateColumn("IsClickable", "1"); + pageEntityBuilder.UpdateColumn("IsClickable", "1", "bool", ""); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].[Module].sln b/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].[Module].sln index b06b40c0..5c90cbac 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].[Module].sln +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].[Module].sln @@ -3,45 +3,42 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28621.142 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Oqtane.Server", "..\oqtane.framework\Oqtane.Server\Oqtane.Server.csproj", "{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Client", "Client\[Owner].[Module].Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Server", "Server\[Owner].[Module].Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Shared", "Shared\[Owner].[Module].Shared.csproj", "{18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Module].Package", "Package\[Owner].[Module].Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Package", "Package\[Owner].[Module].Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU - Wasm|Any CPU = Wasm|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.Build.0 = Release|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.Build.0 = Release|Any CPU - {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.ActiveCfg = Release|Any CPU - {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.Build.0 = Release|Any CPU {04B05448-788F-433D-92C0-FED35122D45A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04B05448-788F-433D-92C0-FED35122D45A}.Debug|Any CPU.Build.0 = Debug|Any CPU {04B05448-788F-433D-92C0-FED35122D45A}.Release|Any CPU.ActiveCfg = Release|Any CPU {04B05448-788F-433D-92C0-FED35122D45A}.Release|Any CPU.Build.0 = Release|Any CPU - {04B05448-788F-433D-92C0-FED35122D45A}.Wasm|Any CPU.ActiveCfg = Release|Any CPU - {04B05448-788F-433D-92C0-FED35122D45A}.Wasm|Any CPU.Build.0 = Release|Any CPU {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Release|Any CPU.Build.0 = Release|Any CPU - {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Wasm|Any CPU.ActiveCfg = Release|Any CPU - {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Wasm|Any CPU.Build.0 = Release|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.Build.0 = Release|Any CPU - {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.ActiveCfg = Debug|Any CPU - {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln index 7c1739bd..842aaf4f 100644 --- a/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln @@ -3,29 +3,30 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28621.142 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Oqtane.Server", "..\oqtane.framework\Oqtane.Server\Oqtane.Server.csproj", "{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Theme].Client", "Client\[Owner].[Theme].Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Theme].Package", "Package\[Owner].[Theme].Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Theme].Package", "Package\[Owner].[Theme].Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU - Wasm|Any CPU = Wasm|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.Build.0 = Release|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.Build.0 = Release|Any CPU - {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.ActiveCfg = Release|Any CPU - {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.Build.0 = Release|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.Build.0 = Release|Any CPU - {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.ActiveCfg = Debug|Any CPU - {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE