From 8f1c760e873ddd527f5c84b4086f51d69fcd0a29 Mon Sep 17 00:00:00 2001 From: Charles Nurse Date: Sun, 21 Mar 2021 14:52:45 -0700 Subject: [PATCH] Updated the Installation of Oqtane to use Migrations --- Oqtane.Server/Controllers/SqlController.cs | 5 +- Oqtane.Server/Data/Oqtane.db | Bin 0 -> 200704 bytes .../Infrastructure/DatabaseManager.cs | 276 +++++++++--------- .../Infrastructure/Interfaces/IInstallable.cs | 5 +- .../Infrastructure/Interfaces/IMigratable.cs | 10 + .../HtmlText/Manager/HtmlTextManager.cs | 70 +++-- .../Migrations/01000000_InitializeModule.cs | 26 ++ .../EntityBuilders/HtmlTextEntityBuilder.cs | 43 +++ .../HtmlText/Repository/HtmlTextContext.cs | 2 +- .../HtmlText/Scripts/HtmlText.1.0.0.sql | 19 -- .../HtmlText/Scripts/HtmlText.Uninstall.sql | 2 - Oqtane.Server/Oqtane.Server.csproj | 10 +- .../Repository/Context/DBContextBase.cs | 50 ++-- Oqtane.Server/Repository/Context/DbConfig.cs | 20 ++ .../Repository/Context/DbContextUtils.cs | 2 +- .../Repository/Context/InstallationContext.cs | 3 + .../Repository/Context/MasterDBContext.cs | 33 ++- .../Repository/Context/TenantDBContext.cs | 2 +- .../Repository/Interfaces/IDbConfig.cs | 14 + .../Repository/Interfaces/ISqlRepository.cs | 4 +- Oqtane.Server/Repository/SqlRepository.cs | 6 +- Oqtane.Server/Startup.cs | 3 +- Oqtane.Server/appsettings.json | 6 +- .../wwwroot/Modules/Oqtane.Blogs/Module.css | 1 + .../wwwroot/Modules/Oqtane.Blogs/Module.js | 1 + .../wwwroot/Modules/Oqtane.Blogs/assets.json | 1 + Oqtane.Shared/Enums/MigrationType.cs | 8 + 27 files changed, 390 insertions(+), 232 deletions(-) create mode 100644 Oqtane.Server/Data/Oqtane.db create mode 100644 Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs create mode 100644 Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs create mode 100644 Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs delete mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql delete mode 100644 Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql create mode 100644 Oqtane.Server/Repository/Context/DbConfig.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IDbConfig.cs create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js create mode 100644 Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json create mode 100644 Oqtane.Shared/Enums/MigrationType.cs diff --git a/Oqtane.Server/Controllers/SqlController.cs b/Oqtane.Server/Controllers/SqlController.cs index 7e7bedcc..d2a13078 100644 --- a/Oqtane.Server/Controllers/SqlController.cs +++ b/Oqtane.Server/Controllers/SqlController.cs @@ -6,11 +6,8 @@ using Oqtane.Shared; using Oqtane.Infrastructure; using Oqtane.Repository; using Oqtane.Enums; -using System.Data.SqlClient; -using System.Data; -using System.Dynamic; -using Newtonsoft.Json; using System; +using Microsoft.Data.SqlClient; namespace Oqtane.Controllers { diff --git a/Oqtane.Server/Data/Oqtane.db b/Oqtane.Server/Data/Oqtane.db new file mode 100644 index 0000000000000000000000000000000000000000..d02cc5a4e260a659fdcdeb39c8340186f72a2eab GIT binary patch literal 200704 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 s.Contains("Master.") && s.EndsWith(".sql",StringComparison.OrdinalIgnoreCase)); - - var upgrade = upgradeConfig.Build(); - if (upgrade.IsUpgradeRequired()) + try { - var upgradeResult = upgrade.PerformUpgrade(); - result.Success = upgradeResult.Successful; - if (!result.Success) + var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString}; + + using (var masterDbContext = new MasterDBContext(new DbContextOptions(), dbConfig)) { - result.Message = upgradeResult.Error.Message; + // Push latest model into database + masterDbContext.Database.Migrate(); + result.Success = true; } } - else + catch (Exception ex) { - result.Success = true; + result.Message = ex.Message; } if (result.Success) @@ -251,10 +247,14 @@ namespace Oqtane.Infrastructure tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName); } - foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (var aliasName in install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { - var alias = new Alias { Name = aliasname, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; - db.Alias.Add(alias); + if (tenant != null) + { + var alias = new Alias { Name = aliasName, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow }; + db.Alias.Add(alias); + } + db.SaveChanges(); } _cache.Remove("aliases"); @@ -270,7 +270,7 @@ namespace Oqtane.Infrastructure { var result = new Installation { Success = false, Message = string.Empty }; - string[] versions = Constants.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var versions = Constants.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); using (var scope = _serviceScopeFactory.CreateScope()) { @@ -280,29 +280,28 @@ namespace Oqtane.Infrastructure { foreach (var tenant in db.Tenant.ToList()) { - MigrateScriptNamingConvention("Tenant", tenant.DBConnectionString); - - var upgradeConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(tenant.DBConnectionString)) - .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains("Tenant.") && s.EndsWith(".sql", StringComparison.OrdinalIgnoreCase)); - - var upgrade = upgradeConfig.Build(); - if (upgrade.IsUpgradeRequired()) + try { - var upgradeResult = upgrade.PerformUpgrade(); - result.Success = upgradeResult.Successful; - if (!result.Success) + var dbConfig = new DbConfig(null, null) {ConnectionString = install.ConnectionString}; + using (var tenantDbContext = new TenantDBContext(dbConfig, null)) { - result.Message = upgradeResult.Error.Message; + // Push latest model into database + tenantDbContext.Database.Migrate(); + result.Success = true; } } + catch (Exception ex) + { + result.Message = ex.Message; + } // execute any version specific upgrade logic - string version = tenant.Version; - int index = Array.FindIndex(versions, item => item == version); + var version = tenant.Version; + var index = Array.FindIndex(versions, item => item == version); if (index != (versions.Length - 1)) { if (index == -1) index = 0; - for (int i = index; i < versions.Length; i++) + for (var i = index; i < versions.Length; i++) { upgrades.Upgrade(tenant, versions[i]); } @@ -328,53 +327,61 @@ namespace Oqtane.Infrastructure using (var scope = _serviceScopeFactory.CreateScope()) { - var moduledefinitions = scope.ServiceProvider.GetRequiredService(); + var moduleDefinitions = scope.ServiceProvider.GetRequiredService(); var sql = scope.ServiceProvider.GetRequiredService(); - foreach (var moduledefinition in moduledefinitions.GetModuleDefinitions()) + foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions()) { - if (!string.IsNullOrEmpty(moduledefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduledefinition.ServerManagerType)) + if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduleDefinition.ServerManagerType)) { - Type moduletype = Type.GetType(moduledefinition.ServerManagerType); - if (moduletype != null) + var moduleType = Type.GetType(moduleDefinition.ServerManagerType); + if (moduleType != null) { - string[] versions = moduledefinition.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) { foreach (var tenant in db.Tenant.ToList()) { - int index = Array.FindIndex(versions, item => item == moduledefinition.Version); - if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) + if (moduleType.GetInterface("IMigratable") != null) { - index = -1; + var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType) as IMigratable; + moduleObject.Migrate(tenant, MigrationType.Up); } - if (index != (versions.Length - 1)) + else { - if (index == -1) index = 0; - for (int i = index; i < versions.Length; i++) + var index = Array.FindIndex(versions, item => item == moduleDefinition.Version); + if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master) { - try + index = -1; + } + if (index != (versions.Length - 1)) + { + if (index == -1) index = 0; + for (var i = index; i < versions.Length; i++) { - if (moduletype.GetInterface("IInstallable") != null) + try { - var moduleobject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduletype); - ((IInstallable)moduleobject).Install(tenant, versions[i]); + if (moduleType.GetInterface("IInstallable") != null) + { + var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType); + ((IInstallable)moduleObject).Install(tenant, versions[i]); + } + else + { + sql.ExecuteScript(tenant, moduleType.Assembly, Utilities.GetTypeName(moduleDefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); + } } - else + catch (Exception ex) { - sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + "." + versions[i] + ".sql"); + result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message; } } - catch (Exception ex) - { - result.Message = "An Error Occurred Installing " + moduledefinition.Name + " Version " + versions[i] + " - " + ex.Message.ToString(); - } } } } - if (string.IsNullOrEmpty(result.Message) && moduledefinition.Version != versions[versions.Length - 1]) + if (string.IsNullOrEmpty(result.Message) && moduleDefinition.Version != versions[versions.Length - 1]) { - moduledefinition.Version = versions[versions.Length - 1]; - db.Entry(moduledefinition).State = EntityState.Modified; + moduleDefinition.Version = versions[versions.Length - 1]; + db.Entry(moduleDefinition).State = EntityState.Modified; db.SaveChanges(); } } @@ -401,8 +408,8 @@ namespace Oqtane.Infrastructure { // use the SiteState to set the Alias explicitly so the tenant can be resolved var aliases = scope.ServiceProvider.GetRequiredService(); - string firstalias = install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0]; - var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstalias); + var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0]; + var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias); var siteState = scope.ServiceProvider.GetRequiredService(); siteState.Alias = alias; @@ -413,82 +420,88 @@ namespace Oqtane.Infrastructure var tenants = scope.ServiceProvider.GetRequiredService(); var users = scope.ServiceProvider.GetRequiredService(); var roles = scope.ServiceProvider.GetRequiredService(); - var userroles = scope.ServiceProvider.GetRequiredService(); + var userRoles = scope.ServiceProvider.GetRequiredService(); var folders = scope.ServiceProvider.GetRequiredService(); var log = scope.ServiceProvider.GetRequiredService(); var identityUserManager = scope.ServiceProvider.GetRequiredService>(); var tenant = tenants.GetTenants().FirstOrDefault(item => item.Name == install.TenantName); - site = new Site + if (tenant != null) { - TenantId = tenant.TenantId, - Name = install.SiteName, - LogoFileId = null, - DefaultThemeType = install.DefaultTheme, - DefaultLayoutType = install.DefaultLayout, - DefaultContainerType = install.DefaultContainer, - SiteTemplateType = install.SiteTemplate - }; - site = sites.AddSite(site); - - IdentityUser identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); - if (identityUser == null) - { - identityUser = new IdentityUser { UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true }; - var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); - if (create.Succeeded) + site = new Site { - var user = new User - { - SiteId = site.SiteId, - Username = UserNames.Host, - Password = install.HostPassword, - Email = install.HostEmail, - DisplayName = install.HostName, - LastIPAddress = "", - LastLoginOn = null - }; + TenantId = tenant.TenantId, + Name = install.SiteName, + LogoFileId = null, + DefaultThemeType = install.DefaultTheme, + DefaultLayoutType = install.DefaultLayout, + DefaultContainerType = install.DefaultContainer, + SiteTemplateType = install.SiteTemplate + }; + site = sites.AddSite(site); - user = users.AddUser(user); - var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; - var userRole = new UserRole { UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null }; - userroles.AddUserRole(userRole); - - // add user folder - var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); - if (folder != null) + var identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult(); + if (identityUser == null) + { + identityUser = new IdentityUser {UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true}; + var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult(); + if (create.Succeeded) { - folders.AddFolder(new Folder + var user = new User { - SiteId = folder.SiteId, - ParentId = folder.FolderId, - Name = "My Folder", - Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), - Order = 1, - IsSystem = true, - Permissions = new List + SiteId = site.SiteId, + Username = UserNames.Host, + Password = install.HostPassword, + Email = install.HostEmail, + DisplayName = install.HostName, + LastIPAddress = "", + LastLoginOn = null + }; + + user = users.AddUser(user); + var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0; + var userRole = new UserRole {UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null}; + userRoles.AddUserRole(userRole); + + // add user folder + var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString())); + if (folder != null) + { + folders.AddFolder(new Folder { - new Permission(PermissionNames.Browse, user.UserId, true), - new Permission(PermissionNames.View, RoleNames.Everyone, true), - new Permission(PermissionNames.Edit, user.UserId, true), - }.EncodePermissions(), - }); + SiteId = folder.SiteId, + ParentId = folder.FolderId, + Name = "My Folder", + Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()), + Order = 1, + IsSystem = true, + Permissions = new List + { + new Permission(PermissionNames.Browse, user.UserId, true), + new Permission(PermissionNames.View, RoleNames.Everyone, true), + new Permission(PermissionNames.Edit, user.UserId, true), + }.EncodePermissions(), + }); + } } } + + foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) + { + alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName); + if (alias != null) + { + alias.SiteId = site.SiteId; + aliases.UpdateAlias(alias); + } + } + + tenant.Version = Constants.Version; + tenants.UpdateTenant(tenant); } - foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) - { - alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasname); - alias.SiteId = site.SiteId; - aliases.UpdateAlias(alias); - } - - tenant.Version = Constants.Version; - tenants.UpdateTenant(tenant); - - log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); + if (site != null) log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); } } } @@ -508,7 +521,7 @@ namespace Oqtane.Infrastructure private string DenormalizeConnectionString(string connectionString) { var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString(); - connectionString = connectionString.Replace(dataDirectory, "|DataDirectory|"); + connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|"); return connectionString; } @@ -567,18 +580,5 @@ namespace Oqtane.Infrastructure if (string.IsNullOrEmpty(value)) value = defaultValue; return value; } - - private void MigrateScriptNamingConvention(string scriptType, string connectionString) - { - // migrate to new naming convention for scripts - var migrateConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(connectionString)) - .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s == scriptType + ".00.00.00.00.sql"); - var migrate = migrateConfig.Build(); - if (migrate.IsUpgradeRequired()) - { - migrate.PerformUpgrade(); - } - } - } } diff --git a/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs b/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs index baef7184..48ed9bc8 100644 --- a/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs +++ b/Oqtane.Server/Infrastructure/Interfaces/IInstallable.cs @@ -1,10 +1,13 @@ -using Oqtane.Models; +using Microsoft.EntityFrameworkCore; +using Oqtane.Enums; +using Oqtane.Models; namespace Oqtane.Infrastructure { public interface IInstallable { bool Install(Tenant tenant, string version); + bool Uninstall(Tenant tenant); } } diff --git a/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs b/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs new file mode 100644 index 00000000..009268fc --- /dev/null +++ b/Oqtane.Server/Infrastructure/Interfaces/IMigratable.cs @@ -0,0 +1,10 @@ +using Oqtane.Enums; +using Oqtane.Models; + +namespace Oqtane.Infrastructure +{ + public interface IMigratable + { + bool Migrate(Tenant tenant, MigrationType migrationType); + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index 7e068076..d8afa1b2 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -1,40 +1,64 @@ -using Oqtane.Infrastructure; +using System; +using Oqtane.Infrastructure; using Oqtane.Models; using Oqtane.Repository; using Oqtane.Modules.HtmlText.Models; using Oqtane.Modules.HtmlText.Repository; using System.Net; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Enums; +// ReSharper disable ConvertToUsingDeclaration namespace Oqtane.Modules.HtmlText.Manager { - public class HtmlTextManager : IInstallable, IPortable + public class HtmlTextManager : IMigratable, IPortable { - private IHtmlTextRepository _htmlTexts; - private ISqlRepository _sql; + private readonly IHtmlTextRepository _htmlText; + private readonly ISqlRepository _sql; - public HtmlTextManager(IHtmlTextRepository htmltexts, ISqlRepository sql) + public HtmlTextManager(IHtmlTextRepository htmlText, ISqlRepository sql) { - _htmlTexts = htmltexts; + _htmlText = htmlText; _sql = sql; } - public bool Install(Tenant tenant, string version) + public bool Migrate(Tenant tenant, MigrationType migrationType) { - return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText." + version + ".sql"); - } + var result = true; - public bool Uninstall(Tenant tenant) - { - return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText.Uninstall.sql"); + var dbConfig = new DbConfig(null, null) {ConnectionString = tenant.DBConnectionString}; + using (var db = new HtmlTextContext(dbConfig, null)) + { + try + { + var migrator = db.GetService(); + if (migrationType == MigrationType.Down) + { + migrator.Migrate(Migration.InitialDatabase); + } + else + { + migrator.Migrate(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + result = false; + } + + } + return result; } public string ExportModule(Module module) { string content = ""; - HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId); - if (htmltext != null) + var htmlText = _htmlText.GetHtmlText(module.ModuleId); + if (htmlText != null) { - content = WebUtility.HtmlEncode(htmltext.Content); + content = WebUtility.HtmlEncode(htmlText.Content); } return content; } @@ -42,18 +66,18 @@ namespace Oqtane.Modules.HtmlText.Manager public void ImportModule(Module module, string content, string version) { content = WebUtility.HtmlDecode(content); - HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId); - if (htmltext != null) + var htmlText = _htmlText.GetHtmlText(module.ModuleId); + if (htmlText != null) { - htmltext.Content = content; - _htmlTexts.UpdateHtmlText(htmltext); + htmlText.Content = content; + _htmlText.UpdateHtmlText(htmlText); } else { - htmltext = new HtmlTextInfo(); - htmltext.ModuleId = module.ModuleId; - htmltext.Content = content; - _htmlTexts.AddHtmlText(htmltext); + htmlText = new HtmlTextInfo(); + htmlText.ModuleId = module.ModuleId; + htmlText.Content = content; + _htmlText.AddHtmlText(htmlText); } } } diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs new file mode 100644 index 00000000..2214df2c --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Migrations/01000000_InitializeModule.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Modules.HtmlText.Migrations.EntityBuilders; +using Oqtane.Modules.HtmlText.Repository; + +namespace Oqtane.Modules.HtmlText.Migrations +{ + [DbContext(typeof(HtmlTextContext))] + [Migration("HtmlText.01.00.00.00")] + public class InitializeModule : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //Create HtmlText table + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + entityBuilder.Create(); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + //Drop HtmlText table + var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder); + entityBuilder.Drop(); + } + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs new file mode 100644 index 00000000..972c4c7d --- /dev/null +++ b/Oqtane.Server/Modules/HtmlText/Migrations/EntityBuilders/HtmlTextEntityBuilder.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; +using Oqtane.Migrations; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Migrations.Extensions; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders +{ + public class HtmlTextEntityBuilder : AuditableBaseEntityBuilder + { + private const string _entityTableName = "HtmlText"; + private readonly PrimaryKey _primaryKey = new("PK_HtmlText", x => x.HtmlTextId); + private readonly ForeignKey _moduleForeignKey = new("FK_HtmlText_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade); + + public HtmlTextEntityBuilder(MigrationBuilder migrationBuilder) : base(migrationBuilder) + { + EntityTableName = _entityTableName; + PrimaryKey = _primaryKey; + ForeignKeys.Add(_moduleForeignKey); + } + + protected override HtmlTextEntityBuilder BuildTable(ColumnsBuilder table) + { + HtmlTextId = table.AddAutoIncrementColumn("HtmlTextId"); + ModuleId = table.AddIntegerColumn("ModuleId"); + Content = table.AddMaxStringColumn("Content"); + + AddAuditableColumns(table); + + return this; + } + + public OperationBuilder HtmlTextId { get; set; } + + public OperationBuilder ModuleId { get; set; } + + public OperationBuilder Content { get; set; } + } +} diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index e9ac5d12..f4aaf48c 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -10,7 +10,7 @@ namespace Oqtane.Modules.HtmlText.Repository { public virtual DbSet HtmlText { get; set; } - public HtmlTextContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) + public HtmlTextContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { // ContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql deleted file mode 100644 index 5c54eae2..00000000 --- a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.1.0.0.sql +++ /dev/null @@ -1,19 +0,0 @@ -CREATE TABLE [dbo].[HtmlText]( - [HtmlTextId] [int] IDENTITY(1,1) NOT NULL, - [ModuleId] [int] NOT NULL, - [Content] [nvarchar](max) NOT NULL, - [CreatedBy] [nvarchar](256) NOT NULL, - [CreatedOn] [datetime] NOT NULL, - [ModifiedBy] [nvarchar](256) NOT NULL, - [ModifiedOn] [datetime] NOT NULL, - CONSTRAINT [PK_HtmlText] PRIMARY KEY CLUSTERED - ( - [HtmlTextId] ASC - ) -) -GO - -ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId]) -REFERENCES [dbo].[Module] ([ModuleId]) -ON DELETE CASCADE -GO diff --git a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql b/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql deleted file mode 100644 index b0831b67..00000000 --- a/Oqtane.Server/Modules/HtmlText/Scripts/HtmlText.Uninstall.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP TABLE [dbo].[HtmlText] -GO diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index db1b8192..a87d0533 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -20,6 +20,9 @@ + + + @@ -36,14 +39,12 @@ - - - + all @@ -67,6 +68,9 @@ + + + diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index d6535f0c..013675d0 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -7,48 +7,56 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; using Oqtane.Models; +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess namespace Oqtane.Repository { public class DBContextBase : IdentityUserContext { - private ITenantResolver _tenantResolver; - private IHttpContextAccessor _accessor; - private readonly IConfiguration _configuration; + private readonly IDbConfig _dbConfig; + private readonly ITenantResolver _tenantResolver; - public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) + public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver) { + _dbConfig = dbConfig; _tenantResolver = tenantResolver; - _accessor = accessor; - _configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - var tenant = _tenantResolver.GetTenant(); - if (tenant != null) + var connectionString = _dbConfig.ConnectionString; + + if (string.IsNullOrEmpty(connectionString) && _tenantResolver != null) + { + var tenant = _tenantResolver.GetTenant(); + var configuration = _dbConfig.Configuration; + + if (tenant != null) + { + connectionString = tenant.DBConnectionString + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + else + { + if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) + { + connectionString = configuration.GetConnectionString("DefaultConnection") + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + } + } + + if (!string.IsNullOrEmpty(connectionString)) { - var connectionString = tenant.DBConnectionString - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); optionsBuilder.UseOqtaneDatabase(connectionString); } - else - { - if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) - { - var connectionString = _configuration.GetConnectionString("DefaultConnection") - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); - optionsBuilder.UseOqtaneDatabase(connectionString); - } - - } base.OnConfiguring(optionsBuilder); } public override int SaveChanges() { - DbContextUtils.SaveChanges(this, _accessor); + DbContextUtils.SaveChanges(this, _dbConfig.Accessor); return base.SaveChanges(); } diff --git a/Oqtane.Server/Repository/Context/DbConfig.cs b/Oqtane.Server/Repository/Context/DbConfig.cs new file mode 100644 index 00000000..7bc5cb8a --- /dev/null +++ b/Oqtane.Server/Repository/Context/DbConfig.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace Oqtane.Repository +{ + public class DbConfig : IDbConfig + { + public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration) + { + Accessor = accessor; + Configuration = configuration; + } + + public IHttpContextAccessor Accessor { get; } + + public IConfiguration Configuration { get; } + + public string ConnectionString { get; set; } + } +} diff --git a/Oqtane.Server/Repository/Context/DbContextUtils.cs b/Oqtane.Server/Repository/Context/DbContextUtils.cs index 1b4014cb..aa204cad 100644 --- a/Oqtane.Server/Repository/Context/DbContextUtils.cs +++ b/Oqtane.Server/Repository/Context/DbContextUtils.cs @@ -6,7 +6,7 @@ using Oqtane.Models; namespace Oqtane.Repository { - public class DbContextUtils + public static class DbContextUtils { public static void SaveChanges(DbContext context, IHttpContextAccessor accessor) { diff --git a/Oqtane.Server/Repository/Context/InstallationContext.cs b/Oqtane.Server/Repository/Context/InstallationContext.cs index 6eaf5a65..52036bbe 100644 --- a/Oqtane.Server/Repository/Context/InstallationContext.cs +++ b/Oqtane.Server/Repository/Context/InstallationContext.cs @@ -22,5 +22,8 @@ namespace Oqtane.Repository public virtual DbSet Tenant { get; set; } public virtual DbSet ModuleDefinition { get; set; } public virtual DbSet Job { get; set; } + public virtual DbSet JobLog { get; set; } + + } } diff --git a/Oqtane.Server/Repository/Context/MasterDBContext.cs b/Oqtane.Server/Repository/Context/MasterDBContext.cs index dd94dedd..68ef6b07 100644 --- a/Oqtane.Server/Repository/Context/MasterDBContext.cs +++ b/Oqtane.Server/Repository/Context/MasterDBContext.cs @@ -1,31 +1,42 @@ using System; -using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Oqtane.Models; using Microsoft.Extensions.Configuration; using Oqtane.Extensions; +// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable CheckNamespace + namespace Oqtane.Repository { public class MasterDBContext : DbContext { - private readonly IHttpContextAccessor _accessor; - private readonly IConfiguration _configuration; + private readonly IDbConfig _dbConfig; - public MasterDBContext(DbContextOptions options, IHttpContextAccessor accessor, IConfiguration configuration) : base(options) + public MasterDBContext(DbContextOptions options, IDbConfig dbConfig) : base(options) { - _accessor = accessor; - _configuration = configuration; + _dbConfig = dbConfig; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection"))) - { - var connectionString = _configuration.GetConnectionString("DefaultConnection") - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + var connectionString = _dbConfig.ConnectionString; + var configuration = _dbConfig.Configuration; + if(string.IsNullOrEmpty(connectionString) && configuration != null) + { + if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection"))) + { + connectionString = configuration.GetConnectionString("DefaultConnection") + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()); + } + + } + + if (!string.IsNullOrEmpty(connectionString)) + { optionsBuilder.UseOqtaneDatabase(connectionString); } base.OnConfiguring(optionsBuilder); @@ -39,7 +50,7 @@ namespace Oqtane.Repository public override int SaveChanges() { - DbContextUtils.SaveChanges(this, _accessor); + DbContextUtils.SaveChanges(this, _dbConfig.Accessor); return base.SaveChanges(); } diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index 4390739f..3e2f5d3d 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -24,7 +24,7 @@ namespace Oqtane.Repository public virtual DbSet Language { get; set; } - public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor, IConfiguration configuration) : base(tenantResolver, accessor, configuration) + public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { // DBContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Repository/Interfaces/IDbConfig.cs b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs new file mode 100644 index 00000000..6ba4cfbe --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/IDbConfig.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace Oqtane.Repository +{ + public interface IDbConfig + { + public IHttpContextAccessor Accessor { get; } + + public IConfiguration Configuration { get; } + + public string ConnectionString { get; set; } + } +} diff --git a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs index a1402e3b..76a6f701 100644 --- a/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISqlRepository.cs @@ -1,5 +1,5 @@ -using System.Data.SqlClient; -using System.Reflection; +using System.Reflection; +using Microsoft.Data.SqlClient; using Oqtane.Models; namespace Oqtane.Repository diff --git a/Oqtane.Server/Repository/SqlRepository.cs b/Oqtane.Server/Repository/SqlRepository.cs index fcc4caf3..037a9e42 100644 --- a/Oqtane.Server/Repository/SqlRepository.cs +++ b/Oqtane.Server/Repository/SqlRepository.cs @@ -1,9 +1,9 @@ using System; using System.Data; -using System.Data.SqlClient; using System.IO; using System.Linq; using System.Reflection; +using Microsoft.Data.SqlClient; using Oqtane.Models; namespace Oqtane.Repository @@ -59,8 +59,8 @@ namespace Oqtane.Repository public int ExecuteNonQuery(Tenant tenant, string query) { - SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); - SqlCommand cmd = conn.CreateCommand(); + var conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString)); + var cmd = conn.CreateCommand(); using (conn) { PrepareCommand(conn, cmd, query); diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index ba2a7d89..5ba2ff1b 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -130,6 +130,7 @@ namespace Oqtane services.AddSingleton(); + services.AddScoped(); services.AddDbContext(options => { }); services.AddDbContext(options => { }); @@ -211,7 +212,7 @@ namespace Oqtane services.AddTransient(); services.AddTransient(); - // load the external assemblies into the app domain, install services + // load the external assemblies into the app domain, install services services.AddOqtane(_runtime, _supportedCultures); services.AddMvc() diff --git a/Oqtane.Server/appsettings.json b/Oqtane.Server/appsettings.json index 1af87b4c..06f423f8 100644 --- a/Oqtane.Server/appsettings.json +++ b/Oqtane.Server/appsettings.json @@ -1,6 +1,10 @@ { + "Database": { + "DatabaseType": "", + "DatabaseEngineVersion": "" + }, "ConnectionStrings": { - "DefaultConnection": "" + "DefaultConnection": "Data Source=.;Initial Catalog=Oqtane-Migrations;Integrated Security=SSPI;" }, "Runtime": "Server", "Installation": { diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css new file mode 100644 index 00000000..0856a263 --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css @@ -0,0 +1 @@ +/* Module Custom Styles */ \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js new file mode 100644 index 00000000..1b415a08 --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js @@ -0,0 +1 @@ +/* Module Script */ \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json new file mode 100644 index 00000000..72f421fc --- /dev/null +++ b/Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json @@ -0,0 +1 @@ +["\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.pdb","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.css","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.js"] \ No newline at end of file diff --git a/Oqtane.Shared/Enums/MigrationType.cs b/Oqtane.Shared/Enums/MigrationType.cs new file mode 100644 index 00000000..e428520a --- /dev/null +++ b/Oqtane.Shared/Enums/MigrationType.cs @@ -0,0 +1,8 @@ +namespace Oqtane.Enums +{ + public enum MigrationType + { + Up, + Down + } +}