oqtane.framework/Oqtane.Client/Installer/Installer.razor
2025-01-17 12:50:26 -05:00

341 lines
13 KiB
Plaintext

@namespace Oqtane.Installer
@using Oqtane.Interfaces
@inject NavigationManager NavigationManager
@inject IInstallationService InstallationService
@inject ISiteService SiteService
@inject IUserService UserService
@inject IDatabaseService DatabaseService
@inject ISiteTemplateService SiteTemplateService
@inject IJSRuntime JSRuntime
@inject IStringLocalizer<Installer> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject SiteState SiteState
<div class="container">
<div class="row">
<div class="mx-auto text-center">
<img src="oqtane-black.png" />
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET 9)</div>
</div>
</div>
<hr class="app-rule" />
<div class="row justify-content-center">
<div class="col text-center">
<h2>@Localizer["DatabaseConfig"]</h2><br />
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="databasetype" HelpText="Select the type of database you wish to use" ResourceKey="DatabaseType">Database:</Label>
<div class="col-sm-9">
@if (_databases != null)
{
<div class="input-group">
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
@foreach (var database in _databases)
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
</select>
@if (!_showConnectionString)
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
}
else
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
}
</div>
}
</div>
</div>
@if (!_showConnectionString)
{
if (_databaseConfigType != null)
{
@DatabaseConfigComponent
}
}
else
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="connectionstring" HelpText="Enter a complete connection string including all parameters and delimiters" ResourceKey="ConnectionString">Settings:</Label>
<div class="col-sm-9">
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
</div>
</div>
}
</div>
</div>
<div class="col text-center">
<h2>@Localizer["ApplicationAdmin"]</h2><br />
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="username" HelpText="Provide a username for the primary user account" ResourceKey="Username">Username:</Label>
<div class="col-sm-9">
<input id="username" type="text" class="form-control" maxlength="256" @bind="@_hostUsername" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="password" HelpText="Provide a password for the primary user account" ResourceKey="Password">Password:</Label>
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordType" class="form-control" maxlength="256" @bind="@_hostPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglePassword</button>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_confirmPasswordType" class="form-control" maxlength="256" @bind="@_confirmPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword" tabindex="-1">@_toggleConfirmPassword</button>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="email" HelpText="Provide the email address for the host user account" ResourceKey="Email">Email:</Label>
<div class="col-sm-9">
<input type="text" class="form-control" maxlength="256" @bind="@_hostEmail" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Provide the full name of the host user" ResourceKey="Name">Full Name:</Label>
<div class="col-sm-9">
<input type="text" class="form-control" maxlength="50" @bind="@_hostName" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="template" HelpText="Select a site template" ResourceKey="Template">Template:</Label>
<div class="col-sm-9">
@if (_templates != null)
{
<select id="template" class="form-select" @bind="@_template" required>
@foreach (var template in _templates)
{
<option value="@template.TypeName">@template.Name</option>
}
</select>
}
</div>
</div>
</div>
</div>
</div>
<hr class="app-rule" />
<div class="row">
<div class="mx-auto text-center">
<button type="button" class="btn btn-success" @onclick="Install">@Localizer["InstallNow"]</button><br /><br />
@if (!string.IsNullOrEmpty(_message))
{
<div class="alert alert-danger alert-dismissible fade show mb-3" role="alert">
@((MarkupString)_message)
<button type="button" class="btn-close" aria-label="Close" @onclick="DismissModal"></button>
</div>
}
</div>
<div class="app-progress-indicator" style="@_loadingDisplay"></div>
</div>
<div class="row">
<div class="mx-auto text-center">
<input type="checkbox" @bind="@_register" /> @Localizer["Register"]
</div>
</div>
</div>
@code {
private List<Database> _databases;
private string _databaseName;
private Type _databaseConfigType;
private object _databaseConfig;
private RenderFragment DatabaseConfigComponent { get; set; }
private bool _showConnectionString = false;
private string _connectionString = string.Empty;
private string _hostUsername = string.Empty;
private string _hostPassword = string.Empty;
private string _passwordType = "password";
private string _confirmPasswordType = "password";
private string _togglePassword = string.Empty;
private string _toggleConfirmPassword = string.Empty;
private string _confirmPassword = string.Empty;
private string _hostEmail = string.Empty;
private string _hostName = string.Empty;
private List<SiteTemplate> _templates;
private string _template = Constants.DefaultSiteTemplate;
private bool _register = true;
private string _message = string.Empty;
private string _loadingDisplay = "display: none;";
protected override async Task OnInitializedAsync()
{
// include CSS
var content = $"<link rel=\"stylesheet\" href=\"{Constants.BootstrapStylesheetUrl}\" integrity=\"{Constants.BootstrapStylesheetIntegrity}\" crossorigin=\"anonymous\" type=\"text/css\"/>";
SiteState.AppendHeadContent(content);
_togglePassword = SharedLocalizer["ShowPassword"];
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
_databases = await DatabaseService.GetDatabasesAsync();
if (_databases.Exists(item => item.IsDefault))
{
_databaseName = _databases.Find(item => item.IsDefault).Name;
}
else
{
_databaseName = "LocalDB";
}
LoadDatabaseConfigComponent();
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
}
private void DatabaseChanged(ChangeEventArgs eventArgs)
{
try
{
_databaseName = (string)eventArgs.Value;
_showConnectionString = false;
LoadDatabaseConfigComponent();
}
catch
{
_message = Localizer["Error.DbConfig.Load"];
}
}
private void LoadDatabaseConfigComponent()
{
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
if (database != null)
{
_databaseConfigType = Type.GetType(database.ControlType);
DatabaseConfigComponent = builder =>
{
builder.OpenComponent(0, _databaseConfigType);
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
builder.CloseComponent();
};
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// include JavaScript
var interop = new Interop(JSRuntime);
await interop.IncludeScript("", Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous", "", "head");
}
}
private async Task Install()
{
var connectionString = String.Empty;
if (_showConnectionString)
{
connectionString = _connectionString;
}
else
{
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
{
connectionString = databaseConfigControl.GetConnectionString();
}
}
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@") && !string.IsNullOrEmpty(_hostName))
{
var result = await UserService.ValidateUserAsync(_hostUsername, _hostEmail, _hostPassword);
if (result.Succeeded)
{
_loadingDisplay = "";
StateHasChanged();
Uri uri = new Uri(NavigationManager.Uri);
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
var config = new InstallConfig
{
DatabaseType = database.DBType,
ConnectionString = connectionString,
Aliases = uri.Authority,
HostUsername = _hostUsername,
HostPassword = _hostPassword,
HostEmail = _hostEmail,
HostName = _hostName,
TenantName = TenantNames.Master,
IsNewTenant = true,
SiteName = Constants.DefaultSite,
Register = _register,
SiteTemplate = _template,
RenderMode = RenderModes.Static,
Runtime = Runtimes.Server
};
var installation = await InstallationService.Install(config);
if (installation.Success)
{
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
}
else
{
_message = installation.Message;
_loadingDisplay = "display: none;";
}
}
else
{
_message = string.Join("<br />", result.Errors.Select(i => !string.IsNullOrEmpty(i.Value) ? i.Value : Localizer[i.Key]));
}
}
else
{
_message = Localizer["Message.Require.DbInfo"];
}
}
private void TogglePassword()
{
if (_passwordType == "password")
{
_passwordType = "text";
_togglePassword = SharedLocalizer["HidePassword"];
}
else
{
_passwordType = "password";
_togglePassword = SharedLocalizer["ShowPassword"];
}
}
private void ToggleConfirmPassword()
{
if (_confirmPasswordType == "password")
{
_confirmPasswordType = "text";
_toggleConfirmPassword = SharedLocalizer["HidePassword"];
}
else
{
_confirmPasswordType = "password";
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
}
}
private void ToggleConnectionString()
{
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
{
_connectionString = databaseConfigControl.GetConnectionString();
}
_showConnectionString = !_showConnectionString;
}
private void DismissModal()
{
_message = "";
StateHasChanged();
}
}