Merge pull request #1205 from sbwalker/dev
Ensure Install Wizard will only be displayed if the Master database connection string in appsettings.json is not specified. This addresses a potential security issue where the Install Wizard could be displayed in an existing installation if the Master database connection failed during startup.
This commit is contained in:
commit
c037614917
|
@ -1,12 +1,14 @@
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
|
|
||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
@if (!_installed)
|
@if (!_installation.Success)
|
||||||
{
|
{
|
||||||
<Installer />
|
<Installer />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
@if (string.IsNullOrEmpty(_installation.Message))
|
||||||
{
|
{
|
||||||
<CascadingAuthenticationState>
|
<CascadingAuthenticationState>
|
||||||
<CascadingValue Value="@PageState">
|
<CascadingValue Value="@PageState">
|
||||||
|
@ -14,18 +16,24 @@
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingAuthenticationState>
|
</CascadingAuthenticationState>
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="app-alert">
|
||||||
|
@_installation.Message
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private Installation _installation;
|
||||||
private bool _initialized;
|
private bool _initialized;
|
||||||
private bool _installed;
|
|
||||||
|
|
||||||
private PageState PageState { get; set; }
|
private PageState PageState { get; set; }
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var installation = await InstallationService.IsInstalled();
|
_installation = await InstallationService.IsInstalled();
|
||||||
_installed = installation.Success;
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ else
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" ResourceKey="EditSite" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" ResourceKey="EditSite" /></td>
|
||||||
<td><ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete The {0} Site?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" ResourceKey="DeleteSite" /></td>
|
<td><ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete The {0} Site?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" ResourceKey="DeleteSite" /></td>
|
||||||
<td><a href="@(_scheme + context.Name)">@context.Name</a></td>
|
<td><a href="@(_scheme + context.Name +"?reload")">@context.Name</a></td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,7 @@ namespace Oqtane.Controllers
|
||||||
[HttpGet("installed")]
|
[HttpGet("installed")]
|
||||||
public Installation IsInstalled()
|
public Installation IsInstalled()
|
||||||
{
|
{
|
||||||
bool isInstalled = _databaseManager.IsInstalled();
|
return _databaseManager.IsInstalled();
|
||||||
return new Installation {Success = isInstalled, Message = string.Empty};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("upgrade")]
|
[HttpGet("upgrade")]
|
||||||
|
|
|
@ -33,27 +33,30 @@ namespace Oqtane.Infrastructure
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsInstalled()
|
public Installation IsInstalled()
|
||||||
{
|
{
|
||||||
var defaultConnectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
var result = new Installation { Success = false, Message = string.Empty };
|
||||||
var result = !string.IsNullOrEmpty(defaultConnectionString);
|
if (!string.IsNullOrEmpty(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
|
result.Success = true;
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
var db = scope.ServiceProvider.GetRequiredService<MasterDBContext>();
|
var db = scope.ServiceProvider.GetRequiredService<MasterDBContext>();
|
||||||
result = db.Database.CanConnect();
|
if (db.Database.CanConnect())
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = db.Tenant.Any();
|
var provisioned = db.Tenant.Any();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
result = false;
|
result.Message = "Master Database Not Installed Correctly";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Message = "Cannot Connect To Master Database";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -74,7 +77,8 @@ namespace Oqtane.Infrastructure
|
||||||
// startup or silent installation
|
// startup or silent installation
|
||||||
install = new InstallConfig { ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), TenantName = TenantNames.Master, IsNewTenant = false };
|
install = new InstallConfig { ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), TenantName = TenantNames.Master, IsNewTenant = false };
|
||||||
|
|
||||||
if (!IsInstalled())
|
var installation = IsInstalled();
|
||||||
|
if (!installation.Success)
|
||||||
{
|
{
|
||||||
install.Aliases = GetInstallationConfig(SettingKeys.DefaultAliasKey, string.Empty);
|
install.Aliases = GetInstallationConfig(SettingKeys.DefaultAliasKey, string.Empty);
|
||||||
install.HostPassword = GetInstallationConfig(SettingKeys.HostPasswordKey, string.Empty);
|
install.HostPassword = GetInstallationConfig(SettingKeys.HostPasswordKey, string.Empty);
|
||||||
|
@ -97,6 +101,14 @@ namespace Oqtane.Infrastructure
|
||||||
install.ConnectionString = "";
|
install.ConnectionString = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(installation.Message))
|
||||||
|
{
|
||||||
|
// problem with prior installation
|
||||||
|
install.ConnectionString = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
public interface IDatabaseManager
|
public interface IDatabaseManager
|
||||||
{
|
{
|
||||||
bool IsInstalled();
|
Installation IsInstalled();
|
||||||
Installation Install();
|
Installation Install();
|
||||||
Installation Install(InstallConfig install);
|
Installation Install(InstallConfig install);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,12 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
public void Upgrade(Tenant tenant, string version)
|
public void Upgrade(Tenant tenant, string version)
|
||||||
{
|
{
|
||||||
// core framework upgrade logic - note that you can check if current tenant is Master if you only want to execute logic once
|
// core framework upgrade logic - note that you can check if current tenant is Master if you only want to execute the logic once
|
||||||
var pageTemplates = new List<PageTemplate>();
|
|
||||||
|
|
||||||
switch (version)
|
switch (version)
|
||||||
{
|
{
|
||||||
case "0.9.0":
|
case "0.9.0":
|
||||||
// add a page to all existing sites on upgrade
|
// this code is commented out on purpose - it provides an example of how to programmatically add a page to all existing sites on upgrade
|
||||||
|
var pageTemplates = new List<PageTemplate>();
|
||||||
//pageTemplates.Add(new PageTemplate
|
//pageTemplates.Add(new PageTemplate
|
||||||
//{
|
//{
|
||||||
// Name = "Test",
|
// Name = "Test",
|
||||||
|
@ -68,7 +66,12 @@ namespace Oqtane.Infrastructure
|
||||||
case "2.0.2":
|
case "2.0.2":
|
||||||
if (tenant.Name == TenantNames.Master)
|
if (tenant.Name == TenantNames.Master)
|
||||||
{
|
{
|
||||||
Directory.Delete(Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", "Internal", Path.DirectorySeparatorChar.ToString()), true);
|
// remove Internal module template files as they are no longer supported
|
||||||
|
var internalTemplatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", "Internal", Path.DirectorySeparatorChar.ToString());
|
||||||
|
if (Directory.Exists(internalTemplatePath))
|
||||||
|
{
|
||||||
|
Directory.Delete(internalTemplatePath, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
|
|
||||||
@if (Model.Message != "")
|
@if (Model.Message != "")
|
||||||
{
|
{
|
||||||
|
<div class="app-alert">
|
||||||
@Model.Message
|
@Model.Message
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<script src="js/interop.js"></script>
|
<script src="js/interop.js"></script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
|
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
|
@ -125,6 +125,13 @@ app {
|
||||||
vertical-align: inherit;
|
vertical-align: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-alert {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f44336; /* red */
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tooltips */
|
/* Tooltips */
|
||||||
.app-tooltip {
|
.app-tooltip {
|
||||||
cursor: help;
|
cursor: help;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user