Install Wizard
This commit is contained in:
parent
af70f0a956
commit
1c0d2de9fe
|
@ -1,15 +1,31 @@
|
||||||
@using Oqtane.Shared
|
@using Oqtane.Shared
|
||||||
@using Oqtane.Client.Shared
|
@using Oqtane.Client.Shared
|
||||||
|
@using Oqtane.Services
|
||||||
|
@inject IInstallationService InstallationService
|
||||||
|
|
||||||
<CascadingAuthenticationState>
|
@if (!Installed)
|
||||||
|
{
|
||||||
|
<Installer />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<CascadingAuthenticationState>
|
||||||
<CascadingValue Value="@PageState">
|
<CascadingValue Value="@PageState">
|
||||||
<SiteRouter OnStateChange="@ChangeState" />
|
<SiteRouter OnStateChange="@ChangeState" />
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingAuthenticationState>
|
</CascadingAuthenticationState>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private bool Installed = false;
|
||||||
private PageState PageState { get; set; }
|
private PageState PageState { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitAsync()
|
||||||
|
{
|
||||||
|
var response = await InstallationService.IsInstalled();
|
||||||
|
Installed = response.Success;
|
||||||
|
}
|
||||||
|
|
||||||
private void ChangeState(PageState pagestate)
|
private void ChangeState(PageState pagestate)
|
||||||
{
|
{
|
||||||
PageState = pagestate;
|
PageState = pagestate;
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } }
|
public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } }
|
||||||
|
|
||||||
public string Message { get; set; } = "<div class=\"alert alert-info\" role=\"alert\">Use host/password For Demo Access</div>";
|
public string Message { get; set; } = "";
|
||||||
public string Username { get; set; } = "";
|
public string Username { get; set; } = "";
|
||||||
public string Password { get; set; } = "";
|
public string Password { get; set; } = "";
|
||||||
public bool Remember { get; set; } = false;
|
public bool Remember { get; set; } = false;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
protected override async Task OnInitAsync()
|
protected override async Task OnInitAsync()
|
||||||
{
|
{
|
||||||
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
|
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper);
|
||||||
List<HtmlTextInfo> htmltextlist = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
List<HtmlTextInfo> htmltextlist = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
if (htmltextlist != null)
|
if (htmltextlist != null)
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
private async Task SaveContent()
|
private async Task SaveContent()
|
||||||
{
|
{
|
||||||
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
|
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper);
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
@using Oqtane.Client.Modules.Controls
|
@using Oqtane.Client.Modules.Controls
|
||||||
@using Oqtane.Shared;
|
@using Oqtane.Shared;
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject IUriHelper UriHelper
|
||||||
@inject HttpClient http
|
@inject HttpClient http
|
||||||
@inject SiteState sitestate
|
@inject SiteState sitestate
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@
|
||||||
|
|
||||||
protected override async Task OnInitAsync()
|
protected override async Task OnInitAsync()
|
||||||
{
|
{
|
||||||
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
|
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper);
|
||||||
List<HtmlTextInfo> htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
List<HtmlTextInfo> htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,16 +13,18 @@ namespace Oqtane.Client.Modules.HtmlText.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public HtmlTextService(HttpClient http, SiteState sitestate)
|
public HtmlTextService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "HtmlText"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "HtmlText"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<HtmlTextInfo>> GetHtmlTextAsync(int ModuleId)
|
public async Task<List<HtmlTextInfo>> GetHtmlTextAsync(int ModuleId)
|
||||||
|
|
|
@ -11,17 +11,19 @@ namespace Oqtane.Services
|
||||||
public class AliasService : ServiceBase, IAliasService
|
public class AliasService : ServiceBase, IAliasService
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
|
private readonly SiteState sitestate;
|
||||||
private readonly IUriHelper urihelper;
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public AliasService(HttpClient http, IUriHelper urihelper)
|
public AliasService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
|
this.sitestate = sitestate;
|
||||||
this.urihelper = urihelper;
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(urihelper.GetAbsoluteUri(), "Alias"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Alias"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Alias>> GetAliasesAsync()
|
public async Task<List<Alias>> GetAliasesAsync()
|
||||||
|
|
12
Oqtane.Client/Services/IInstallationService.cs
Normal file
12
Oqtane.Client/Services/IInstallationService.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Oqtane.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public interface IInstallationService
|
||||||
|
{
|
||||||
|
Task<GenericResponse> IsInstalled();
|
||||||
|
Task<GenericResponse> Install(string connectionstring);
|
||||||
|
}
|
||||||
|
}
|
39
Oqtane.Client/Services/InstallationService.cs
Normal file
39
Oqtane.Client/Services/InstallationService.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using Oqtane.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public class InstallationService : ServiceBase, IInstallationService
|
||||||
|
{
|
||||||
|
private readonly HttpClient http;
|
||||||
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
|
public InstallationService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
|
{
|
||||||
|
this.http = http;
|
||||||
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string apiurl
|
||||||
|
{
|
||||||
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Installation"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GenericResponse> IsInstalled()
|
||||||
|
{
|
||||||
|
return await http.GetJsonAsync<GenericResponse>(apiurl + "/installed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GenericResponse> Install(string connectionstring)
|
||||||
|
{
|
||||||
|
return await http.PostJsonAsync<GenericResponse>(apiurl, connectionstring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,16 +14,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public ModuleDefinitionService(HttpClient http, SiteState sitestate)
|
public ModuleDefinitionService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "ModuleDefinition"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "ModuleDefinition"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync()
|
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync()
|
||||||
|
|
|
@ -12,16 +12,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public ModuleService(HttpClient http, SiteState sitestate)
|
public ModuleService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "Module"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Module"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Module>> GetModulesAsync(int PageId)
|
public async Task<List<Module>> GetModulesAsync(int PageId)
|
||||||
|
|
|
@ -12,16 +12,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public PageModuleService(HttpClient http, SiteState sitestate)
|
public PageModuleService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "PageModule"); }
|
get { return CreateApiUrl(sitestate.Alias, "PageModule", urihelper.GetAbsoluteUri()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<PageModule>> GetPageModulesAsync()
|
public async Task<List<PageModule>> GetPageModulesAsync()
|
||||||
|
|
|
@ -12,16 +12,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public PageService(HttpClient http, SiteState sitestate)
|
public PageService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "Page"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Page"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Page>> GetPagesAsync(int SiteId)
|
public async Task<List<Page>> GetPagesAsync(int SiteId)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
@ -6,22 +7,25 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class ServiceBase
|
public class ServiceBase
|
||||||
{
|
{
|
||||||
// method for alias agnostic api call
|
|
||||||
public string CreateApiUrl(string absoluteUri, string serviceName)
|
|
||||||
{
|
|
||||||
Uri uri = new Uri(absoluteUri);
|
|
||||||
string apiurl = uri.Scheme + "://" + uri.Authority + "/~/api/" + serviceName;
|
|
||||||
return apiurl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// method for alias specific api call
|
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
|
||||||
public string CreateApiUrl(Alias alias, string serviceName)
|
|
||||||
{
|
{
|
||||||
string apiurl = alias.Url + "/";
|
string apiurl = "";
|
||||||
|
if (alias != null)
|
||||||
|
{
|
||||||
|
// build a url which passes the alias that may include a subfolder for multi-tenancy
|
||||||
|
apiurl = alias.Url + "/";
|
||||||
if (alias.Path == "")
|
if (alias.Path == "")
|
||||||
{
|
{
|
||||||
apiurl += "~/";
|
apiurl += "~/";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// build a url which ignores any subfolder for multi-tenancy
|
||||||
|
Uri uri = new Uri(absoluteUri);
|
||||||
|
apiurl = uri.Scheme + "://" + uri.Authority + "/~/";
|
||||||
|
}
|
||||||
apiurl += "api/" + serviceName;
|
apiurl += "api/" + serviceName;
|
||||||
return apiurl;
|
return apiurl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public SiteService(HttpClient http, SiteState sitestate)
|
public SiteService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "Site"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Site"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Site>> GetSitesAsync()
|
public async Task<List<Site>> GetSitesAsync()
|
||||||
|
|
|
@ -12,16 +12,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public TenantService(HttpClient http, SiteState sitestate)
|
public TenantService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "Tenant"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Tenant"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Tenant>> GetTenantsAsync()
|
public async Task<List<Tenant>> GetTenantsAsync()
|
||||||
|
|
|
@ -14,16 +14,18 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
private readonly SiteState sitestate;
|
private readonly SiteState sitestate;
|
||||||
|
private readonly IUriHelper urihelper;
|
||||||
|
|
||||||
public ThemeService(HttpClient http, SiteState sitestate)
|
public ThemeService(HttpClient http, SiteState sitestate, IUriHelper urihelper)
|
||||||
{
|
{
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.sitestate = sitestate;
|
this.sitestate = sitestate;
|
||||||
|
this.urihelper = urihelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "Theme"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Theme"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Theme>> GetThemesAsync()
|
public async Task<List<Theme>> GetThemesAsync()
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Oqtane.Services
|
||||||
|
|
||||||
private string apiurl
|
private string apiurl
|
||||||
{
|
{
|
||||||
get { return CreateApiUrl(sitestate.Alias, "User"); }
|
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "User"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<User>> GetUsersAsync()
|
public async Task<List<User>> GetUsersAsync()
|
||||||
|
|
187
Oqtane.Client/Shared/Installer.razor
Normal file
187
Oqtane.Client/Shared/Installer.razor
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
@using Oqtane.Services
|
||||||
|
@using Oqtane.Models
|
||||||
|
@inject IUriHelper UriHelper
|
||||||
|
@inject IInstallationService InstallationService
|
||||||
|
@inject IUserService UserService
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
<img src="oqtane.png" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
|
||||||
|
<h2 class="text-center">Database Configuration</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
<table class="form-group" cellpadding="4" cellspacing="4">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Database Type: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select class="custom-select" @bind="@DatabaseType">
|
||||||
|
<option value="LocalDB">Local Database</option>
|
||||||
|
<option value="SQLServer">SQL Server</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Server: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="ServerName" class="form-control" @bind="@ServerName" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Database: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="DatabaseName" class="form-control" @bind="@DatabaseName" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Integrated Security: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select class="custom-select" @onchange="@SetIntegratedSecurity">
|
||||||
|
<option value="true" selected>True</option>
|
||||||
|
<option value="false">False</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="@IntegratedSecurityDisplay">
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Username: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="Username" class="form-control" @bind="@Username" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="@IntegratedSecurityDisplay">
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Password: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" id="Password" class="form-control" @bind="@Password" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
|
||||||
|
<h2 class="text-center">Application Administrator</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
<table class="form-group" cellpadding="4" cellspacing="4">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Username: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="Email" class="form-control" @bind="@HostUsername" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Title" class="control-label" style="font-weight: bold">Password: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" id="Email" class="form-control" @bind="@HostPassword" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
<button class="btn btn-success" @onclick="@Install">Install Now</button><br /><br />
|
||||||
|
@((MarkupString)@Message)
|
||||||
|
</div>
|
||||||
|
<div class="loading" style="@LoadingDisplay"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
private string DatabaseType = "LocalDB";
|
||||||
|
private string ServerName = "(LocalDb)\\MSSQLLocalDB";
|
||||||
|
private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm");
|
||||||
|
private bool IntegratedSecurity = true;
|
||||||
|
private string Username = "";
|
||||||
|
private string Password = "";
|
||||||
|
private string HostUsername = "host";
|
||||||
|
private string HostPassword = "";
|
||||||
|
private string Message = "";
|
||||||
|
|
||||||
|
private string IntegratedSecurityDisplay = "display:none;";
|
||||||
|
private string LoadingDisplay = "display:none;";
|
||||||
|
|
||||||
|
private void SetIntegratedSecurity(UIChangeEventArgs e)
|
||||||
|
{
|
||||||
|
if (Convert.ToBoolean(e.Value))
|
||||||
|
{
|
||||||
|
IntegratedSecurityDisplay = "display:none;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IntegratedSecurityDisplay = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Install()
|
||||||
|
{
|
||||||
|
if (HostPassword.Length >= 6)
|
||||||
|
{
|
||||||
|
LoadingDisplay = "";
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
string connectionstring = "";
|
||||||
|
if (DatabaseType == "LocalDB")
|
||||||
|
{
|
||||||
|
connectionstring = "Data Source=" + ServerName + ";AttachDbFilename=|DataDirectory|\\" + DatabaseName + ".mdf;Initial Catalog=" + DatabaseName + ";Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionstring = "Data Source=" + ServerName + ";Initial Catalog=" + DatabaseName + ";";
|
||||||
|
if (IntegratedSecurityDisplay == "display:none;")
|
||||||
|
{
|
||||||
|
connectionstring += "Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionstring += "User ID=" + Username + ";Password=" + Password;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GenericResponse response = await InstallationService.Install(connectionstring);
|
||||||
|
if (response.Success)
|
||||||
|
{
|
||||||
|
User user = new User();
|
||||||
|
user.Username = HostUsername;
|
||||||
|
user.DisplayName = HostUsername;
|
||||||
|
user.Password = HostPassword;
|
||||||
|
user.IsSuperUser = true;
|
||||||
|
user.Roles = "";
|
||||||
|
await UserService.AddUserAsync(user);
|
||||||
|
UriHelper.NavigateTo("", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Message = "<div class=\"alert alert-danger\" role=\"alert\">" + response.Message + "</div>";
|
||||||
|
LoadingDisplay = "display:none;";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Message = "<div class=\"alert alert-danger\" role=\"alert\">Password Must Be 6 Characters Or Greater</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ namespace Oqtane.Client
|
||||||
|
|
||||||
// register scoped core services
|
// register scoped core services
|
||||||
services.AddScoped<SiteState>();
|
services.AddScoped<SiteState>();
|
||||||
|
services.AddScoped<IInstallationService, InstallationService>();
|
||||||
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
||||||
services.AddScoped<IThemeService, ThemeService>();
|
services.AddScoped<IThemeService, ThemeService>();
|
||||||
services.AddScoped<IAliasService, AliasService>();
|
services.AddScoped<IAliasService, AliasService>();
|
||||||
|
|
|
@ -246,3 +246,13 @@ app {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
background: rgba(0,0,0,0.2) url('../loading.gif') no-repeat 50% 50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
|
@ -20,6 +20,14 @@ window.interop = {
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
|
getElementByName: function (name) {
|
||||||
|
var elements = document.getElementsByName(name);
|
||||||
|
if (elements.length) {
|
||||||
|
return elements[0].value;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
addCSS: function (fileName) {
|
addCSS: function (fileName) {
|
||||||
var head = document.head;
|
var head = document.head;
|
||||||
var link = document.createElement("link");
|
var link = document.createElement("link");
|
||||||
|
|
BIN
Oqtane.Client/wwwroot/loading.gif
Normal file
BIN
Oqtane.Client/wwwroot/loading.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
192
Oqtane.Server/Controllers/InstallationController.cs
Normal file
192
Oqtane.Server/Controllers/InstallationController.cs
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
using DbUp;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using System;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Oqtane.Controllers
|
||||||
|
{
|
||||||
|
[Route("{site}/api/[controller]")]
|
||||||
|
public class InstallationController : Controller
|
||||||
|
{
|
||||||
|
private readonly IConfigurationRoot _config;
|
||||||
|
|
||||||
|
public InstallationController(IConfigurationRoot config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST api/<controller>
|
||||||
|
[HttpPost]
|
||||||
|
public GenericResponse Post([FromBody] string connectionString)
|
||||||
|
{
|
||||||
|
var response = new GenericResponse { Success = false, Message = "" };
|
||||||
|
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
bool exists = IsInstalled().Success;
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
string datadirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
|
||||||
|
connectionString = connectionString.Replace("|DataDirectory|", datadirectory);
|
||||||
|
|
||||||
|
SqlConnection connection = new SqlConnection(connectionString);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (connection)
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
}
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// database does not exist
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to create database if it does not exist
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
string masterConnectionString = "";
|
||||||
|
string databaseName = "";
|
||||||
|
string[] fragments = connectionString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
foreach (string fragment in fragments)
|
||||||
|
{
|
||||||
|
if (fragment.ToLower().Contains("initial catalog=") || fragment.ToLower().Contains("database="))
|
||||||
|
{
|
||||||
|
databaseName = fragment.Substring(fragment.IndexOf("=") + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!fragment.ToLower().Contains("attachdbfilename="))
|
||||||
|
{
|
||||||
|
masterConnectionString += fragment + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection = new SqlConnection(masterConnectionString);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (connection)
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
SqlCommand command;
|
||||||
|
if (connectionString.ToLower().Contains("attachdbfilename=")) // LocalDB
|
||||||
|
{
|
||||||
|
command = new SqlCommand("CREATE DATABASE [" + databaseName + "] ON ( NAME = '" + databaseName + "', FILENAME = '" + datadirectory + "\\" + databaseName + ".mdf')", connection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command = new SqlCommand("CREATE DATABASE [" + databaseName + "]", connection);
|
||||||
|
}
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
response.Message = "Can Not Create Database - " + ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sleep to allow SQL server to attach new database
|
||||||
|
Thread.Sleep(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
// get master initialization script and update connectionstring and alias in seed data
|
||||||
|
string initializationScript = "";
|
||||||
|
using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\Scripts\\Master.sql"))
|
||||||
|
{
|
||||||
|
initializationScript = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
initializationScript = initializationScript.Replace("{ConnectionString}", connectionString);
|
||||||
|
initializationScript = initializationScript.Replace("{Alias}", HttpContext.Request.Host.Value);
|
||||||
|
|
||||||
|
var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionString)
|
||||||
|
.WithScript(new DbUp.Engine.SqlScript("Master.sql", initializationScript))
|
||||||
|
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()); // tenant scripts should be added to /Scripts folder as Embedded Resources
|
||||||
|
var dbUpgrade = dbUpgradeConfig.Build();
|
||||||
|
if (dbUpgrade.IsUpgradeRequired())
|
||||||
|
{
|
||||||
|
var result = dbUpgrade.PerformUpgrade();
|
||||||
|
if (!result.Successful)
|
||||||
|
{
|
||||||
|
response.Message = result.Error.Message;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update appsettings
|
||||||
|
string config = "";
|
||||||
|
using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\appsettings.json"))
|
||||||
|
{
|
||||||
|
config = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
connectionString = connectionString.Replace(datadirectory, "|DataDirectory|");
|
||||||
|
connectionString = connectionString.Replace(@"\", @"\\");
|
||||||
|
config = config.Replace("DefaultConnection\": \"", "DefaultConnection\": \"" + connectionString);
|
||||||
|
using (StreamWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + "\\appsettings.json"))
|
||||||
|
{
|
||||||
|
writer.WriteLine(config);
|
||||||
|
}
|
||||||
|
_config.Reload();
|
||||||
|
response.Success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.Message = "Application Is Already Installed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/installed
|
||||||
|
[HttpGet("installed")]
|
||||||
|
public GenericResponse IsInstalled()
|
||||||
|
{
|
||||||
|
var response = new GenericResponse { Success = false, Message = "" };
|
||||||
|
|
||||||
|
string datadirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
|
||||||
|
string connectionString = _config.GetConnectionString("DefaultConnection");
|
||||||
|
connectionString = connectionString.Replace("|DataDirectory|", datadirectory);
|
||||||
|
|
||||||
|
SqlConnection connection = new SqlConnection(connectionString);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (connection)
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
}
|
||||||
|
response.Success = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// database does not exist
|
||||||
|
response.Message = "Database Does Not Exist";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Success)
|
||||||
|
{
|
||||||
|
var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionString)
|
||||||
|
.WithScript(new DbUp.Engine.SqlScript("Master.sql", ""));
|
||||||
|
var dbUpgrade = dbUpgradeConfig.Build();
|
||||||
|
response.Success = !dbUpgrade.IsUpgradeRequired();
|
||||||
|
if (!response.Success)
|
||||||
|
{
|
||||||
|
response.Message = "Scripts Have Not Been Run";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,20 +86,9 @@ namespace Oqtane.Controllers
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
public async Task<User> Login([FromBody] User user)
|
public async Task<User> Login([FromBody] User user)
|
||||||
{
|
{
|
||||||
// TODO: seed host user - this logic should be moved to installation
|
|
||||||
IdentityUser identityuser = await identityUserManager.FindByNameAsync("host");
|
|
||||||
if (identityuser == null)
|
|
||||||
{
|
|
||||||
var result = await identityUserManager.CreateAsync(new IdentityUser { UserName = "host", Email = "host" }, "password");
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
users.AddUser(new Models.User { Username = "host", DisplayName = "host", IsSuperUser = true, Roles = "" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
identityuser = await identityUserManager.FindByNameAsync(user.Username);
|
IdentityUser identityuser = await identityUserManager.FindByNameAsync(user.Username);
|
||||||
if (identityuser != null)
|
if (identityuser != null)
|
||||||
{
|
{
|
||||||
var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, false);
|
var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, false);
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using System.Reflection;
|
|
||||||
using DbUp;
|
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.Threading;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace Oqtane.Filters
|
|
||||||
{
|
|
||||||
public class UpgradeFilter : IStartupFilter
|
|
||||||
{
|
|
||||||
private readonly IConfiguration _config;
|
|
||||||
|
|
||||||
public UpgradeFilter(IConfiguration config)
|
|
||||||
{
|
|
||||||
_config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
|
|
||||||
{
|
|
||||||
string datadirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
|
|
||||||
string connectionString = _config.GetConnectionString("DefaultConnection");
|
|
||||||
connectionString = connectionString.Replace("|DataDirectory|", datadirectory);
|
|
||||||
|
|
||||||
// check if database exists
|
|
||||||
SqlConnection connection = new SqlConnection(connectionString);
|
|
||||||
bool databaseExists;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (connection)
|
|
||||||
{
|
|
||||||
connection.Open();
|
|
||||||
}
|
|
||||||
databaseExists = true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
databaseExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create database if it does not exist
|
|
||||||
if (!databaseExists)
|
|
||||||
{
|
|
||||||
string masterConnectionString = "";
|
|
||||||
string databaseName = "";
|
|
||||||
string[] fragments = connectionString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
foreach(string fragment in fragments)
|
|
||||||
{
|
|
||||||
if (fragment.ToLower().Contains("initial catalog=") || fragment.ToLower().Contains("database="))
|
|
||||||
{
|
|
||||||
databaseName = fragment.Substring(fragment.IndexOf("=") + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!fragment.ToLower().Contains("attachdbfilename="))
|
|
||||||
{
|
|
||||||
masterConnectionString += fragment + ";";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connection = new SqlConnection(masterConnectionString);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (connection)
|
|
||||||
{
|
|
||||||
connection.Open();
|
|
||||||
SqlCommand command;
|
|
||||||
if (connectionString.ToLower().Contains("attachdbfilename=")) // LocalDB
|
|
||||||
{
|
|
||||||
command = new SqlCommand("CREATE DATABASE [" + databaseName + "] ON ( NAME = '" + databaseName + "', FILENAME = '" + datadirectory + "\\" + databaseName + ".mdf')", connection);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command = new SqlCommand("CREATE DATABASE [" + databaseName + "]", connection);
|
|
||||||
}
|
|
||||||
command.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sleep to allow SQL server to attach new database
|
|
||||||
Thread.Sleep(5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get master initialization script and update connectionstring in seed data
|
|
||||||
string initializationScript = "";
|
|
||||||
using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\Scripts\\Master.sql"))
|
|
||||||
{
|
|
||||||
initializationScript = reader.ReadToEnd();
|
|
||||||
}
|
|
||||||
initializationScript = initializationScript.Replace("{ConnectionString}", connectionString);
|
|
||||||
|
|
||||||
// handle upgrade scripts
|
|
||||||
var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionString)
|
|
||||||
.WithScript(new DbUp.Engine.SqlScript("Master.sql", initializationScript))
|
|
||||||
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()); // upgrade scripts should be added to /Scripts folder as Embedded Resources
|
|
||||||
var dbUpgrade = dbUpgradeConfig.Build();
|
|
||||||
if (dbUpgrade.IsUpgradeRequired())
|
|
||||||
{
|
|
||||||
var result = dbUpgrade.PerformUpgrade();
|
|
||||||
if (!result.Successful)
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,8 @@
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.AspNetCore.Blazor.Hosting;
|
using Microsoft.AspNetCore.Blazor.Hosting;
|
||||||
using Microsoft.AspNetCore;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using System.IO;
|
using Microsoft.AspNetCore;
|
||||||
using System.Text;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Oqtane.Server
|
namespace Oqtane.Server
|
||||||
{
|
{
|
||||||
|
@ -14,7 +11,6 @@ namespace Oqtane.Server
|
||||||
#if DEBUG || RELEASE
|
#if DEBUG || RELEASE
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
PrepareConfiguration();
|
|
||||||
CreateHostBuilder(args).Build().Run();
|
CreateHostBuilder(args).Build().Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +25,6 @@ namespace Oqtane.Server
|
||||||
#if WASM
|
#if WASM
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
PrepareConfiguration();
|
|
||||||
BuildWebHost(args).Run();
|
BuildWebHost(args).Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,24 +37,5 @@ namespace Oqtane.Server
|
||||||
.Build();
|
.Build();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static void PrepareConfiguration()
|
|
||||||
{
|
|
||||||
string config = "";
|
|
||||||
using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\appsettings.json"))
|
|
||||||
{
|
|
||||||
config = reader.ReadToEnd();
|
|
||||||
}
|
|
||||||
// if using LocalDB create a unique database name
|
|
||||||
if (config.Contains("AttachDbFilename=|DataDirectory|\\\\Oqtane.mdf"))
|
|
||||||
{
|
|
||||||
string timestamp = DateTime.Now.ToString("yyyyMMddHHmm");
|
|
||||||
config = config.Replace("Initial Catalog=Oqtane", "Initial Catalog=Oqtane-" + timestamp)
|
|
||||||
.Replace("AttachDbFilename=|DataDirectory|\\\\Oqtane.mdf", "AttachDbFilename=|DataDirectory|\\\\Oqtane-" + timestamp + ".mdf");
|
|
||||||
using (StreamWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + "\\appsettings.json"))
|
|
||||||
{
|
|
||||||
writer.WriteLine(config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class AliasRepository : IAliasRepository
|
public class AliasRepository : IAliasRepository
|
||||||
{
|
{
|
||||||
private HostContext db;
|
private MasterContext db;
|
||||||
private readonly IMemoryCache _cache;
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
public AliasRepository(HostContext context, IMemoryCache cache)
|
public AliasRepository(MasterContext context, IMemoryCache cache)
|
||||||
{
|
{
|
||||||
db = context;
|
db = context;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
|
|
@ -3,9 +3,9 @@ using Oqtane.Models;
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class HostContext : DbContext
|
public class MasterContext : DbContext
|
||||||
{
|
{
|
||||||
public HostContext(DbContextOptions<HostContext> options) : base(options) { }
|
public MasterContext(DbContextOptions<MasterContext> options) : base(options) { }
|
||||||
|
|
||||||
public virtual DbSet<Alias> Alias { get; set; }
|
public virtual DbSet<Alias> Alias { get; set; }
|
||||||
public virtual DbSet<Tenant> Tenant { get; set; }
|
public virtual DbSet<Tenant> Tenant { get; set; }
|
|
@ -10,10 +10,10 @@ namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class TenantRepository : ITenantRepository
|
public class TenantRepository : ITenantRepository
|
||||||
{
|
{
|
||||||
private HostContext db;
|
private MasterContext db;
|
||||||
private readonly IMemoryCache _cache;
|
private readonly IMemoryCache _cache;
|
||||||
|
|
||||||
public TenantRepository(HostContext context, IMemoryCache cache)
|
public TenantRepository(MasterContext context, IMemoryCache cache)
|
||||||
{
|
{
|
||||||
db = context;
|
db = context;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class TenantResolver : ITenantResolver
|
public class TenantResolver : ITenantResolver
|
||||||
{
|
{
|
||||||
private HostContext db;
|
private MasterContext db;
|
||||||
private readonly string aliasname;
|
private readonly string aliasname;
|
||||||
private readonly IAliasRepository _aliasrepository;
|
private readonly IAliasRepository _aliasrepository;
|
||||||
private readonly ITenantRepository _tenantrepository;
|
private readonly ITenantRepository _tenantrepository;
|
||||||
|
|
||||||
public TenantResolver(HostContext context, IHttpContextAccessor accessor, IAliasRepository aliasrepository, ITenantRepository tenantrepository)
|
public TenantResolver(MasterContext context, IHttpContextAccessor accessor, IAliasRepository aliasrepository, ITenantRepository tenantrepository)
|
||||||
{
|
{
|
||||||
db = context;
|
db = context;
|
||||||
_aliasrepository = aliasrepository;
|
_aliasrepository = aliasrepository;
|
||||||
|
|
|
@ -54,10 +54,10 @@ GO
|
||||||
SET IDENTITY_INSERT [dbo].[Alias] ON
|
SET IDENTITY_INSERT [dbo].[Alias] ON
|
||||||
GO
|
GO
|
||||||
INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId])
|
INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId])
|
||||||
VALUES (1, N'localhost:44357', 1, 1)
|
VALUES (1, N'{Alias}', 1, 1)
|
||||||
GO
|
GO
|
||||||
INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId])
|
INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId])
|
||||||
VALUES (2, N'localhost:44357/site2', 1, 2)
|
VALUES (2, N'{Alias}/site2', 1, 2)
|
||||||
GO
|
GO
|
||||||
SET IDENTITY_INSERT [dbo].[Alias] OFF
|
SET IDENTITY_INSERT [dbo].[Alias] OFF
|
||||||
GO
|
GO
|
||||||
|
|
|
@ -11,7 +11,6 @@ using System.Reflection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Filters;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
|
@ -25,7 +24,7 @@ namespace Oqtane.Server
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public IConfiguration Configuration { get; }
|
public IConfigurationRoot Configuration { get; }
|
||||||
public Startup(IWebHostEnvironment env)
|
public Startup(IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
var builder = new ConfigurationBuilder()
|
var builder = new ConfigurationBuilder()
|
||||||
|
@ -68,6 +67,7 @@ namespace Oqtane.Server
|
||||||
|
|
||||||
// register scoped core services
|
// register scoped core services
|
||||||
services.AddScoped<SiteState>();
|
services.AddScoped<SiteState>();
|
||||||
|
services.AddScoped<IInstallationService, InstallationService>();
|
||||||
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
||||||
services.AddScoped<IThemeService, ThemeService>();
|
services.AddScoped<IThemeService, ThemeService>();
|
||||||
services.AddScoped<IAliasService, AliasService>();
|
services.AddScoped<IAliasService, AliasService>();
|
||||||
|
@ -101,7 +101,7 @@ namespace Oqtane.Server
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
services.AddDbContext<HostContext>(options =>
|
services.AddDbContext<MasterContext>(options =>
|
||||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")
|
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")
|
||||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString())
|
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString())
|
||||||
));
|
));
|
||||||
|
@ -143,10 +143,8 @@ namespace Oqtane.Server
|
||||||
|
|
||||||
services.AddMvc().AddNewtonsoftJson();
|
services.AddMvc().AddNewtonsoftJson();
|
||||||
|
|
||||||
// register database install/upgrade filter
|
|
||||||
services.AddTransient<IStartupFilter, UpgradeFilter>();
|
|
||||||
|
|
||||||
// register singleton scoped core services
|
// register singleton scoped core services
|
||||||
|
services.AddSingleton<IConfigurationRoot>(Configuration);
|
||||||
services.AddSingleton<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
services.AddSingleton<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
||||||
services.AddSingleton<IThemeRepository, ThemeRepository>();
|
services.AddSingleton<IThemeRepository, ThemeRepository>();
|
||||||
|
|
||||||
|
@ -237,7 +235,7 @@ namespace Oqtane.Server
|
||||||
{
|
{
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
services.AddDbContext<HostContext>(options =>
|
services.AddDbContext<MasterContext>(options =>
|
||||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")
|
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")
|
||||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString())
|
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString())
|
||||||
));
|
));
|
||||||
|
@ -279,10 +277,8 @@ namespace Oqtane.Server
|
||||||
|
|
||||||
services.AddMvc().AddNewtonsoftJson();
|
services.AddMvc().AddNewtonsoftJson();
|
||||||
|
|
||||||
// register database install/upgrade filter
|
|
||||||
services.AddTransient<IStartupFilter, UpgradeFilter>();
|
|
||||||
|
|
||||||
// register singleton scoped core services
|
// register singleton scoped core services
|
||||||
|
services.AddSingleton<IConfigurationRoot>(Configuration);
|
||||||
services.AddSingleton<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
services.AddSingleton<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
||||||
services.AddSingleton<IThemeRepository, ThemeRepository>();
|
services.AddSingleton<IThemeRepository, ThemeRepository>();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Data Source=(LocalDb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\Oqtane.mdf;Initial Catalog=Oqtane;Integrated Security=SSPI;"
|
"DefaultConnection": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -246,3 +246,13 @@ app {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
background: rgba(0,0,0,0.2) url('../loading.gif') no-repeat 50% 50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
BIN
Oqtane.Server/wwwroot/loading.gif
Normal file
BIN
Oqtane.Server/wwwroot/loading.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
8
Oqtane.Shared/Models/GenericResponse.cs
Normal file
8
Oqtane.Shared/Models/GenericResponse.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class GenericResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user