commit
6c8703356f
|
@ -31,7 +31,7 @@
|
|||
{
|
||||
foreach (var database in _databases)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
|
@ -174,7 +174,6 @@
|
|||
var config = new InstallConfig
|
||||
{
|
||||
DatabaseType = database.DBType,
|
||||
DatabasePackage = database.Package,
|
||||
ConnectionString = connectionString,
|
||||
Aliases = uri.Authority,
|
||||
HostEmail = _hostEmail,
|
||||
|
|
|
@ -130,7 +130,7 @@ else
|
|||
<select id="databaseType" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@foreach (var database in _databases)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
|
@ -305,7 +305,6 @@ else
|
|||
{
|
||||
config.TenantName = _tenantName;
|
||||
config.DatabaseType = database.DBType;
|
||||
config.DatabasePackage = database.Package;
|
||||
config.ConnectionString = connectionString;
|
||||
config.HostEmail = user.Email;
|
||||
config.HostPassword = _hostpassword;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Oqtane.Services
|
|||
public async Task<List<Database>> GetDatabasesAsync()
|
||||
{
|
||||
List<Database> databases = await GetJsonAsync<List<Database>>(Apiurl);
|
||||
return databases.OrderBy(item => item.FriendlyName).ToList();
|
||||
return databases.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Interfaces;
|
||||
// ReSharper disable ConvertToUsingDeclaration
|
||||
|
||||
namespace Oqtane.Extensions
|
||||
|
|
102
Oqtane.Server/Infrastructure/ConfigManager.cs
Normal file
102
Oqtane.Server/Infrastructure/ConfigManager.cs
Normal file
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class ConfigManager : IConfigManager
|
||||
{
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
||||
public ConfigManager(IConfigurationRoot config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public IConfigurationSection GetSection(string key)
|
||||
{
|
||||
return _config.GetSection(key);
|
||||
}
|
||||
|
||||
public string GetSetting(string sectionKey, string settingKey, string defaultValue)
|
||||
{
|
||||
var value = _config.GetSection(sectionKey).GetValue(settingKey, defaultValue);
|
||||
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
public void AddOrUpdateSetting<T>(string key, T value, bool reload)
|
||||
{
|
||||
AddOrUpdateSetting("appsettings.json", key, value, reload);
|
||||
}
|
||||
|
||||
public void AddOrUpdateSetting<T>(string file, string key, T value, bool reload)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Directory.GetCurrentDirectory(), file);
|
||||
dynamic jsonObj = JsonConvert.DeserializeObject(File.ReadAllText(path));
|
||||
SetValueRecursively(key, jsonObj, value, "set");
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
|
||||
if (reload) Reload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error modifying app settings {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSetting(string key, bool reload)
|
||||
{
|
||||
RemoveSetting("appsettings.json", key, reload);
|
||||
}
|
||||
|
||||
public void RemoveSetting(string file, string key, bool reload)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Directory.GetCurrentDirectory(), file);
|
||||
dynamic jsonObj = JsonConvert.DeserializeObject(File.ReadAllText(path));
|
||||
SetValueRecursively(key, jsonObj, "", "remove");
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
|
||||
if (reload) Reload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error modifying app settings {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetValueRecursively<T>(string key, dynamic jsonObj, T value, string action)
|
||||
{
|
||||
var remainingSections = key.Split(":", 2);
|
||||
|
||||
var currentSection = remainingSections[0];
|
||||
if (remainingSections.Length > 1)
|
||||
{
|
||||
var nextSection = remainingSections[1];
|
||||
jsonObj[currentSection] ??= new JObject();
|
||||
SetValueRecursively(nextSection, jsonObj[currentSection], value, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case "set":
|
||||
jsonObj[currentSection] = value;
|
||||
break;
|
||||
case "remove":
|
||||
jsonObj.Property(currentSection).Remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
_config.Reload();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,14 +10,13 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Enums;
|
||||
using File = System.IO.File;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable ConvertToUsingDeclaration
|
||||
|
@ -32,18 +31,23 @@ namespace Oqtane.Infrastructure
|
|||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IConfigManager _configManager;
|
||||
|
||||
public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache)
|
||||
public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager)
|
||||
{
|
||||
_config = config;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_environment = environment;
|
||||
_cache = cache;
|
||||
_configManager = configManager;
|
||||
}
|
||||
|
||||
public Installation IsInstalled()
|
||||
{
|
||||
var result = new Installation { Success = false, Message = string.Empty };
|
||||
|
||||
ValidateConfiguration();
|
||||
|
||||
if (!string.IsNullOrEmpty(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))
|
||||
{
|
||||
result.Success = true;
|
||||
|
@ -97,7 +101,6 @@ namespace Oqtane.Infrastructure
|
|||
if (string.IsNullOrEmpty(install.DatabaseType))
|
||||
{
|
||||
install.DatabaseType = Constants.DefaultDBType;
|
||||
install.DatabasePackage = Constants.DefaultDBType.Substring(Constants.DefaultDBType.IndexOf(",") + 2);
|
||||
InstallDatabase(install);
|
||||
UpdateDatabaseType(install.DatabaseType);
|
||||
}
|
||||
|
@ -106,7 +109,6 @@ namespace Oqtane.Infrastructure
|
|||
// if database type does not exist, install the associated Nuget package
|
||||
if (Type.GetType(install.DatabaseType) == null)
|
||||
{
|
||||
install.DatabasePackage = install.DatabaseType.Substring(install.DatabaseType.IndexOf(",") + 2);
|
||||
InstallDatabase(install);
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +222,7 @@ namespace Oqtane.Infrastructure
|
|||
// iterate through Nuget packages in source folder
|
||||
foreach (var package in packagesFolder.GetFiles("*.nupkg.bak"))
|
||||
{
|
||||
if (package.Name.StartsWith(install.DatabasePackage))
|
||||
if (package.Name.StartsWith(Utilities.GetAssemblyName(install.DatabaseType)))
|
||||
{
|
||||
//rename file
|
||||
var packageName = Path.Combine(package.DirectoryName, package.Name);
|
||||
|
@ -237,7 +239,7 @@ namespace Oqtane.Infrastructure
|
|||
|
||||
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||
var assembliesFolder = new DirectoryInfo(assemblyPath);
|
||||
var assemblyFile = new FileInfo($"{assembliesFolder}/{install.DatabasePackage}.dll");
|
||||
var assemblyFile = new FileInfo($"{assembliesFolder}/{Utilities.GetAssemblyName(install.DatabaseType)}.dll");
|
||||
|
||||
AssemblyLoadContext.Default.LoadOqtaneAssembly(assemblyFile);
|
||||
|
||||
|
@ -644,25 +646,6 @@ namespace Oqtane.Infrastructure
|
|||
return result;
|
||||
}
|
||||
|
||||
public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
|
||||
var json = File.ReadAllText(filePath);
|
||||
dynamic jsonObj = JsonConvert.DeserializeObject(json);
|
||||
|
||||
SetValueRecursively(sectionPathKey, jsonObj, value);
|
||||
|
||||
string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented);
|
||||
File.WriteAllText(filePath, output);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error writing app settings | {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private string DenormalizeConnectionString(string connectionString)
|
||||
{
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||
|
@ -687,10 +670,7 @@ namespace Oqtane.Infrastructure
|
|||
|
||||
private string GetInstallationConfig(string key, string defaultValue)
|
||||
{
|
||||
var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue);
|
||||
// double fallback to default value - allow hold sample keys in config
|
||||
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
||||
return value;
|
||||
return _configManager.GetSetting(SettingKeys.InstallationSection, key, defaultValue);
|
||||
}
|
||||
|
||||
private string NormalizeConnectionString(string connectionString)
|
||||
|
@ -700,39 +680,18 @@ namespace Oqtane.Infrastructure
|
|||
return connectionString;
|
||||
}
|
||||
|
||||
private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
|
||||
{
|
||||
// split the string at the first ':' character
|
||||
var remainingSections = sectionPathKey.Split(":", 2);
|
||||
|
||||
var currentSection = remainingSections[0];
|
||||
if (remainingSections.Length > 1)
|
||||
{
|
||||
// continue with the process, moving down the tree
|
||||
var nextSection = remainingSections[1];
|
||||
SetValueRecursively(nextSection, jsonObj[currentSection], value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've got to the end of the tree, set the value
|
||||
jsonObj[currentSection] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateConnectionString(string connectionString)
|
||||
{
|
||||
connectionString = DenormalizeConnectionString(connectionString);
|
||||
if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString)
|
||||
{
|
||||
AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString);
|
||||
_config.Reload();
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDatabaseType(string databaseType)
|
||||
{
|
||||
AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType);
|
||||
_config.Reload();
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType, true);
|
||||
}
|
||||
|
||||
public void UpgradeSqlServer(ISqlRepository sql, string connectionString, string databaseType, bool isMaster)
|
||||
|
@ -744,5 +703,24 @@ namespace Oqtane.Infrastructure
|
|||
|
||||
sql.ExecuteNonQuery(connectionString, databaseType, query);
|
||||
}
|
||||
|
||||
private void ValidateConfiguration()
|
||||
{
|
||||
if (_configManager.GetSetting(SettingKeys.DatabaseSection, SettingKeys.DatabaseTypeKey, "") == "")
|
||||
{
|
||||
_configManager.AddOrUpdateSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", Constants.DefaultDBType, true);
|
||||
}
|
||||
if (!_configManager.GetSection(SettingKeys.AvailableDatabasesSection).Exists())
|
||||
{
|
||||
string databases = "[";
|
||||
databases += "{ \"Name\": \"LocalDB\", \"ControlType\": \"Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
|
||||
databases += "{ \"Name\": \"SQL Server\", \"ControlType\": \"Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
|
||||
databases += "{ \"Name\": \"SQLite\", \"ControlType\": \"Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Database.Sqlite\" },";
|
||||
databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.MySQL.SqlServerDatabase, Oqtane.Database.MySQL\" },";
|
||||
databases += "{ \"Name\": \"PostgreSQL\", \"ControlType\": \"Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Database.PostgreSQL\" }";
|
||||
databases += "]";
|
||||
_configManager.AddOrUpdateSetting(SettingKeys.AvailableDatabasesSection, JsonConvert.DeserializeObject<dynamic>(databases), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
Oqtane.Server/Infrastructure/Interfaces/IConfigManager.cs
Normal file
15
Oqtane.Server/Infrastructure/Interfaces/IConfigManager.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public interface IConfigManager
|
||||
{
|
||||
public IConfigurationSection GetSection(string sectionKey);
|
||||
public string GetSetting(string sectionKey, string settingKey, string defaultValue);
|
||||
void AddOrUpdateSetting<T>(string key, T value, bool reload);
|
||||
void AddOrUpdateSetting<T>(string file, string key, T value, bool reload);
|
||||
void RemoveSetting(string key, bool reload);
|
||||
void RemoveSetting(string file, string key, bool reload);
|
||||
void Reload();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
|
@ -11,15 +13,15 @@ namespace Oqtane.Infrastructure
|
|||
{
|
||||
public class UpgradeManager : IUpgradeManager
|
||||
{
|
||||
private readonly IAliasRepository _aliases;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IConfigManager _configManager;
|
||||
|
||||
public UpgradeManager(IAliasRepository aliases, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment)
|
||||
public UpgradeManager(IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IConfigManager configManager)
|
||||
{
|
||||
_aliases = aliases;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_environment = environment;
|
||||
_configManager = configManager;
|
||||
}
|
||||
|
||||
public void Upgrade(Tenant tenant, string version)
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Oqtane
|
|||
// Register localization services
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
services.AddOptions<List<Database>>().Bind(Configuration.GetSection("AvailableDatabases"));
|
||||
services.AddOptions<List<Database>>().Bind(Configuration.GetSection(SettingKeys.AvailableDatabasesSection));
|
||||
|
||||
services.AddServerSideBlazor().AddCircuitOptions(options =>
|
||||
{
|
||||
|
@ -176,6 +176,7 @@ namespace Oqtane
|
|||
services.AddSingleton<IInstallationManager, InstallationManager>();
|
||||
services.AddSingleton<ISyncManager, SyncManager>();
|
||||
services.AddSingleton<IDatabaseManager, DatabaseManager>();
|
||||
services.AddSingleton<IConfigManager, ConfigManager>();
|
||||
|
||||
// install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain )
|
||||
InstallationManager.InstallPackages(_env.WebRootPath, _env.ContentRootPath);
|
||||
|
|
|
@ -5,11 +5,6 @@ namespace Oqtane.Models
|
|||
/// </summary>
|
||||
public class Database
|
||||
{
|
||||
/// <summary>
|
||||
/// Friendly name for the Admin to identify the DB
|
||||
/// </summary>
|
||||
public string FriendlyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the Database
|
||||
/// </summary>
|
||||
|
@ -24,10 +19,5 @@ namespace Oqtane.Models
|
|||
/// Type of DB using the full namespace, like `Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer`
|
||||
/// </summary>
|
||||
public string DBType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Software package responsible for using this DB - like `Oqtane.Database.MySQL`
|
||||
/// </summary>
|
||||
public string Package { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Oqtane.Shared
|
|||
{
|
||||
public string ConnectionString { get; set; }
|
||||
public string DatabaseType { get; set; }
|
||||
public string DatabasePackage { get; set; }
|
||||
public string Aliases { get; set; }
|
||||
public string TenantName { get; set; }
|
||||
public bool IsNewTenant { get; set; }
|
||||
|
|
|
@ -16,5 +16,7 @@ namespace Oqtane.Shared
|
|||
public const string DefaultThemeKey = "DefaultTheme";
|
||||
public const string DefaultLayoutKey = "DefaultLayout";
|
||||
public const string DefaultContainerKey = "DefaultContainer";
|
||||
|
||||
public const string AvailableDatabasesSection = "AvailableDatabases";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user