Merge pull request #1682 from gjwalk/dev

Sites Validation
This commit is contained in:
Shaun Walker 2021-09-23 17:12:36 -04:00 committed by GitHub
commit f220cb52bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -19,136 +19,140 @@
} }
else else
{ {
<div class="container"> <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="row mb-1 align-items-center"> <div class="container">
<Label Class="col-sm-3" For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="alias" HelpText="Enter the aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they can be separated by commas." ResourceKey="Aliases">Aliases: </Label>
<div class="col-sm-9">
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
<div class="col-sm-9">
<select id="defaultTheme" class="form-select" @onchange="(e => ThemeChanged(e))">
<option value="-">&lt;@Localizer["Theme.Select"]&gt;</option>
@foreach (var theme in _themes)
{
<option value="@theme.TypeName">@theme.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
<div class="col-sm-9">
<select id="defaultContainer" class="form-select" @bind="@_containertype">
<option value="-">&lt;@Localizer["Container.Select"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
<div class="col-sm-9">
<select id="adminContainer" class="form-select" @bind="@_admincontainertype">
<option value="-">&lt;@Localizer["Container.Select"]&gt;</option>
<option value="">&lt;@Localizer["DefaultContainer.Admin"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
<div class="col-sm-9">
<select id="siteTemplate" class="form-select" @bind="@_sitetemplatetype">
<option value="-">&lt;@Localizer["SiteTemplate.Select"]&gt;</option>
@foreach (SiteTemplate siteTemplate in _siteTemplates)
{
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
<div class="col-sm-9">
<select id="tenant" class="form-select" @onchange="(e => TenantChanged(e))">
<option value="-">&lt;@Localizer["Tenant.Select"]&gt;</option>
<option value="+">&lt;@Localizer["Tenant.Add"]&gt;</option>
@foreach (Tenant tenant in _tenants)
{
<option value="@tenant.TenantId">@tenant.Name</option>
}
</select>
</div>
</div>
@if (_tenantid == "+")
{
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<hr class="app-rule" /> <Label Class="col-sm-3" For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="name" class="form-control" @bind="@_tenantName" /> <input id="name" class="form-control" @bind="@_name" maxlength="200" required />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label> <Label Class="col-sm-3" For="alias" HelpText="Enter the aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they can be separated by commas." ResourceKey="Aliases">Aliases: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))"> <textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
@foreach (var database in _databases) </div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
<div class="col-sm-9">
<select id="defaultTheme" class="form-select" @onchange="(e => ThemeChanged(e))" required>
<option value="-">&lt;@Localizer["Theme.Select"]&gt;</option>
@foreach (var theme in _themes)
{ {
if (database.IsDefault) <option value="@theme.TypeName">@theme.Name</option>
{
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
}
else
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
} }
</select> </select>
</div> </div>
</div> </div>
if (_databaseConfigType != null) <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
<div class="col-sm-9">
<select id="defaultContainer" class="form-select" @bind="@_containertype" required>
<option value="-">&lt;@Localizer["Container.Select"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
<div class="col-sm-9">
<select id="adminContainer" class="form-select" @bind="@_admincontainertype" required>
<option value="-">&lt;@Localizer["Container.Select"]&gt;</option>
<option value="">&lt;@Localizer["DefaultContainer.Admin"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
<div class="col-sm-9">
<select id="siteTemplate" class="form-select" @bind="@_sitetemplatetype" required>
<option value="-">&lt;@Localizer["SiteTemplate.Select"]&gt;</option>
@foreach (SiteTemplate siteTemplate in _siteTemplates)
{
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
<div class="col-sm-9">
<select id="tenant" class="form-select" @onchange="(e => TenantChanged(e))" required>
<option value="-">&lt;@Localizer["Tenant.Select"]&gt;</option>
<option value="+">&lt;@Localizer["Tenant.Add"]&gt;</option>
@foreach (Tenant tenant in _tenants)
{
<option value="@tenant.TenantId">@tenant.Name</option>
}
</select>
</div>
</div>
@if (_tenantid == "+")
{ {
@DatabaseConfigComponent; <div class="row mb-1 align-items-center">
<hr class="app-rule" />
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_tenantName" maxlength="100" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
<div class="col-sm-9">
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
@foreach (var database in _databases)
{
if (database.IsDefault)
{
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
}
else
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
}
</select>
</div>
</div>
if (_databaseConfigType != null)
{
@DatabaseConfigComponent;
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
<div class="col-sm-9">
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
<div class="col-sm-9">
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" required />
</div>
</div>
} }
<div class="row mb-1 align-items-center"> </div>
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter a valid host username" ResourceKey="HostUsername">Host Username:</Label> <br />
<div class="col-sm-9"> <br />
<input id="hostUsername" class="form-control" @bind="@_hostusername" /> <button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
</div> <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
</div> </form>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="hostPassword" HelpText="Enter a valid host password" ResourceKey="HostPassword">Host Password:</Label>
<div class="col-sm-9">
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" />
</div>
</div>
}
</div>
<br />
<br />
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
} }
@code { @code {
private List<Database> _databases; private List<Database> _databases;
private ElementReference form;
private bool validated = false;
private string _databaseName = "LocalDB"; private string _databaseName = "LocalDB";
private Type _databaseConfigType; private Type _databaseConfigType;
private object _databaseConfig; private object _databaseConfig;
@ -164,7 +168,7 @@ else
private string _tenantName = string.Empty; private string _tenantName = string.Empty;
private string _hostusername = string.Empty; private string _hostUserName = UserNames.Host;
private string _hostpassword = string.Empty; private string _hostpassword = string.Empty;
private string _name = string.Empty; private string _name = string.Empty;
@ -252,112 +256,120 @@ else
private async Task SaveSite() private async Task SaveSite()
{ {
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-") validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{ {
var duplicates = new List<string>(); if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
var aliases = await AliasService.GetAliasesAsync();
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{ {
if (aliases.Exists(item => item.Name == name)) var duplicates = new List<string>();
var aliases = await AliasService.GetAliasesAsync();
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{ {
duplicates.Add(name); if (aliases.Exists(item => item.Name == name))
}
}
if (duplicates.Count == 0)
{
InstallConfig config = new InstallConfig();
if (_tenantid == "+")
{
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
{ {
// validate host credentials duplicates.Add(name);
var user = new User(); }
user.SiteId = PageState.Site.SiteId; }
user.Username = _hostusername;
user.Password = _hostpassword;
user = await UserService.LoginUserAsync(user, false, false);
if (user.IsAuthenticated)
{
var connectionString = String.Empty;
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
{
connectionString = databaseConfigControl.GetConnectionString();
}
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
if (connectionString != "") if (duplicates.Count == 0)
{
InstallConfig config = new InstallConfig();
if (_tenantid == "+")
{
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
{
// validate host credentials
var user = new User();
user.SiteId = PageState.Site.SiteId;
user.Username = UserNames.Host;
user.Password = _hostpassword;
user = await UserService.LoginUserAsync(user, false, false);
if (user.IsAuthenticated)
{ {
config.TenantName = _tenantName; var connectionString = String.Empty;
config.DatabaseType = database.DBType; if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
config.ConnectionString = connectionString; {
config.HostUsername = _hostusername; connectionString = databaseConfigControl.GetConnectionString();
config.HostPassword = _hostpassword; }
config.HostEmail = user.Email; var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
config.HostName = user.DisplayName;
config.IsNewTenant = true; if (connectionString != "")
{
config.TenantName = _tenantName;
config.DatabaseType = database.DBType;
config.ConnectionString = connectionString;
config.HostEmail = user.Email;
config.HostPassword = _hostpassword;
config.HostName = user.DisplayName;
config.IsNewTenant = true;
}
else
{
AddModuleMessage(Localizer["Error.Required.ServerDatabase"], MessageType.Error);
}
} }
else else
{ {
AddModuleMessage(Localizer["Error.Required.ServerDatabase"], MessageType.Error); AddModuleMessage(Localizer["Error.InvalidPassword"], MessageType.Error);
} }
} }
else else
{ {
AddModuleMessage(Localizer["Error.InvalidPassword"], MessageType.Error); AddModuleMessage(Localizer["Error.TenantName.Exists"], MessageType.Error);
} }
} }
else else
{ {
AddModuleMessage(Localizer["Error.TenantName.Exists"], MessageType.Error); var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid));
if (tenant != null)
{
config.TenantName = tenant.Name;
config.DatabaseType = tenant.DBType;
config.ConnectionString = tenant.DBConnectionString;
config.IsNewTenant = false;
}
}
if (!string.IsNullOrEmpty(config.TenantName))
{
config.SiteName = _name;
config.Aliases = _urls;
config.DefaultTheme = _themetype;
config.DefaultContainer = _containertype;
config.DefaultAdminContainer = _admincontainertype;
config.SiteTemplate = _sitetemplatetype;
ShowProgressIndicator();
var installation = await InstallationService.Install(config);
if (installation.Success)
{
var aliasname = config.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
var uri = new Uri(NavigationManager.Uri);
NavigationManager.NavigateTo(uri.Scheme + "://" + aliasname, true);
}
else
{
await logger.LogError("Error Creating Site {Error}", installation.Message);
AddModuleMessage(installation.Message, MessageType.Error);
}
} }
} }
else else
{ {
var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); AddModuleMessage(string.Format(Localizer["Message.SiteName.InUse"], string.Join(", ", duplicates.ToArray())), MessageType.Warning);
if (tenant != null)
{
config.TenantName = tenant.Name;
config.DatabaseType = tenant.DBType;
config.ConnectionString = tenant.DBConnectionString;
config.IsNewTenant = false;
}
}
if (!string.IsNullOrEmpty(config.TenantName))
{
config.SiteName = _name;
config.Aliases = _urls;
config.DefaultTheme = _themetype;
config.DefaultContainer = _containertype;
config.DefaultAdminContainer = _admincontainertype;
config.SiteTemplate = _sitetemplatetype;
ShowProgressIndicator();
var installation = await InstallationService.Install(config);
if (installation.Success)
{
var aliasname = config.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
var uri = new Uri(NavigationManager.Uri);
NavigationManager.NavigateTo(uri.Scheme + "://" + aliasname, true);
}
else
{
await logger.LogError("Error Creating Site {Error}", installation.Message);
AddModuleMessage(installation.Message, MessageType.Error);
}
} }
} }
else else
{ {
AddModuleMessage(string.Format(Localizer["Message.SiteName.InUse"], string.Join(", ", duplicates.ToArray())), MessageType.Warning); AddModuleMessage(Localizer["Message.Required.Tenant"], MessageType.Warning);
} }
} }
else else
{ {
AddModuleMessage(Localizer["Message.Required.Tenant"], MessageType.Warning); AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
} }
} }
} }